about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorJohannes Hoff <johshoff@gmail.com>2014-12-24 13:22:11 +0100
committerJohannes Hoff <johshoff@gmail.com>2014-12-24 13:22:11 +0100
commit0128159c95d0544e0c30b8b52ce3e7ce348fc114 (patch)
tree8af4db0f2758f86434b895169122a9962fb79b21 /src/libstd
parent8f827d33cab1be648120fc8ac34651d9cc079b5e (diff)
parente64a8193b02ce72ef183274994a25eae281cb89c (diff)
downloadrust-0128159c95d0544e0c30b8b52ce3e7ce348fc114.tar.gz
rust-0128159c95d0544e0c30b8b52ce3e7ce348fc114.zip
Merge branch 'master' into cfg_tmp_dir
Conflicts:
	src/etc/rustup.sh
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/ascii.rs180
-rw-r--r--src/libstd/bitflags.rs69
-rw-r--r--src/libstd/bool.rs15
-rw-r--r--src/libstd/c_str.rs844
-rw-r--r--src/libstd/c_vec.rs39
-rw-r--r--src/libstd/collections/hash/map.rs846
-rw-r--r--src/libstd/collections/hash/set.rs390
-rw-r--r--src/libstd/collections/hash/table.rs80
-rw-r--r--src/libstd/collections/lru_cache.rs470
-rw-r--r--src/libstd/collections/mod.rs39
-rw-r--r--src/libstd/comm/blocking.rs83
-rw-r--r--src/libstd/comm/mod.rs2028
-rw-r--r--src/libstd/comm/mpsc_queue.rs201
-rw-r--r--src/libstd/comm/oneshot.rs375
-rw-r--r--src/libstd/comm/select.rs721
-rw-r--r--src/libstd/comm/shared.rs486
-rw-r--r--src/libstd/comm/spsc_queue.rs337
-rw-r--r--src/libstd/comm/stream.rs484
-rw-r--r--src/libstd/comm/sync.rs475
-rw-r--r--src/libstd/dynamic_lib.rs56
-rw-r--r--src/libstd/error.rs17
-rw-r--r--src/libstd/failure.rs104
-rw-r--r--src/libstd/fmt.rs786
-rw-r--r--src/libstd/hash.rs106
-rw-r--r--src/libstd/io/buffered.rs88
-rw-r--r--src/libstd/io/comm_adapters.rs29
-rw-r--r--src/libstd/io/extensions.rs22
-rw-r--r--src/libstd/io/fs.rs185
-rw-r--r--src/libstd/io/mem.rs178
-rw-r--r--src/libstd/io/mod.rs495
-rw-r--r--src/libstd/io/net/addrinfo.rs22
-rw-r--r--src/libstd/io/net/ip.rs79
-rw-r--r--src/libstd/io/net/mod.rs11
-rw-r--r--src/libstd/io/net/pipe.rs111
-rw-r--r--src/libstd/io/net/tcp.rs173
-rw-r--r--src/libstd/io/net/udp.rs41
-rw-r--r--src/libstd/io/pipe.rs6
-rw-r--r--src/libstd/io/process.rs54
-rw-r--r--src/libstd/io/result.rs2
-rw-r--r--src/libstd/io/stdio.rs266
-rw-r--r--src/libstd/io/tempfile.rs61
-rw-r--r--src/libstd/io/test.rs15
-rw-r--r--src/libstd/io/timer.rs24
-rw-r--r--src/libstd/io/util.rs22
-rw-r--r--src/libstd/lib.rs62
-rw-r--r--src/libstd/macros.rs184
-rw-r--r--src/libstd/num/f32.rs44
-rw-r--r--src/libstd/num/f64.rs42
-rw-r--r--src/libstd/num/float_macros.rs4
-rw-r--r--src/libstd/num/i16.rs2
-rw-r--r--src/libstd/num/i32.rs2
-rw-r--r--src/libstd/num/i64.rs2
-rw-r--r--src/libstd/num/i8.rs2
-rw-r--r--src/libstd/num/int.rs4
-rw-r--r--src/libstd/num/int_macros.rs4
-rw-r--r--src/libstd/num/mod.rs94
-rw-r--r--src/libstd/num/strconv.rs169
-rw-r--r--src/libstd/num/u16.rs4
-rw-r--r--src/libstd/num/u32.rs4
-rw-r--r--src/libstd/num/u64.rs4
-rw-r--r--src/libstd/num/u8.rs4
-rw-r--r--src/libstd/num/uint.rs6
-rw-r--r--src/libstd/num/uint_macros.rs24
-rw-r--r--src/libstd/os.rs668
-rw-r--r--src/libstd/path/mod.rs142
-rw-r--r--src/libstd/path/posix.rs235
-rw-r--r--src/libstd/path/windows.rs377
-rw-r--r--src/libstd/prelude.rs29
-rw-r--r--src/libstd/rand/mod.rs52
-rw-r--r--src/libstd/rand/os.rs43
-rw-r--r--src/libstd/rand/reader.rs4
-rw-r--r--src/libstd/rt/args.rs166
-rw-r--r--src/libstd/rt/at_exit_imp.rs75
-rw-r--r--src/libstd/rt/backtrace.rs991
-rw-r--r--src/libstd/rt/exclusive.rs115
-rw-r--r--src/libstd/rt/libunwind.rs128
-rw-r--r--src/libstd/rt/macros.rs45
-rw-r--r--src/libstd/rt/mod.rs215
-rw-r--r--src/libstd/rt/task.rs554
-rw-r--r--src/libstd/rt/unwind.rs613
-rw-r--r--src/libstd/rt/util.rs143
-rw-r--r--src/libstd/rtdeps.rs2
-rw-r--r--src/libstd/sync/atomic.rs225
-rw-r--r--src/libstd/sync/barrier.rs117
-rw-r--r--src/libstd/sync/condvar.rs365
-rw-r--r--src/libstd/sync/future.rs104
-rw-r--r--src/libstd/sync/mod.rs24
-rw-r--r--src/libstd/sync/mutex.rs433
-rw-r--r--src/libstd/sync/once.rs170
-rw-r--r--src/libstd/sync/poison.rs38
-rw-r--r--src/libstd/sync/rwlock.rs514
-rw-r--r--src/libstd/sync/semaphore.rs195
-rw-r--r--src/libstd/sync/task_pool.rs40
-rw-r--r--src/libstd/sys/common/backtrace.rs136
-rw-r--r--src/libstd/sys/common/condvar.rs67
-rw-r--r--src/libstd/sys/common/helper_thread.rs40
-rw-r--r--src/libstd/sys/common/mod.rs23
-rw-r--r--src/libstd/sys/common/mutex.rs62
-rw-r--r--src/libstd/sys/common/net.rs53
-rw-r--r--src/libstd/sys/common/rwlock.rs86
-rw-r--r--src/libstd/sys/common/stack.rs325
-rw-r--r--src/libstd/sys/common/thread.rs35
-rw-r--r--src/libstd/sys/common/thread_info.rs68
-rw-r--r--src/libstd/sys/common/thread_local.rs284
-rw-r--r--src/libstd/sys/unix/backtrace.rs493
-rw-r--r--src/libstd/sys/unix/condvar.rs83
-rw-r--r--src/libstd/sys/unix/ext.rs107
-rw-r--r--src/libstd/sys/unix/fs.rs19
-rw-r--r--src/libstd/sys/unix/mod.rs28
-rw-r--r--src/libstd/sys/unix/mutex.rs52
-rw-r--r--src/libstd/sys/unix/os.rs137
-rw-r--r--src/libstd/sys/unix/pipe.rs22
-rw-r--r--src/libstd/sys/unix/process.rs79
-rw-r--r--src/libstd/sys/unix/rwlock.rs57
-rw-r--r--src/libstd/sys/unix/stack_overflow.rs277
-rw-r--r--src/libstd/sys/unix/sync.rs208
-rw-r--r--src/libstd/sys/unix/tcp.rs17
-rw-r--r--src/libstd/sys/unix/thread.rs271
-rw-r--r--src/libstd/sys/unix/thread_local.rs52
-rw-r--r--src/libstd/sys/unix/timer.rs4
-rw-r--r--src/libstd/sys/windows/backtrace.rs371
-rw-r--r--src/libstd/sys/windows/c.rs14
-rw-r--r--src/libstd/sys/windows/condvar.rs62
-rw-r--r--src/libstd/sys/windows/ext.rs100
-rw-r--r--src/libstd/sys/windows/fs.rs26
-rw-r--r--src/libstd/sys/windows/mod.rs25
-rw-r--r--src/libstd/sys/windows/mutex.rs78
-rw-r--r--src/libstd/sys/windows/os.rs238
-rw-r--r--src/libstd/sys/windows/pipe.rs17
-rw-r--r--src/libstd/sys/windows/process.rs70
-rw-r--r--src/libstd/sys/windows/rwlock.rs53
-rw-r--r--src/libstd/sys/windows/stack_overflow.rs115
-rw-r--r--src/libstd/sys/windows/sync.rs58
-rw-r--r--src/libstd/sys/windows/tcp.rs45
-rw-r--r--src/libstd/sys/windows/thread.rs96
-rw-r--r--src/libstd/sys/windows/thread_local.rs259
-rw-r--r--src/libstd/sys/windows/timer.rs4
-rw-r--r--src/libstd/sys/windows/tty.rs4
-rw-r--r--src/libstd/task.rs525
-rw-r--r--src/libstd/thread.rs654
-rw-r--r--src/libstd/thread_local/mod.rs653
-rw-r--r--src/libstd/thread_local/scoped.rs264
-rw-r--r--src/libstd/thunk.rs55
-rw-r--r--src/libstd/time/duration.rs82
-rw-r--r--src/libstd/tuple.rs66
-rw-r--r--src/libstd/unit.rs45
146 files changed, 20157 insertions, 5505 deletions
diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs
index 933794cb5a4..6c213555ce4 100644
--- a/src/libstd/ascii.rs
+++ b/src/libstd/ascii.rs
@@ -12,49 +12,69 @@
 
 //! Operations on ASCII strings and characters
 
-#![experimental]
+#![unstable = "unsure about placement and naming"]
+#![allow(deprecated)]
 
 use core::kinds::Sized;
 use fmt;
-use iter::Iterator;
+use iter::IteratorExt;
 use mem;
-use option::{Option, Some, None};
-use slice::{SlicePrelude, AsSlice};
-use str::{Str, StrPrelude};
-use string::{mod, String, IntoString};
+use ops::FnMut;
+use option::Option;
+use option::Option::{Some, None};
+use slice::{SliceExt, AsSlice};
+use str::{Str, StrExt};
+use string::{String, IntoString};
 use vec::Vec;
 
 /// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero.
-#[deriving(Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
+#[deriving(Clone, Copy, PartialEq, PartialOrd, Ord, Eq, Hash)]
 pub struct Ascii { chr: u8 }
 
 impl Ascii {
     /// Converts an ascii character into a `u8`.
     #[inline]
-    pub fn to_byte(self) -> u8 {
+    #[unstable = "recently renamed"]
+    pub fn as_byte(&self) -> u8 {
         self.chr
     }
 
+    /// Deprecated: use `as_byte` instead.
+    #[deprecated = "use as_byte"]
+    pub fn to_byte(self) -> u8 {
+        self.as_byte()
+    }
+
     /// Converts an ascii character into a `char`.
     #[inline]
-    pub fn to_char(self) -> char {
+    #[unstable = "recently renamed"]
+    pub fn as_char(&self) -> char {
         self.chr as char
     }
 
+    /// Deprecated: use `as_char` instead.
+    #[deprecated = "use as_char"]
+    pub fn to_char(self) -> char {
+        self.as_char()
+    }
+
     /// Convert to lowercase.
     #[inline]
-    pub fn to_lowercase(self) -> Ascii {
+    #[stable]
+    pub fn to_lowercase(&self) -> Ascii {
         Ascii{chr: ASCII_LOWER_MAP[self.chr as uint]}
     }
 
     /// Convert to uppercase.
     #[inline]
-    pub fn to_uppercase(self) -> Ascii {
+    #[stable]
+    pub fn to_uppercase(&self) -> Ascii {
         Ascii{chr: ASCII_UPPER_MAP[self.chr as uint]}
     }
 
     /// Compares two ascii characters of equality, ignoring case.
     #[inline]
+    #[deprecated = "normalize with to_lowercase"]
     pub fn eq_ignore_case(self, other: Ascii) -> bool {
         ASCII_LOWER_MAP[self.chr as uint] == ASCII_LOWER_MAP[other.chr as uint]
     }
@@ -63,66 +83,77 @@ impl Ascii {
 
     /// Check if the character is a letter (a-z, A-Z)
     #[inline]
+    #[stable]
     pub fn is_alphabetic(&self) -> bool {
         (self.chr >= 0x41 && self.chr <= 0x5A) || (self.chr >= 0x61 && self.chr <= 0x7A)
     }
 
     /// Check if the character is a number (0-9)
     #[inline]
+    #[unstable = "may be renamed"]
     pub fn is_digit(&self) -> bool {
         self.chr >= 0x30 && self.chr <= 0x39
     }
 
     /// Check if the character is a letter or number
     #[inline]
+    #[stable]
     pub fn is_alphanumeric(&self) -> bool {
         self.is_alphabetic() || self.is_digit()
     }
 
     /// Check if the character is a space or horizontal tab
     #[inline]
+    #[experimental = "likely to be removed"]
     pub fn is_blank(&self) -> bool {
         self.chr == b' ' || self.chr == b'\t'
     }
 
     /// Check if the character is a control character
     #[inline]
+    #[stable]
     pub fn is_control(&self) -> bool {
         self.chr < 0x20 || self.chr == 0x7F
     }
 
     /// Checks if the character is printable (except space)
     #[inline]
+    #[experimental = "unsure about naming, or whether this is needed"]
     pub fn is_graph(&self) -> bool {
         (self.chr - 0x21) < 0x5E
     }
 
     /// Checks if the character is printable (including space)
     #[inline]
+    #[unstable = "unsure about naming"]
     pub fn is_print(&self) -> bool {
         (self.chr - 0x20) < 0x5F
     }
 
-    /// Checks if the character is lowercase
+    /// Checks if the character is alphabetic and lowercase
     #[inline]
+    #[stable]
     pub fn is_lowercase(&self) -> bool {
         (self.chr - b'a') < 26
     }
 
-    /// Checks if the character is uppercase
+    /// Checks if the character is alphabetic and uppercase
     #[inline]
+    #[stable]
     pub fn is_uppercase(&self) -> bool {
         (self.chr - b'A') < 26
     }
 
     /// Checks if the character is punctuation
     #[inline]
+    #[stable]
     pub fn is_punctuation(&self) -> bool {
         self.is_graph() && !self.is_alphanumeric()
     }
 
     /// Checks if the character is a valid hex digit
     #[inline]
+    #[stable]
     pub fn is_hex(&self) -> bool {
         self.is_digit() || ((self.chr | 32u8) - b'a') < 6
     }
@@ -135,7 +166,8 @@ impl<'a> fmt::Show for Ascii {
 }
 
 /// Trait for converting into an ascii type.
-pub trait AsciiCast<T> {
+#[experimental = "may be replaced by generic conversion traits"]
+pub trait AsciiCast<T> for Sized? {
     /// Convert to an ascii type, panic on non-ASCII input.
     #[inline]
     fn to_ascii(&self) -> T {
@@ -160,10 +192,11 @@ pub trait AsciiCast<T> {
     fn is_ascii(&self) -> bool;
 }
 
-impl<'a> AsciiCast<&'a[Ascii]> for &'a [u8] {
+#[experimental = "may be replaced by generic conversion traits"]
+impl<'a> AsciiCast<&'a[Ascii]> for [u8] {
     #[inline]
     unsafe fn to_ascii_nocheck(&self) -> &'a[Ascii] {
-        mem::transmute(*self)
+        mem::transmute(self)
     }
 
     #[inline]
@@ -175,10 +208,11 @@ impl<'a> AsciiCast<&'a[Ascii]> for &'a [u8] {
     }
 }
 
-impl<'a> AsciiCast<&'a [Ascii]> for &'a str {
+#[experimental = "may be replaced by generic conversion traits"]
+impl<'a> AsciiCast<&'a [Ascii]> for str {
     #[inline]
     unsafe fn to_ascii_nocheck(&self) -> &'a [Ascii] {
-        mem::transmute(*self)
+        mem::transmute(self)
     }
 
     #[inline]
@@ -187,6 +221,7 @@ impl<'a> AsciiCast<&'a [Ascii]> for &'a str {
     }
 }
 
+#[experimental = "may be replaced by generic conversion traits"]
 impl AsciiCast<Ascii> for u8 {
     #[inline]
     unsafe fn to_ascii_nocheck(&self) -> Ascii {
@@ -199,6 +234,7 @@ impl AsciiCast<Ascii> for u8 {
     }
 }
 
+#[experimental = "may be replaced by generic conversion traits"]
 impl AsciiCast<Ascii> for char {
     #[inline]
     unsafe fn to_ascii_nocheck(&self) -> Ascii {
@@ -212,6 +248,7 @@ impl AsciiCast<Ascii> for char {
 }
 
 /// Trait for copyless casting to an ascii vector.
+#[experimental = "may be replaced by generic conversion traits"]
 pub trait OwnedAsciiCast {
     /// Check if convertible to ascii
     fn is_ascii(&self) -> bool;
@@ -241,6 +278,7 @@ pub trait OwnedAsciiCast {
     unsafe fn into_ascii_nocheck(self) -> Vec<Ascii>;
 }
 
+#[experimental = "may be replaced by generic conversion traits"]
 impl OwnedAsciiCast for String {
     #[inline]
     fn is_ascii(&self) -> bool {
@@ -253,6 +291,7 @@ impl OwnedAsciiCast for String {
     }
 }
 
+#[experimental = "may be replaced by generic conversion traits"]
 impl OwnedAsciiCast for Vec<u8> {
     #[inline]
     fn is_ascii(&self) -> bool {
@@ -274,6 +313,7 @@ impl OwnedAsciiCast for Vec<u8> {
 
 /// Trait for converting an ascii type to a string. Needed to convert
 /// `&[Ascii]` to `&str`.
+#[experimental = "may be replaced by generic conversion traits"]
 pub trait AsciiStr for Sized? {
     /// Convert to a string.
     fn as_str_ascii<'a>(&'a self) -> &'a str;
@@ -283,6 +323,7 @@ pub trait AsciiStr for Sized? {
     fn to_lower(&self) -> Vec<Ascii>;
 
     /// Convert to vector representing a lower cased ascii string.
+    #[deprecated = "use iterators instead"]
     fn to_lowercase(&self) -> Vec<Ascii>;
 
     /// Deprecated: use `to_uppercase`
@@ -290,12 +331,15 @@ pub trait AsciiStr for Sized? {
     fn to_upper(&self) -> Vec<Ascii>;
 
     /// Convert to vector representing a upper cased ascii string.
+    #[deprecated = "use iterators instead"]
     fn to_uppercase(&self) -> Vec<Ascii>;
 
     /// Compares two Ascii strings ignoring case.
+    #[deprecated = "use iterators instead"]
     fn eq_ignore_case(&self, other: &[Ascii]) -> bool;
 }
 
+#[experimental = "may be replaced by generic conversion traits"]
 impl AsciiStr for [Ascii] {
     #[inline]
     fn as_str_ascii<'a>(&'a self) -> &'a str {
@@ -331,18 +375,18 @@ impl AsciiStr for [Ascii] {
 impl IntoString for Vec<Ascii> {
     #[inline]
     fn into_string(self) -> String {
-        unsafe {
-            string::raw::from_utf8(self.into_bytes())
-        }
+        unsafe { String::from_utf8_unchecked(self.into_bytes()) }
     }
 }
 
 /// Trait to convert to an owned byte vector by consuming self
+#[experimental = "may be replaced by generic conversion traits"]
 pub trait IntoBytes {
     /// Converts to an owned byte vector by consuming self
     fn into_bytes(self) -> Vec<u8>;
 }
 
+#[experimental = "may be replaced by generic conversion traits"]
 impl IntoBytes for Vec<Ascii> {
     fn into_bytes(self) -> Vec<u8> {
         unsafe {
@@ -360,6 +404,7 @@ impl IntoBytes for Vec<Ascii> {
 
 
 /// Extension methods for ASCII-subset only operations on owned strings
+#[experimental = "would prefer to do this in a more general way"]
 pub trait OwnedAsciiExt {
     /// Convert the string to ASCII upper case:
     /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
@@ -373,6 +418,7 @@ pub trait OwnedAsciiExt {
 }
 
 /// Extension methods for ASCII-subset only operations on string slices
+#[experimental = "would prefer to do this in a more general way"]
 pub trait AsciiExt<T> for Sized? {
     /// Makes a copy of the string in ASCII upper case:
     /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
@@ -390,17 +436,18 @@ pub trait AsciiExt<T> for Sized? {
     fn eq_ignore_ascii_case(&self, other: &Self) -> bool;
 }
 
+#[experimental = "would prefer to do this in a more general way"]
 impl AsciiExt<String> for str {
     #[inline]
     fn to_ascii_upper(&self) -> String {
         // Vec<u8>::to_ascii_upper() preserves the UTF-8 invariant.
-        unsafe { string::raw::from_utf8(self.as_bytes().to_ascii_upper()) }
+        unsafe { String::from_utf8_unchecked(self.as_bytes().to_ascii_upper()) }
     }
 
     #[inline]
     fn to_ascii_lower(&self) -> String {
         // Vec<u8>::to_ascii_lower() preserves the UTF-8 invariant.
-        unsafe { string::raw::from_utf8(self.as_bytes().to_ascii_lower()) }
+        unsafe { String::from_utf8_unchecked(self.as_bytes().to_ascii_lower()) }
     }
 
     #[inline]
@@ -409,20 +456,22 @@ impl AsciiExt<String> for str {
     }
 }
 
+#[experimental = "would prefer to do this in a more general way"]
 impl OwnedAsciiExt for String {
     #[inline]
     fn into_ascii_upper(self) -> String {
         // Vec<u8>::into_ascii_upper() preserves the UTF-8 invariant.
-        unsafe { string::raw::from_utf8(self.into_bytes().into_ascii_upper()) }
+        unsafe { String::from_utf8_unchecked(self.into_bytes().into_ascii_upper()) }
     }
 
     #[inline]
     fn into_ascii_lower(self) -> String {
         // Vec<u8>::into_ascii_lower() preserves the UTF-8 invariant.
-        unsafe { string::raw::from_utf8(self.into_bytes().into_ascii_lower()) }
+        unsafe { String::from_utf8_unchecked(self.into_bytes().into_ascii_lower()) }
     }
 }
 
+#[experimental = "would prefer to do this in a more general way"]
 impl AsciiExt<Vec<u8>> for [u8] {
     #[inline]
     fn to_ascii_upper(&self) -> Vec<u8> {
@@ -445,6 +494,7 @@ impl AsciiExt<Vec<u8>> for [u8] {
     }
 }
 
+#[experimental = "would prefer to do this in a more general way"]
 impl OwnedAsciiExt for Vec<u8> {
     #[inline]
     fn into_ascii_upper(mut self) -> Vec<u8> {
@@ -474,7 +524,10 @@ impl OwnedAsciiExt for Vec<u8> {
 /// - Any other chars in the range [0x20,0x7e] are not escaped.
 /// - Any other chars are given hex escapes.
 /// - Unicode escapes are never generated by this function.
-pub fn escape_default(c: u8, f: |u8|) {
+#[unstable = "needs to be updated to use an iterator"]
+pub fn escape_default<F>(c: u8, mut f: F) where
+    F: FnMut(u8),
+{
     match c {
         b'\t' => { f(b'\\'); f(b't'); }
         b'\r' => { f(b'\\'); f(b'r'); }
@@ -496,7 +549,7 @@ pub fn escape_default(c: u8, f: |u8|) {
     }
 }
 
-pub static ASCII_LOWER_MAP: [u8, ..256] = [
+static ASCII_LOWER_MAP: [u8, ..256] = [
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
@@ -535,7 +588,7 @@ pub static ASCII_LOWER_MAP: [u8, ..256] = [
     0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
 ];
 
-pub static ASCII_UPPER_MAP: [u8, ..256] = [
+static ASCII_UPPER_MAP: [u8, ..256] = [
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
@@ -580,16 +633,15 @@ mod tests {
     use prelude::*;
     use super::*;
     use char::from_u32;
-    use str::StrPrelude;
 
-    macro_rules! v2ascii (
+    macro_rules! v2ascii {
         ( [$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
         (&[$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
-    )
+    }
 
-    macro_rules! vec2ascii (
+    macro_rules! vec2ascii {
         ($($e:expr),*) => ([$(Ascii{chr:$e}),*].to_vec());
-    )
+    }
 
     #[test]
     fn test_ascii() {
@@ -628,33 +680,33 @@ mod tests {
         assert_eq!(test.to_ascii(), b);
         assert_eq!("( ;".to_ascii(), b);
         let v = vec![40u8, 32u8, 59u8];
-        assert_eq!(v.as_slice().to_ascii(), b);
-        assert_eq!("( ;".to_string().as_slice().to_ascii(), b);
+        assert_eq!(v.to_ascii(), b);
+        assert_eq!("( ;".to_string().to_ascii(), b);
 
-        assert_eq!("abCDef&?#".to_ascii().to_lowercase().into_string(), "abcdef&?#".to_string());
-        assert_eq!("abCDef&?#".to_ascii().to_uppercase().into_string(), "ABCDEF&?#".to_string());
+        assert_eq!("abCDef&?#".to_ascii().to_lowercase().into_string(), "abcdef&?#");
+        assert_eq!("abCDef&?#".to_ascii().to_uppercase().into_string(), "ABCDEF&?#");
 
-        assert_eq!("".to_ascii().to_lowercase().into_string(), "".to_string());
-        assert_eq!("YMCA".to_ascii().to_lowercase().into_string(), "ymca".to_string());
+        assert_eq!("".to_ascii().to_lowercase().into_string(), "");
+        assert_eq!("YMCA".to_ascii().to_lowercase().into_string(), "ymca");
         let mixed = "abcDEFxyz:.;".to_ascii();
-        assert_eq!(mixed.to_uppercase().into_string(), "ABCDEFXYZ:.;".to_string());
+        assert_eq!(mixed.to_uppercase().into_string(), "ABCDEFXYZ:.;");
 
         assert!("aBcDeF&?#".to_ascii().eq_ignore_case("AbCdEf&?#".to_ascii()));
 
         assert!("".is_ascii());
         assert!("a".is_ascii());
-        assert!(!"\u2009".is_ascii());
+        assert!(!"\u{2009}".is_ascii());
 
     }
 
     #[test]
     fn test_ascii_vec_ng() {
-        assert_eq!("abCDef&?#".to_ascii().to_lowercase().into_string(), "abcdef&?#".to_string());
-        assert_eq!("abCDef&?#".to_ascii().to_uppercase().into_string(), "ABCDEF&?#".to_string());
-        assert_eq!("".to_ascii().to_lowercase().into_string(), "".to_string());
-        assert_eq!("YMCA".to_ascii().to_lowercase().into_string(), "ymca".to_string());
+        assert_eq!("abCDef&?#".to_ascii().to_lowercase().into_string(), "abcdef&?#");
+        assert_eq!("abCDef&?#".to_ascii().to_uppercase().into_string(), "ABCDEF&?#");
+        assert_eq!("".to_ascii().to_lowercase().into_string(), "");
+        assert_eq!("YMCA".to_ascii().to_lowercase().into_string(), "ymca");
         let mixed = "abcDEFxyz:.;".to_ascii();
-        assert_eq!(mixed.to_uppercase().into_string(), "ABCDEFXYZ:.;".to_string());
+        assert_eq!(mixed.to_uppercase().into_string(), "ABCDEFXYZ:.;");
     }
 
     #[test]
@@ -671,8 +723,8 @@ mod tests {
 
     #[test]
     fn test_ascii_into_string() {
-        assert_eq!(vec2ascii![40, 32, 59].into_string(), "( ;".to_string());
-        assert_eq!(vec2ascii!(40, 32, 59).into_string(), "( ;".to_string());
+        assert_eq!(vec2ascii![40, 32, 59].into_string(), "( ;");
+        assert_eq!(vec2ascii!(40, 32, 59).into_string(), "( ;");
     }
 
     #[test]
@@ -724,31 +776,31 @@ mod tests {
 
     #[test]
     fn test_to_ascii_upper() {
-        assert_eq!("url()URL()uRl()ürl".to_ascii_upper(), "URL()URL()URL()üRL".to_string());
-        assert_eq!("hıKß".to_ascii_upper(), "HıKß".to_string());
+        assert_eq!("url()URL()uRl()ürl".to_ascii_upper(), "URL()URL()URL()üRL");
+        assert_eq!("hıKß".to_ascii_upper(), "HıKß");
 
         let mut i = 0;
         while i <= 500 {
             let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
                         else { i };
-            assert_eq!((from_u32(i).unwrap()).to_string().as_slice().to_ascii_upper(),
-                       (from_u32(upper).unwrap()).to_string())
+            assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_upper(),
+                       (from_u32(upper).unwrap()).to_string());
             i += 1;
         }
     }
 
     #[test]
     fn test_to_ascii_lower() {
-        assert_eq!("url()URL()uRl()Ürl".to_ascii_lower(), "url()url()url()Ürl".to_string());
+        assert_eq!("url()URL()uRl()Ürl".to_ascii_lower(), "url()url()url()Ürl");
         // Dotted capital I, Kelvin sign, Sharp S.
-        assert_eq!("HİKß".to_ascii_lower(), "hİKß".to_string());
+        assert_eq!("HİKß".to_ascii_lower(), "hİKß");
 
         let mut i = 0;
         while i <= 500 {
             let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
                         else { i };
-            assert_eq!((from_u32(i).unwrap()).to_string().as_slice().to_ascii_lower(),
-                       (from_u32(lower).unwrap()).to_string())
+            assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_lower(),
+                       (from_u32(lower).unwrap()).to_string());
             i += 1;
         }
     }
@@ -757,14 +809,14 @@ mod tests {
     fn test_into_ascii_upper() {
         assert_eq!(("url()URL()uRl()ürl".to_string()).into_ascii_upper(),
                    "URL()URL()URL()üRL".to_string());
-        assert_eq!(("hıKß".to_string()).into_ascii_upper(), "HıKß".to_string());
+        assert_eq!(("hıKß".to_string()).into_ascii_upper(), "HıKß");
 
         let mut i = 0;
         while i <= 500 {
             let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
                         else { i };
             assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_upper(),
-                       (from_u32(upper).unwrap()).to_string())
+                       (from_u32(upper).unwrap()).to_string());
             i += 1;
         }
     }
@@ -772,16 +824,16 @@ mod tests {
     #[test]
     fn test_into_ascii_lower() {
         assert_eq!(("url()URL()uRl()Ürl".to_string()).into_ascii_lower(),
-                   "url()url()url()Ürl".to_string());
+                   "url()url()url()Ürl");
         // Dotted capital I, Kelvin sign, Sharp S.
-        assert_eq!(("HİKß".to_string()).into_ascii_lower(), "hİKß".to_string());
+        assert_eq!(("HİKß".to_string()).into_ascii_lower(), "hİKß");
 
         let mut i = 0;
         while i <= 500 {
             let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
                         else { i };
             assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_lower(),
-                       (from_u32(lower).unwrap()).to_string())
+                       (from_u32(lower).unwrap()).to_string());
             i += 1;
         }
     }
@@ -801,7 +853,7 @@ mod tests {
             let c = i;
             let lower = if 'A' as u32 <= c && c <= 'Z' as u32 { c + 'a' as u32 - 'A' as u32 }
                         else { c };
-            assert!((from_u32(i).unwrap()).to_string().as_slice().eq_ignore_ascii_case(
+            assert!((from_u32(i).unwrap()).to_string().eq_ignore_ascii_case(
                     (from_u32(lower).unwrap()).to_string().as_slice()));
             i += 1;
         }
@@ -810,12 +862,12 @@ mod tests {
     #[test]
     fn test_to_string() {
         let s = Ascii{ chr: b't' }.to_string();
-        assert_eq!(s, "t".to_string());
+        assert_eq!(s, "t");
     }
 
     #[test]
     fn test_show() {
         let c = Ascii { chr: b't' };
-        assert_eq!(format!("{}", c), "t".to_string());
+        assert_eq!(format!("{}", c), "t");
     }
 }
diff --git a/src/libstd/bitflags.rs b/src/libstd/bitflags.rs
index d8023dd3e4e..5dd76047779 100644
--- a/src/libstd/bitflags.rs
+++ b/src/libstd/bitflags.rs
@@ -24,9 +24,9 @@
 /// ```{.rust}
 /// bitflags! {
 ///     flags Flags: u32 {
-///         const FLAG_A       = 0x00000001,
-///         const FLAG_B       = 0x00000010,
-///         const FLAG_C       = 0x00000100,
+///         const FLAG_A       = 0b00000001,
+///         const FLAG_B       = 0b00000010,
+///         const FLAG_C       = 0b00000100,
 ///         const FLAG_ABC     = FLAG_A.bits
 ///                            | FLAG_B.bits
 ///                            | FLAG_C.bits,
@@ -50,8 +50,8 @@
 ///
 /// bitflags! {
 ///     flags Flags: u32 {
-///         const FLAG_A   = 0x00000001,
-///         const FLAG_B   = 0x00000010,
+///         const FLAG_A   = 0b00000001,
+///         const FLAG_B   = 0b00000010,
 ///     }
 /// }
 ///
@@ -117,7 +117,7 @@ macro_rules! bitflags {
     ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
         $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+
     }) => {
-        #[deriving(PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
+        #[deriving(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
         $(#[$attr])*
         pub struct $BitFlags {
             bits: $T,
@@ -149,9 +149,9 @@ macro_rules! bitflags {
             #[inline]
             pub fn from_bits(bits: $T) -> ::std::option::Option<$BitFlags> {
                 if (bits & !$BitFlags::all().bits()) != 0 {
-                    ::std::option::None
+                    ::std::option::Option::None
                 } else {
-                    ::std::option::Some($BitFlags { bits: bits })
+                    ::std::option::Option::Some($BitFlags { bits: bits })
                 }
             }
 
@@ -208,7 +208,7 @@ macro_rules! bitflags {
         impl BitOr<$BitFlags, $BitFlags> for $BitFlags {
             /// Returns the union of the two sets of flags.
             #[inline]
-            fn bitor(&self, other: &$BitFlags) -> $BitFlags {
+            fn bitor(self, other: $BitFlags) -> $BitFlags {
                 $BitFlags { bits: self.bits | other.bits }
             }
         }
@@ -216,7 +216,7 @@ macro_rules! bitflags {
         impl BitXor<$BitFlags, $BitFlags> for $BitFlags {
             /// Returns the left flags, but with all the right flags toggled.
             #[inline]
-            fn bitxor(&self, other: &$BitFlags) -> $BitFlags {
+            fn bitxor(self, other: $BitFlags) -> $BitFlags {
                 $BitFlags { bits: self.bits ^ other.bits }
             }
         }
@@ -224,7 +224,7 @@ macro_rules! bitflags {
         impl BitAnd<$BitFlags, $BitFlags> for $BitFlags {
             /// Returns the intersection between the two sets of flags.
             #[inline]
-            fn bitand(&self, other: &$BitFlags) -> $BitFlags {
+            fn bitand(self, other: $BitFlags) -> $BitFlags {
                 $BitFlags { bits: self.bits & other.bits }
             }
         }
@@ -232,11 +232,13 @@ macro_rules! bitflags {
         impl Sub<$BitFlags, $BitFlags> for $BitFlags {
             /// Returns the set difference of the two sets of flags.
             #[inline]
-            fn sub(&self, other: &$BitFlags) -> $BitFlags {
+            fn sub(self, other: $BitFlags) -> $BitFlags {
                 $BitFlags { bits: self.bits & !other.bits }
             }
         }
 
+        // NOTE(stage0): Remove impl after a snapshot
+        #[cfg(stage0)]
         impl Not<$BitFlags> for $BitFlags {
             /// Returns the complement of this set of flags.
             #[inline]
@@ -244,6 +246,15 @@ macro_rules! bitflags {
                 $BitFlags { bits: !self.bits } & $BitFlags::all()
             }
         }
+
+        #[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
+        impl Not<$BitFlags> for $BitFlags {
+            /// Returns the complement of this set of flags.
+            #[inline]
+            fn not(self) -> $BitFlags {
+                $BitFlags { bits: !self.bits } & $BitFlags::all()
+            }
+        }
     };
     ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
         $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+,
@@ -261,7 +272,7 @@ macro_rules! bitflags {
 #[allow(non_upper_case_globals)]
 mod tests {
     use hash;
-    use option::{Some, None};
+    use option::Option::{Some, None};
     use ops::{BitOr, BitAnd, BitXor, Sub, Not};
 
     bitflags! {
@@ -270,10 +281,10 @@ mod tests {
         #[doc = "> "]
         #[doc = "> - Richard Feynman"]
         flags Flags: u32 {
-            const FlagA       = 0x00000001,
+            const FlagA       = 0b00000001,
             #[doc = "<pcwalton> macros are way better at generating code than trans is"]
-            const FlagB       = 0x00000010,
-            const FlagC       = 0x00000100,
+            const FlagB       = 0b00000010,
+            const FlagC       = 0b00000100,
             #[doc = "* cmr bed"]
             #[doc = "* strcat table"]
             #[doc = "<strcat> wait what?"]
@@ -291,21 +302,21 @@ mod tests {
 
     #[test]
     fn test_bits(){
-        assert_eq!(Flags::empty().bits(), 0x00000000);
-        assert_eq!(FlagA.bits(), 0x00000001);
-        assert_eq!(FlagABC.bits(), 0x00000111);
+        assert_eq!(Flags::empty().bits(), 0b00000000);
+        assert_eq!(FlagA.bits(), 0b00000001);
+        assert_eq!(FlagABC.bits(), 0b00000111);
 
-        assert_eq!(AnotherSetOfFlags::empty().bits(), 0x00);
+        assert_eq!(AnotherSetOfFlags::empty().bits(), 0b00);
         assert_eq!(AnotherFlag.bits(), !0_i8);
     }
 
     #[test]
     fn test_from_bits() {
         assert!(Flags::from_bits(0) == Some(Flags::empty()));
-        assert!(Flags::from_bits(0x1) == Some(FlagA));
-        assert!(Flags::from_bits(0x10) == Some(FlagB));
-        assert!(Flags::from_bits(0x11) == Some(FlagA | FlagB));
-        assert!(Flags::from_bits(0x1000) == None);
+        assert!(Flags::from_bits(0b1) == Some(FlagA));
+        assert!(Flags::from_bits(0b10) == Some(FlagB));
+        assert!(Flags::from_bits(0b11) == Some(FlagA | FlagB));
+        assert!(Flags::from_bits(0b1000) == None);
 
         assert!(AnotherSetOfFlags::from_bits(!0_i8) == Some(AnotherFlag));
     }
@@ -313,11 +324,11 @@ mod tests {
     #[test]
     fn test_from_bits_truncate() {
         assert!(Flags::from_bits_truncate(0) == Flags::empty());
-        assert!(Flags::from_bits_truncate(0x1) == FlagA);
-        assert!(Flags::from_bits_truncate(0x10) == FlagB);
-        assert!(Flags::from_bits_truncate(0x11) == (FlagA | FlagB));
-        assert!(Flags::from_bits_truncate(0x1000) == Flags::empty());
-        assert!(Flags::from_bits_truncate(0x1001) == FlagA);
+        assert!(Flags::from_bits_truncate(0b1) == FlagA);
+        assert!(Flags::from_bits_truncate(0b10) == FlagB);
+        assert!(Flags::from_bits_truncate(0b11) == (FlagA | FlagB));
+        assert!(Flags::from_bits_truncate(0b1000) == Flags::empty());
+        assert!(Flags::from_bits_truncate(0b1001) == FlagA);
 
         assert!(AnotherSetOfFlags::from_bits_truncate(0_i8) == AnotherSetOfFlags::empty());
     }
diff --git a/src/libstd/bool.rs b/src/libstd/bool.rs
new file mode 100644
index 00000000000..bbaab5ee3db
--- /dev/null
+++ b/src/libstd/bool.rs
@@ -0,0 +1,15 @@
+// Copyright 2013 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.
+
+//! The boolean type
+
+#![doc(primitive = "bool")]
+#![stable]
+
diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs
new file mode 100644
index 00000000000..fb44961017f
--- /dev/null
+++ b/src/libstd/c_str.rs
@@ -0,0 +1,844 @@
+// Copyright 2012 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.
+
+//! C-string manipulation and management
+//!
+//! This modules provides the basic methods for creating and manipulating
+//! null-terminated strings for use with FFI calls (back to C). Most C APIs require
+//! that the string being passed to them is null-terminated, and by default rust's
+//! string types are *not* null terminated.
+//!
+//! The other problem with translating Rust strings to C strings is that Rust
+//! strings can validly contain a null-byte in the middle of the string (0 is a
+//! valid Unicode codepoint). This means that not all Rust strings can actually be
+//! translated to C strings.
+//!
+//! # Creation of a C string
+//!
+//! A C string is managed through the `CString` type defined in this module. It
+//! "owns" the internal buffer of characters and will automatically deallocate the
+//! buffer when the string is dropped. The `ToCStr` trait is implemented for `&str`
+//! and `&[u8]`, but the conversions can fail due to some of the limitations
+//! explained above.
+//!
+//! This also means that currently whenever a C string is created, an allocation
+//! must be performed to place the data elsewhere (the lifetime of the C string is
+//! not tied to the lifetime of the original string/data buffer). If C strings are
+//! heavily used in applications, then caching may be advisable to prevent
+//! unnecessary amounts of allocations.
+//!
+//! Be carefull to remember that the memory is managed by C allocator API and not
+//! by Rust allocator API.
+//! That means that the CString pointers should be freed with C allocator API
+//! if you intend to do that on your own, as the behaviour if you free them with
+//! Rust's allocator API is not well defined
+//!
+//! An example of creating and using a C string would be:
+//!
+//! ```rust
+//! extern crate libc;
+//!
+//! extern {
+//!     fn puts(s: *const libc::c_char);
+//! }
+//!
+//! fn main() {
+//!     let my_string = "Hello, world!";
+//!
+//!     // Allocate the C string with an explicit local that owns the string. The
+//!     // `c_buffer` pointer will be deallocated when `my_c_string` goes out of scope.
+//!     let my_c_string = my_string.to_c_str();
+//!     unsafe {
+//!         puts(my_c_string.as_ptr());
+//!     }
+//!
+//!     // Don't save/return the pointer to the C string, the `c_buffer` will be
+//!     // deallocated when this block returns!
+//!     my_string.with_c_str(|c_buffer| {
+//!         unsafe { puts(c_buffer); }
+//!     });
+//! }
+//! ```
+
+use core::prelude::*;
+use libc;
+
+use fmt;
+use hash;
+use kinds::marker;
+use mem;
+use ptr;
+use slice::{mod, ImmutableIntSlice};
+use str;
+use string::String;
+
+
+/// The representation of a C String.
+///
+/// This structure wraps a `*libc::c_char`, and will automatically free the
+/// memory it is pointing to when it goes out of scope.
+#[allow(missing_copy_implementations)]
+pub struct CString {
+    buf: *const libc::c_char,
+    owns_buffer_: bool,
+}
+
+impl Clone for CString {
+    /// Clone this CString into a new, uniquely owned CString. For safety
+    /// reasons, this is always a deep clone with the memory allocated
+    /// with C's allocator API, rather than the usual shallow clone.
+    fn clone(&self) -> CString {
+        let len = self.len() + 1;
+        let buf = unsafe { libc::malloc(len as libc::size_t) } as *mut libc::c_char;
+        if buf.is_null() { ::alloc::oom() }
+        unsafe { ptr::copy_nonoverlapping_memory(buf, self.buf, len); }
+        CString { buf: buf as *const libc::c_char, owns_buffer_: true }
+    }
+}
+
+impl PartialEq for CString {
+    fn eq(&self, other: &CString) -> bool {
+        // Check if the two strings share the same buffer
+        if self.buf as uint == other.buf as uint {
+            true
+        } else {
+            unsafe {
+                libc::strcmp(self.buf, other.buf) == 0
+            }
+        }
+    }
+}
+
+impl PartialOrd for CString {
+    #[inline]
+    fn partial_cmp(&self, other: &CString) -> Option<Ordering> {
+        self.as_bytes().partial_cmp(other.as_bytes())
+    }
+}
+
+impl Eq for CString {}
+
+impl<S: hash::Writer> hash::Hash<S> for CString {
+    #[inline]
+    fn hash(&self, state: &mut S) {
+        self.as_bytes().hash(state)
+    }
+}
+
+impl CString {
+    /// Create a C String from a pointer, with memory managed by C's allocator
+    /// API, so avoid calling it with a pointer to memory managed by Rust's
+    /// allocator API, as the behaviour would not be well defined.
+    ///
+    ///# Panics
+    ///
+    /// Panics if `buf` is null
+    pub unsafe fn new(buf: *const libc::c_char, owns_buffer: bool) -> CString {
+        assert!(!buf.is_null());
+        CString { buf: buf, owns_buffer_: owns_buffer }
+    }
+
+    /// Return a pointer to the NUL-terminated string data.
+    ///
+    /// `.as_ptr` returns an internal pointer into the `CString`, and
+    /// may be invalidated when the `CString` falls out of scope (the
+    /// destructor will run, freeing the allocation if there is
+    /// one).
+    ///
+    /// ```rust
+    /// let foo = "some string";
+    ///
+    /// // right
+    /// let x = foo.to_c_str();
+    /// let p = x.as_ptr();
+    ///
+    /// // wrong (the CString will be freed, invalidating `p`)
+    /// let p = foo.to_c_str().as_ptr();
+    /// ```
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// extern crate libc;
+    ///
+    /// fn main() {
+    ///     let c_str = "foo bar".to_c_str();
+    ///     unsafe {
+    ///         libc::puts(c_str.as_ptr());
+    ///     }
+    /// }
+    /// ```
+    pub fn as_ptr(&self) -> *const libc::c_char {
+        self.buf
+    }
+
+    /// Return a mutable pointer to the NUL-terminated string data.
+    ///
+    /// `.as_mut_ptr` returns an internal pointer into the `CString`, and
+    /// may be invalidated when the `CString` falls out of scope (the
+    /// destructor will run, freeing the allocation if there is
+    /// one).
+    ///
+    /// ```rust
+    /// let foo = "some string";
+    ///
+    /// // right
+    /// let mut x = foo.to_c_str();
+    /// let p = x.as_mut_ptr();
+    ///
+    /// // wrong (the CString will be freed, invalidating `p`)
+    /// let p = foo.to_c_str().as_mut_ptr();
+    /// ```
+    pub fn as_mut_ptr(&mut self) -> *mut libc::c_char {
+        self.buf as *mut _
+    }
+
+    /// Returns whether or not the `CString` owns the buffer.
+    pub fn owns_buffer(&self) -> bool {
+        self.owns_buffer_
+    }
+
+    /// Converts the CString into a `&[u8]` without copying.
+    /// Includes the terminating NUL byte.
+    #[inline]
+    pub fn as_bytes<'a>(&'a self) -> &'a [u8] {
+        unsafe {
+            slice::from_raw_buf(&self.buf, self.len() + 1).as_unsigned()
+        }
+    }
+
+    /// Converts the CString into a `&[u8]` without copying.
+    /// Does not include the terminating NUL byte.
+    #[inline]
+    pub fn as_bytes_no_nul<'a>(&'a self) -> &'a [u8] {
+        unsafe {
+            slice::from_raw_buf(&self.buf, self.len()).as_unsigned()
+        }
+    }
+
+    /// Converts the CString into a `&str` without copying.
+    /// Returns None if the CString is not UTF-8.
+    #[inline]
+    pub fn as_str<'a>(&'a self) -> Option<&'a str> {
+        let buf = self.as_bytes_no_nul();
+        str::from_utf8(buf).ok()
+    }
+
+    /// Return a CString iterator.
+    pub fn iter<'a>(&'a self) -> CChars<'a> {
+        CChars {
+            ptr: self.buf,
+            marker: marker::ContravariantLifetime,
+        }
+    }
+
+    /// Unwraps the wrapped `*libc::c_char` from the `CString` wrapper.
+    ///
+    /// Any ownership of the buffer by the `CString` wrapper is
+    /// forgotten, meaning that the backing allocation of this
+    /// `CString` is not automatically freed if it owns the
+    /// allocation. In this case, a user of `.unwrap()` should ensure
+    /// the allocation is freed, to avoid leaking memory. You should
+    /// use libc's memory allocator in this case.
+    ///
+    /// Prefer `.as_ptr()` when just retrieving a pointer to the
+    /// string data, as that does not relinquish ownership.
+    pub unsafe fn into_inner(mut self) -> *const libc::c_char {
+        self.owns_buffer_ = false;
+        self.buf
+    }
+
+    /// Deprecated, use into_inner() instead
+    #[deprecated = "renamed to into_inner()"]
+    pub unsafe fn unwrap(self) -> *const libc::c_char { self.into_inner() }
+
+    /// Return the number of bytes in the CString (not including the NUL
+    /// terminator).
+    #[inline]
+    pub fn len(&self) -> uint {
+        unsafe { libc::strlen(self.buf) as uint }
+    }
+
+    /// Returns if there are no bytes in this string
+    #[inline]
+    pub fn is_empty(&self) -> bool { self.len() == 0 }
+}
+
+impl Drop for CString {
+    fn drop(&mut self) {
+        if self.owns_buffer_ {
+            unsafe {
+                libc::free(self.buf as *mut libc::c_void)
+            }
+        }
+    }
+}
+
+impl fmt::Show for CString {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        String::from_utf8_lossy(self.as_bytes_no_nul()).fmt(f)
+    }
+}
+
+/// A generic trait for converting a value to a CString.
+pub trait ToCStr for Sized? {
+    /// Copy the receiver into a CString.
+    ///
+    /// # Panics
+    ///
+    /// Panics the task if the receiver has an interior null.
+    fn to_c_str(&self) -> CString;
+
+    /// Unsafe variant of `to_c_str()` that doesn't check for nulls.
+    unsafe fn to_c_str_unchecked(&self) -> CString;
+
+    /// Work with a temporary CString constructed from the receiver.
+    /// The provided `*libc::c_char` will be freed immediately upon return.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// extern crate libc;
+    ///
+    /// fn main() {
+    ///     let s = "PATH".with_c_str(|path| unsafe {
+    ///         libc::getenv(path)
+    ///     });
+    /// }
+    /// ```
+    ///
+    /// # Panics
+    ///
+    /// Panics the task if the receiver has an interior null.
+    #[inline]
+    fn with_c_str<T, F>(&self, f: F) -> T where
+        F: FnOnce(*const libc::c_char) -> T,
+    {
+        let c_str = self.to_c_str();
+        f(c_str.as_ptr())
+    }
+
+    /// Unsafe variant of `with_c_str()` that doesn't check for nulls.
+    #[inline]
+    unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
+        F: FnOnce(*const libc::c_char) -> T,
+    {
+        let c_str = self.to_c_str_unchecked();
+        f(c_str.as_ptr())
+    }
+}
+
+impl ToCStr for str {
+    #[inline]
+    fn to_c_str(&self) -> CString {
+        self.as_bytes().to_c_str()
+    }
+
+    #[inline]
+    unsafe fn to_c_str_unchecked(&self) -> CString {
+        self.as_bytes().to_c_str_unchecked()
+    }
+
+    #[inline]
+    fn with_c_str<T, F>(&self, f: F) -> T where
+        F: FnOnce(*const libc::c_char) -> T,
+    {
+        self.as_bytes().with_c_str(f)
+    }
+
+    #[inline]
+    unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
+        F: FnOnce(*const libc::c_char) -> T,
+    {
+        self.as_bytes().with_c_str_unchecked(f)
+    }
+}
+
+impl ToCStr for String {
+    #[inline]
+    fn to_c_str(&self) -> CString {
+        self.as_bytes().to_c_str()
+    }
+
+    #[inline]
+    unsafe fn to_c_str_unchecked(&self) -> CString {
+        self.as_bytes().to_c_str_unchecked()
+    }
+
+    #[inline]
+    fn with_c_str<T, F>(&self, f: F) -> T where
+        F: FnOnce(*const libc::c_char) -> T,
+    {
+        self.as_bytes().with_c_str(f)
+    }
+
+    #[inline]
+    unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
+        F: FnOnce(*const libc::c_char) -> T,
+    {
+        self.as_bytes().with_c_str_unchecked(f)
+    }
+}
+
+// The length of the stack allocated buffer for `vec.with_c_str()`
+const BUF_LEN: uint = 128;
+
+impl ToCStr for [u8] {
+    fn to_c_str(&self) -> CString {
+        let mut cs = unsafe { self.to_c_str_unchecked() };
+        check_for_null(self, cs.as_mut_ptr());
+        cs
+    }
+
+    unsafe fn to_c_str_unchecked(&self) -> CString {
+        let self_len = self.len();
+        let buf = libc::malloc(self_len as libc::size_t + 1) as *mut u8;
+        if buf.is_null() { ::alloc::oom() }
+
+        ptr::copy_memory(buf, self.as_ptr(), self_len);
+        *buf.offset(self_len as int) = 0;
+
+        CString::new(buf as *const libc::c_char, true)
+    }
+
+    fn with_c_str<T, F>(&self, f: F) -> T where
+        F: FnOnce(*const libc::c_char) -> T,
+    {
+        unsafe { with_c_str(self, true, f) }
+    }
+
+    unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
+        F: FnOnce(*const libc::c_char) -> T,
+    {
+        with_c_str(self, false, f)
+    }
+}
+
+impl<'a, Sized? T: ToCStr> ToCStr for &'a T {
+    #[inline]
+    fn to_c_str(&self) -> CString {
+        (**self).to_c_str()
+    }
+
+    #[inline]
+    unsafe fn to_c_str_unchecked(&self) -> CString {
+        (**self).to_c_str_unchecked()
+    }
+
+    #[inline]
+    fn with_c_str<T, F>(&self, f: F) -> T where
+        F: FnOnce(*const libc::c_char) -> T,
+    {
+        (**self).with_c_str(f)
+    }
+
+    #[inline]
+    unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
+        F: FnOnce(*const libc::c_char) -> T,
+    {
+        (**self).with_c_str_unchecked(f)
+    }
+}
+
+// Unsafe function that handles possibly copying the &[u8] into a stack array.
+unsafe fn with_c_str<T, F>(v: &[u8], checked: bool, f: F) -> T where
+    F: FnOnce(*const libc::c_char) -> T,
+{
+    let c_str = if v.len() < BUF_LEN {
+        let mut buf: [u8, .. BUF_LEN] = mem::uninitialized();
+        slice::bytes::copy_memory(&mut buf, v);
+        buf[v.len()] = 0;
+
+        let buf = buf.as_mut_ptr();
+        if checked {
+            check_for_null(v, buf as *mut libc::c_char);
+        }
+
+        return f(buf as *const libc::c_char)
+    } else if checked {
+        v.to_c_str()
+    } else {
+        v.to_c_str_unchecked()
+    };
+
+    f(c_str.as_ptr())
+}
+
+#[inline]
+fn check_for_null(v: &[u8], buf: *mut libc::c_char) {
+    for i in range(0, v.len()) {
+        unsafe {
+            let p = buf.offset(i as int);
+            assert!(*p != 0);
+        }
+    }
+}
+
+/// External iterator for a CString's bytes.
+///
+/// Use with the `std::iter` module.
+pub struct CChars<'a> {
+    ptr: *const libc::c_char,
+    marker: marker::ContravariantLifetime<'a>,
+}
+
+impl<'a> Iterator<libc::c_char> for CChars<'a> {
+    fn next(&mut self) -> Option<libc::c_char> {
+        let ch = unsafe { *self.ptr };
+        if ch == 0 {
+            None
+        } else {
+            self.ptr = unsafe { self.ptr.offset(1) };
+            Some(ch)
+        }
+    }
+}
+
+/// Parses a C "multistring", eg windows env values or
+/// the req->ptr result in a uv_fs_readdir() call.
+///
+/// Optionally, a `count` can be passed in, limiting the
+/// parsing to only being done `count`-times.
+///
+/// The specified closure is invoked with each string that
+/// is found, and the number of strings found is returned.
+pub unsafe fn from_c_multistring<F>(buf: *const libc::c_char,
+                                    count: Option<uint>,
+                                    mut f: F)
+                                    -> uint where
+    F: FnMut(&CString),
+{
+
+    let mut curr_ptr: uint = buf as uint;
+    let mut ctr = 0;
+    let (limited_count, limit) = match count {
+        Some(limit) => (true, limit),
+        None => (false, 0)
+    };
+    while ((limited_count && ctr < limit) || !limited_count)
+          && *(curr_ptr as *const libc::c_char) != 0 as libc::c_char {
+        let cstr = CString::new(curr_ptr as *const libc::c_char, false);
+        f(&cstr);
+        curr_ptr += cstr.len() + 1;
+        ctr += 1;
+    }
+    return ctr;
+}
+
+#[cfg(test)]
+mod tests {
+    use prelude::*;
+    use ptr;
+    use thread::Thread;
+    use libc;
+
+    use super::*;
+
+    #[test]
+    fn test_str_multistring_parsing() {
+        unsafe {
+            let input = b"zero\0one\0\0";
+            let ptr = input.as_ptr();
+            let expected = ["zero", "one"];
+            let mut it = expected.iter();
+            let result = from_c_multistring(ptr as *const libc::c_char, None, |c| {
+                let cbytes = c.as_bytes_no_nul();
+                assert_eq!(cbytes, it.next().unwrap().as_bytes());
+            });
+            assert_eq!(result, 2);
+            assert!(it.next().is_none());
+        }
+    }
+
+    #[test]
+    fn test_str_to_c_str() {
+        let c_str = "".to_c_str();
+        unsafe {
+            assert_eq!(*c_str.as_ptr().offset(0), 0);
+        }
+
+        let c_str = "hello".to_c_str();
+        let buf = c_str.as_ptr();
+        unsafe {
+            assert_eq!(*buf.offset(0), 'h' as libc::c_char);
+            assert_eq!(*buf.offset(1), 'e' as libc::c_char);
+            assert_eq!(*buf.offset(2), 'l' as libc::c_char);
+            assert_eq!(*buf.offset(3), 'l' as libc::c_char);
+            assert_eq!(*buf.offset(4), 'o' as libc::c_char);
+            assert_eq!(*buf.offset(5), 0);
+        }
+    }
+
+    #[test]
+    fn test_vec_to_c_str() {
+        let b: &[u8] = &[];
+        let c_str = b.to_c_str();
+        unsafe {
+            assert_eq!(*c_str.as_ptr().offset(0), 0);
+        }
+
+        let c_str = b"hello".to_c_str();
+        let buf = c_str.as_ptr();
+        unsafe {
+            assert_eq!(*buf.offset(0), 'h' as libc::c_char);
+            assert_eq!(*buf.offset(1), 'e' as libc::c_char);
+            assert_eq!(*buf.offset(2), 'l' as libc::c_char);
+            assert_eq!(*buf.offset(3), 'l' as libc::c_char);
+            assert_eq!(*buf.offset(4), 'o' as libc::c_char);
+            assert_eq!(*buf.offset(5), 0);
+        }
+
+        let c_str = b"foo\xFF".to_c_str();
+        let buf = c_str.as_ptr();
+        unsafe {
+            assert_eq!(*buf.offset(0), 'f' as libc::c_char);
+            assert_eq!(*buf.offset(1), 'o' as libc::c_char);
+            assert_eq!(*buf.offset(2), 'o' as libc::c_char);
+            assert_eq!(*buf.offset(3), 0xffu8 as libc::c_char);
+            assert_eq!(*buf.offset(4), 0);
+        }
+    }
+
+    #[test]
+    fn test_unwrap() {
+        let c_str = "hello".to_c_str();
+        unsafe { libc::free(c_str.unwrap() as *mut libc::c_void) }
+    }
+
+    #[test]
+    fn test_as_ptr() {
+        let c_str = "hello".to_c_str();
+        let len = unsafe { libc::strlen(c_str.as_ptr()) };
+        assert_eq!(len, 5);
+    }
+
+    #[test]
+    fn test_iterator() {
+        let c_str = "".to_c_str();
+        let mut iter = c_str.iter();
+        assert_eq!(iter.next(), None);
+
+        let c_str = "hello".to_c_str();
+        let mut iter = c_str.iter();
+        assert_eq!(iter.next(), Some('h' as libc::c_char));
+        assert_eq!(iter.next(), Some('e' as libc::c_char));
+        assert_eq!(iter.next(), Some('l' as libc::c_char));
+        assert_eq!(iter.next(), Some('l' as libc::c_char));
+        assert_eq!(iter.next(), Some('o' as libc::c_char));
+        assert_eq!(iter.next(), None);
+    }
+
+    #[test]
+    fn test_to_c_str_fail() {
+        assert!(Thread::spawn(move|| { "he\x00llo".to_c_str() }).join().is_err());
+    }
+
+    #[test]
+    fn test_to_c_str_unchecked() {
+        unsafe {
+            let c_string = "he\x00llo".to_c_str_unchecked();
+            let buf = c_string.as_ptr();
+            assert_eq!(*buf.offset(0), 'h' as libc::c_char);
+            assert_eq!(*buf.offset(1), 'e' as libc::c_char);
+            assert_eq!(*buf.offset(2), 0);
+            assert_eq!(*buf.offset(3), 'l' as libc::c_char);
+            assert_eq!(*buf.offset(4), 'l' as libc::c_char);
+            assert_eq!(*buf.offset(5), 'o' as libc::c_char);
+            assert_eq!(*buf.offset(6), 0);
+        }
+    }
+
+    #[test]
+    fn test_as_bytes() {
+        let c_str = "hello".to_c_str();
+        assert_eq!(c_str.as_bytes(), b"hello\0");
+        let c_str = "".to_c_str();
+        assert_eq!(c_str.as_bytes(), b"\0");
+        let c_str = b"foo\xFF".to_c_str();
+        assert_eq!(c_str.as_bytes(), b"foo\xFF\0");
+    }
+
+    #[test]
+    fn test_as_bytes_no_nul() {
+        let c_str = "hello".to_c_str();
+        assert_eq!(c_str.as_bytes_no_nul(), b"hello");
+        let c_str = "".to_c_str();
+        let exp: &[u8] = &[];
+        assert_eq!(c_str.as_bytes_no_nul(), exp);
+        let c_str = b"foo\xFF".to_c_str();
+        assert_eq!(c_str.as_bytes_no_nul(), b"foo\xFF");
+    }
+
+    #[test]
+    fn test_as_str() {
+        let c_str = "hello".to_c_str();
+        assert_eq!(c_str.as_str(), Some("hello"));
+        let c_str = "".to_c_str();
+        assert_eq!(c_str.as_str(), Some(""));
+        let c_str = b"foo\xFF".to_c_str();
+        assert_eq!(c_str.as_str(), None);
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_new_fail() {
+        let _c_str = unsafe { CString::new(ptr::null(), false) };
+    }
+
+    #[test]
+    fn test_clone() {
+        let a = "hello".to_c_str();
+        let b = a.clone();
+        assert!(a == b);
+    }
+
+    #[test]
+    fn test_clone_noleak() {
+        fn foo<F>(f: F) where F: FnOnce(&CString) {
+            let s = "test".to_string();
+            let c = s.to_c_str();
+            // give the closure a non-owned CString
+            let mut c_ = unsafe { CString::new(c.as_ptr(), false) };
+            f(&c_);
+            // muck with the buffer for later printing
+            unsafe { *c_.as_mut_ptr() = 'X' as libc::c_char }
+        }
+
+        let mut c_: Option<CString> = None;
+        foo(|c| {
+            c_ = Some(c.clone());
+            c.clone();
+            // force a copy, reading the memory
+            c.as_bytes().to_vec();
+        });
+        let c_ = c_.unwrap();
+        // force a copy, reading the memory
+        c_.as_bytes().to_vec();
+    }
+}
+
+#[cfg(test)]
+mod bench {
+    extern crate test;
+
+    use self::test::Bencher;
+    use libc;
+    use prelude::*;
+
+    #[inline]
+    fn check(s: &str, c_str: *const libc::c_char) {
+        let s_buf = s.as_ptr();
+        for i in range(0, s.len()) {
+            unsafe {
+                assert_eq!(
+                    *s_buf.offset(i as int) as libc::c_char,
+                    *c_str.offset(i as int));
+            }
+        }
+    }
+
+    static S_SHORT: &'static str = "Mary";
+    static S_MEDIUM: &'static str = "Mary had a little lamb";
+    static S_LONG: &'static str = "\
+        Mary had a little lamb, Little lamb
+        Mary had a little lamb, Little lamb
+        Mary had a little lamb, Little lamb
+        Mary had a little lamb, Little lamb
+        Mary had a little lamb, Little lamb
+        Mary had a little lamb, Little lamb";
+
+    fn bench_to_string(b: &mut Bencher, s: &str) {
+        b.iter(|| {
+            let c_str = s.to_c_str();
+            check(s, c_str.as_ptr());
+        })
+    }
+
+    #[bench]
+    fn bench_to_c_str_short(b: &mut Bencher) {
+        bench_to_string(b, S_SHORT)
+    }
+
+    #[bench]
+    fn bench_to_c_str_medium(b: &mut Bencher) {
+        bench_to_string(b, S_MEDIUM)
+    }
+
+    #[bench]
+    fn bench_to_c_str_long(b: &mut Bencher) {
+        bench_to_string(b, S_LONG)
+    }
+
+    fn bench_to_c_str_unchecked(b: &mut Bencher, s: &str) {
+        b.iter(|| {
+            let c_str = unsafe { s.to_c_str_unchecked() };
+            check(s, c_str.as_ptr())
+        })
+    }
+
+    #[bench]
+    fn bench_to_c_str_unchecked_short(b: &mut Bencher) {
+        bench_to_c_str_unchecked(b, S_SHORT)
+    }
+
+    #[bench]
+    fn bench_to_c_str_unchecked_medium(b: &mut Bencher) {
+        bench_to_c_str_unchecked(b, S_MEDIUM)
+    }
+
+    #[bench]
+    fn bench_to_c_str_unchecked_long(b: &mut Bencher) {
+        bench_to_c_str_unchecked(b, S_LONG)
+    }
+
+    fn bench_with_c_str(b: &mut Bencher, s: &str) {
+        b.iter(|| {
+            s.with_c_str(|c_str_buf| check(s, c_str_buf))
+        })
+    }
+
+    #[bench]
+    fn bench_with_c_str_short(b: &mut Bencher) {
+        bench_with_c_str(b, S_SHORT)
+    }
+
+    #[bench]
+    fn bench_with_c_str_medium(b: &mut Bencher) {
+        bench_with_c_str(b, S_MEDIUM)
+    }
+
+    #[bench]
+    fn bench_with_c_str_long(b: &mut Bencher) {
+        bench_with_c_str(b, S_LONG)
+    }
+
+    fn bench_with_c_str_unchecked(b: &mut Bencher, s: &str) {
+        b.iter(|| {
+            unsafe {
+                s.with_c_str_unchecked(|c_str_buf| check(s, c_str_buf))
+            }
+        })
+    }
+
+    #[bench]
+    fn bench_with_c_str_unchecked_short(b: &mut Bencher) {
+        bench_with_c_str_unchecked(b, S_SHORT)
+    }
+
+    #[bench]
+    fn bench_with_c_str_unchecked_medium(b: &mut Bencher) {
+        bench_with_c_str_unchecked(b, S_MEDIUM)
+    }
+
+    #[bench]
+    fn bench_with_c_str_unchecked_long(b: &mut Bencher) {
+        bench_with_c_str_unchecked(b, S_LONG)
+    }
+}
diff --git a/src/libstd/c_vec.rs b/src/libstd/c_vec.rs
index 1267d7411cc..44e7291150e 100644
--- a/src/libstd/c_vec.rs
+++ b/src/libstd/c_vec.rs
@@ -37,18 +37,20 @@
 
 use kinds::Send;
 use mem;
-use ops::Drop;
-use option::{Option, Some, None};
+use ops::{Drop, FnOnce};
+use option::Option;
+use option::Option::{Some, None};
 use ptr::RawPtr;
 use ptr;
 use raw;
 use slice::AsSlice;
+use thunk::{Thunk};
 
 /// The type representing a foreign chunk of memory
 pub struct CVec<T> {
     base: *mut T,
     len: uint,
-    dtor: Option<proc():Send>,
+    dtor: Option<Thunk>,
 }
 
 #[unsafe_destructor]
@@ -56,7 +58,7 @@ impl<T> Drop for CVec<T> {
     fn drop(&mut self) {
         match self.dtor.take() {
             None => (),
-            Some(f) => f()
+            Some(f) => f.invoke(())
         }
     }
 }
@@ -89,15 +91,20 @@ impl<T> CVec<T> {
     ///
     /// * base - A foreign pointer to a buffer
     /// * len - The number of elements in the buffer
-    /// * dtor - A proc to run when the value is destructed, useful
+    /// * dtor - A fn to run when the value is destructed, useful
     ///          for freeing the buffer, etc.
-    pub unsafe fn new_with_dtor(base: *mut T, len: uint,
-                                dtor: proc():Send) -> CVec<T> {
+    pub unsafe fn new_with_dtor<F>(base: *mut T,
+                                   len: uint,
+                                   dtor: F)
+                                   -> CVec<T>
+        where F : FnOnce(), F : Send
+    {
         assert!(base != ptr::null_mut());
+        let dtor: Thunk = Thunk::new(dtor);
         CVec {
             base: base,
             len: len,
-            dtor: Some(dtor),
+            dtor: Some(dtor)
         }
     }
 
@@ -138,11 +145,15 @@ impl<T> CVec<T> {
     /// Note that if you want to access the underlying pointer without
     /// cancelling the destructor, you can simply call `transmute` on the return
     /// value of `get(0)`.
-    pub unsafe fn unwrap(mut self) -> *mut T {
+    pub unsafe fn into_inner(mut self) -> *mut T {
         self.dtor = None;
         self.base
     }
 
+    /// Deprecated, use into_inner() instead
+    #[deprecated = "renamed to into_inner()"]
+    pub unsafe fn unwrap(self) -> *mut T { self.into_inner() }
+
     /// Returns the number of items in this vector.
     pub fn len(&self) -> uint { self.len }
 
@@ -172,8 +183,9 @@ mod tests {
             let mem = libc::malloc(n as libc::size_t);
             if mem.is_null() { ::alloc::oom() }
 
-            CVec::new_with_dtor(mem as *mut u8, n,
-                proc() { libc::free(mem as *mut libc::c_void); })
+            CVec::new_with_dtor(mem as *mut u8,
+                                n,
+                                move|| { libc::free(mem as *mut libc::c_void); })
         }
     }
 
@@ -213,8 +225,9 @@ mod tests {
     #[test]
     fn test_unwrap() {
         unsafe {
-            let cv = CVec::new_with_dtor(1 as *mut int, 0,
-                proc() { panic!("Don't run this destructor!") });
+            let cv = CVec::new_with_dtor(1 as *mut int,
+                                         0,
+                                         move|:| panic!("Don't run this destructor!"));
             let p = cv.unwrap();
             assert_eq!(p, 1 as *mut int);
         }
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 69375e8d4f8..d749cd77cef 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -10,7 +10,7 @@
 //
 // ignore-lexer-test FIXME #15883
 
-pub use self::Entry::*;
+use self::Entry::*;
 use self::SearchResult::*;
 use self::VacantEntryState::*;
 
@@ -20,66 +20,78 @@ use cmp::{max, Eq, Equiv, PartialEq};
 use default::Default;
 use fmt::{mod, Show};
 use hash::{Hash, Hasher, RandomSipHasher};
-use iter::{mod, Iterator, FromIterator, Extend};
+use iter::{mod, Iterator, IteratorExt, FromIterator, Extend, Map};
 use kinds::Sized;
 use mem::{mod, replace};
-use num::UnsignedInt;
-use ops::{Deref, Index, IndexMut};
-use option::{Some, None, Option};
-use result::{Result, Ok, Err};
+use num::{Int, UnsignedInt};
+use ops::{Deref, FnMut, Index, IndexMut};
+use option::Option;
+use option::Option::{Some, None};
+use result::Result;
+use result::Result::{Ok, Err};
 
-use super::table;
 use super::table::{
+    mod,
     Bucket,
-    Empty,
     EmptyBucket,
-    Full,
     FullBucket,
     FullBucketImm,
     FullBucketMut,
     RawTable,
     SafeHash
 };
-
-// FIXME(conventions): update capacity management to match other collections (no auto-shrink)
+use super::table::BucketState::{
+    Empty,
+    Full,
+};
 
 const INITIAL_LOG2_CAP: uint = 5;
 pub const INITIAL_CAPACITY: uint = 1 << INITIAL_LOG2_CAP; // 2^5
 
 /// The default behavior of HashMap implements a load factor of 90.9%.
-/// This behavior is characterized by the following conditions:
+/// This behavior is characterized by the following condition:
 ///
-/// - if size > 0.909 * capacity: grow
-/// - if size < 0.25 * capacity: shrink (if this won't bring capacity lower
-///   than the minimum)
+/// - if size > 0.909 * capacity: grow the map
 #[deriving(Clone)]
-struct DefaultResizePolicy {
-    /// Doubled minimal capacity. The capacity must never drop below
-    /// the minimum capacity. (The check happens before the capacity
-    /// is potentially halved.)
-    minimum_capacity2: uint
-}
+struct DefaultResizePolicy;
 
 impl DefaultResizePolicy {
-    fn new(new_capacity: uint) -> DefaultResizePolicy {
-        DefaultResizePolicy {
-            minimum_capacity2: new_capacity << 1
-        }
+    fn new() -> DefaultResizePolicy {
+        DefaultResizePolicy
     }
 
     #[inline]
-    fn capacity_range(&self, new_size: uint) -> (uint, uint) {
-        // Here, we are rephrasing the logic by specifying the ranges:
+    fn min_capacity(&self, usable_size: uint) -> uint {
+        // Here, we are rephrasing the logic by specifying the lower limit
+        // on capacity:
         //
-        // - if `size * 1.1 < cap < size * 4`: don't resize
-        // - if `cap < minimum_capacity * 2`: don't shrink
-        // - otherwise, resize accordingly
-        ((new_size * 11) / 10, max(new_size << 2, self.minimum_capacity2))
+        // - if `cap < size * 1.1`: grow the map
+        usable_size * 11 / 10
     }
 
+    /// An inverse of `min_capacity`, approximately.
     #[inline]
-    fn reserve(&mut self, new_capacity: uint) {
-        self.minimum_capacity2 = new_capacity << 1;
+    fn usable_capacity(&self, cap: uint) -> uint {
+        // As the number of entries approaches usable capacity,
+        // min_capacity(size) must be smaller than the internal capacity,
+        // so that the map is not resized:
+        // `min_capacity(usable_capacity(x)) <= x`.
+        // The lef-hand side can only be smaller due to flooring by integer
+        // division.
+        //
+        // This doesn't have to be checked for overflow since allocation size
+        // in bytes will overflow earlier than multiplication by 10.
+        cap * 10 / 11
+    }
+}
+
+#[test]
+fn test_resize_policy() {
+    use prelude::*;
+    let rp = DefaultResizePolicy;
+    for n in range(0u, 1000) {
+        assert!(rp.min_capacity(rp.usable_capacity(n)) <= n);
+        assert!(rp.usable_capacity(rp.min_capacity(n)) <= n);
     }
 }
 
@@ -282,15 +294,17 @@ pub struct HashMap<K, V, H = RandomSipHasher> {
 
     table: RawTable<K, V>,
 
-    // We keep this at the end since it might as well have tail padding.
     resize_policy: DefaultResizePolicy,
 }
 
 /// Search for a pre-hashed key.
-fn search_hashed<K, V, M: Deref<RawTable<K, V>>>(table: M,
-                                                 hash: &SafeHash,
-                                                 is_match: |&K| -> bool)
-                                                 -> SearchResult<K, V, M> {
+fn search_hashed<K, V, M, F>(table: M,
+                             hash: SafeHash,
+                             mut is_match: F)
+                             -> SearchResult<K, V, M> where
+    M: Deref<RawTable<K, V>>,
+    F: FnMut(&K) -> bool,
+{
     let size = table.size();
     let mut probe = Bucket::new(table, hash);
     let ib = probe.index();
@@ -308,14 +322,9 @@ fn search_hashed<K, V, M: Deref<RawTable<K, V>>>(table: M,
         }
 
         // If the hash doesn't match, it can't be this one..
-        if *hash == full.hash() {
-            let matched = {
-                let (k, _) = full.read();
-                is_match(k)
-            };
-
+        if hash == full.hash() {
             // If the key doesn't match, it can't be this one..
-            if matched {
+            if is_match(full.read().0) {
                 return FoundExisting(full);
             }
         }
@@ -341,7 +350,7 @@ fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>) -> (K, V) {
     }
 
     // Now we've done all our shifting. Return the value we grabbed earlier.
-    return (retkey, retval);
+    (retkey, retval)
 }
 
 /// Perform robin hood bucket stealing at the given `bucket`. You must
@@ -372,17 +381,18 @@ fn robin_hood<'a, K: 'a, V: 'a>(mut bucket: FullBucketMut<'a, K, V>,
             assert!(probe.index() != idx_end);
 
             let full_bucket = match probe.peek() {
-                table::Empty(bucket) => {
+                Empty(bucket) => {
                     // Found a hole!
                     let b = bucket.put(old_hash, old_key, old_val);
                     // Now that it's stolen, just read the value's pointer
                     // right out of the table!
-                    let (_, v) = Bucket::at_index(b.into_table(), starting_index).peek()
-                                                                                 .expect_full()
-                                                                                 .into_mut_refs();
-                    return v;
+                    return Bucket::at_index(b.into_table(), starting_index)
+                               .peek()
+                               .expect_full()
+                               .into_mut_refs()
+                               .1;
                 },
-                table::Full(bucket) => bucket
+                Full(bucket) => bucket
             };
 
             let probe_ib = full_bucket.index() - full_bucket.distance();
@@ -425,16 +435,18 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
         table::make_hash(&self.hasher, x)
     }
 
+    #[allow(deprecated)]
     fn search_equiv<'a, Sized? Q: Hash<S> + Equiv<K>>(&'a self, q: &Q)
                     -> Option<FullBucketImm<'a, K, V>> {
         let hash = self.make_hash(q);
-        search_hashed(&self.table, &hash, |k| q.equiv(k)).into_option()
+        search_hashed(&self.table, hash, |k| q.equiv(k)).into_option()
     }
 
+    #[allow(deprecated)]
     fn search_equiv_mut<'a, Sized? Q: Hash<S> + Equiv<K>>(&'a mut self, q: &Q)
                     -> Option<FullBucketMut<'a, K, V>> {
         let hash = self.make_hash(q);
-        search_hashed(&mut self.table, &hash, |k| q.equiv(k)).into_option()
+        search_hashed(&mut self.table, hash, |k| q.equiv(k)).into_option()
     }
 
     /// Search for a key, yielding the index if it's found in the hashtable.
@@ -444,7 +456,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
         where Q: BorrowFrom<K> + Eq + Hash<S>
     {
         let hash = self.make_hash(q);
-        search_hashed(&self.table, &hash, |k| q.eq(BorrowFrom::borrow_from(k)))
+        search_hashed(&self.table, hash, |k| q.eq(BorrowFrom::borrow_from(k)))
             .into_option()
     }
 
@@ -452,14 +464,14 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
         where Q: BorrowFrom<K> + Eq + Hash<S>
     {
         let hash = self.make_hash(q);
-        search_hashed(&mut self.table, &hash, |k| q.eq(BorrowFrom::borrow_from(k)))
+        search_hashed(&mut self.table, hash, |k| q.eq(BorrowFrom::borrow_from(k)))
             .into_option()
     }
 
     // The caller should ensure that invariants by Robin Hood Hashing hold.
     fn insert_hashed_ordered(&mut self, hash: SafeHash, k: K, v: V) {
         let cap = self.table.capacity();
-        let mut buckets = Bucket::new(&mut self.table, &hash);
+        let mut buckets = Bucket::new(&mut self.table, hash);
         let ib = buckets.index();
 
         while buckets.index() != ib + cap {
@@ -529,7 +541,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     pub fn with_hasher(hasher: H) -> HashMap<K, V, H> {
         HashMap {
             hasher:        hasher,
-            resize_policy: DefaultResizePolicy::new(INITIAL_CAPACITY),
+            resize_policy: DefaultResizePolicy::new(),
             table:         RawTable::new(0),
         }
     }
@@ -554,20 +566,39 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// ```
     #[inline]
     pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashMap<K, V, H> {
-        let cap = max(INITIAL_CAPACITY, capacity).next_power_of_two();
+        let resize_policy = DefaultResizePolicy::new();
+        let min_cap = max(INITIAL_CAPACITY, resize_policy.min_capacity(capacity));
+        let internal_cap = min_cap.checked_next_power_of_two().expect("capacity overflow");
+        assert!(internal_cap >= capacity, "capacity overflow");
         HashMap {
             hasher:        hasher,
-            resize_policy: DefaultResizePolicy::new(cap),
-            table:         RawTable::new(cap),
+            resize_policy: resize_policy,
+            table:         RawTable::new(internal_cap),
         }
     }
 
-    /// The hashtable will never try to shrink below this size. You can use
-    /// this function to reduce reallocations if your hashtable frequently
-    /// grows and shrinks by large amounts.
+    /// Returns the number of elements the map can hold without reallocating.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    /// let map: HashMap<int, int> = HashMap::with_capacity(100);
+    /// assert!(map.capacity() >= 100);
+    /// ```
+    #[inline]
+    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    pub fn capacity(&self) -> uint {
+        self.resize_policy.usable_capacity(self.table.capacity())
+    }
+
+    /// Reserves capacity for at least `additional` more elements to be inserted
+    /// in the `HashMap`. The collection may reserve more space to avoid
+    /// frequent reallocations.
     ///
-    /// This function has no effect on the operational semantics of the
-    /// hashtable, only on performance.
+    /// # Panics
+    ///
+    /// Panics if the new allocation size overflows `uint`.
     ///
     /// # Example
     ///
@@ -576,23 +607,28 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// let mut map: HashMap<&str, int> = HashMap::new();
     /// map.reserve(10);
     /// ```
-    pub fn reserve(&mut self, new_minimum_capacity: uint) {
-        let cap = max(INITIAL_CAPACITY, new_minimum_capacity).next_power_of_two();
+    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    pub fn reserve(&mut self, additional: uint) {
+        let new_size = self.len().checked_add(additional).expect("capacity overflow");
+        let min_cap = self.resize_policy.min_capacity(new_size);
 
-        self.resize_policy.reserve(cap);
+        // An invalid value shouldn't make us run out of space. This includes
+        // an overflow check.
+        assert!(new_size <= min_cap);
 
-        if self.table.capacity() < cap {
-            self.resize(cap);
+        if self.table.capacity() < min_cap {
+            let new_capacity = max(min_cap.next_power_of_two(), INITIAL_CAPACITY);
+            self.resize(new_capacity);
         }
     }
 
     /// Resizes the internal vectors to a new capacity. It's your responsibility to:
     ///   1) Make sure the new capacity is enough for all the elements, accounting
     ///      for the load factor.
-    ///   2) Ensure new_capacity is a power of two.
+    ///   2) Ensure new_capacity is a power of two or zero.
     fn resize(&mut self, new_capacity: uint) {
         assert!(self.table.size() <= new_capacity);
-        assert!(new_capacity.is_power_of_two());
+        assert!(new_capacity.is_power_of_two() || new_capacity == 0);
 
         let mut old_table = replace(&mut self.table, RawTable::new(new_capacity));
         let old_size = old_table.size();
@@ -601,94 +637,106 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
             return;
         }
 
-        if new_capacity < old_table.capacity() {
-            // Shrink the table. Naive algorithm for resizing:
-            for (h, k, v) in old_table.into_iter() {
-                self.insert_hashed_nocheck(h, k, v);
-            }
-        } else {
-            // Grow the table.
-            // Specialization of the other branch.
-            let mut bucket = Bucket::first(&mut old_table);
-
-            // "So a few of the first shall be last: for many be called,
-            // but few chosen."
-            //
-            // We'll most likely encounter a few buckets at the beginning that
-            // have their initial buckets near the end of the table. They were
-            // placed at the beginning as the probe wrapped around the table
-            // during insertion. We must skip forward to a bucket that won't
-            // get reinserted too early and won't unfairly steal others spot.
-            // This eliminates the need for robin hood.
-            loop {
-                bucket = match bucket.peek() {
-                    Full(full) => {
-                        if full.distance() == 0 {
-                            // This bucket occupies its ideal spot.
-                            // It indicates the start of another "cluster".
-                            bucket = full.into_bucket();
-                            break;
-                        }
-                        // Leaving this bucket in the last cluster for later.
-                        full.into_bucket()
-                    }
-                    Empty(b) => {
-                        // Encountered a hole between clusters.
-                        b.into_bucket()
-                    }
-                };
-                bucket.next();
-            }
+        // Grow the table.
+        // Specialization of the other branch.
+        let mut bucket = Bucket::first(&mut old_table);
 
-            // This is how the buckets might be laid out in memory:
-            // ($ marks an initialized bucket)
-            //  ________________
-            // |$$$_$$$$$$_$$$$$|
-            //
-            // But we've skipped the entire initial cluster of buckets
-            // and will continue iteration in this order:
-            //  ________________
-            //     |$$$$$$_$$$$$
-            //                  ^ wrap around once end is reached
-            //  ________________
-            //  $$$_____________|
-            //    ^ exit once table.size == 0
-            loop {
-                bucket = match bucket.peek() {
-                    Full(bucket) => {
-                        let h = bucket.hash();
-                        let (b, k, v) = bucket.take();
-                        self.insert_hashed_ordered(h, k, v);
-                        {
-                            let t = b.table(); // FIXME "lifetime too short".
-                            if t.size() == 0 { break }
-                        };
-                        b.into_bucket()
+        // "So a few of the first shall be last: for many be called,
+        // but few chosen."
+        //
+        // We'll most likely encounter a few buckets at the beginning that
+        // have their initial buckets near the end of the table. They were
+        // placed at the beginning as the probe wrapped around the table
+        // during insertion. We must skip forward to a bucket that won't
+        // get reinserted too early and won't unfairly steal others spot.
+        // This eliminates the need for robin hood.
+        loop {
+            bucket = match bucket.peek() {
+                Full(full) => {
+                    if full.distance() == 0 {
+                        // This bucket occupies its ideal spot.
+                        // It indicates the start of another "cluster".
+                        bucket = full.into_bucket();
+                        break;
                     }
-                    Empty(b) => b.into_bucket()
-                };
-                bucket.next();
-            }
+                    // Leaving this bucket in the last cluster for later.
+                    full.into_bucket()
+                }
+                Empty(b) => {
+                    // Encountered a hole between clusters.
+                    b.into_bucket()
+                }
+            };
+            bucket.next();
+        }
+
+        // This is how the buckets might be laid out in memory:
+        // ($ marks an initialized bucket)
+        //  ________________
+        // |$$$_$$$$$$_$$$$$|
+        //
+        // But we've skipped the entire initial cluster of buckets
+        // and will continue iteration in this order:
+        //  ________________
+        //     |$$$$$$_$$$$$
+        //                  ^ wrap around once end is reached
+        //  ________________
+        //  $$$_____________|
+        //    ^ exit once table.size == 0
+        loop {
+            bucket = match bucket.peek() {
+                Full(bucket) => {
+                    let h = bucket.hash();
+                    let (b, k, v) = bucket.take();
+                    self.insert_hashed_ordered(h, k, v);
+                    {
+                        let t = b.table(); // FIXME "lifetime too short".
+                        if t.size() == 0 { break }
+                    };
+                    b.into_bucket()
+                }
+                Empty(b) => b.into_bucket()
+            };
+            bucket.next();
         }
 
         assert_eq!(self.table.size(), old_size);
     }
 
-    /// Performs any necessary resize operations, such that there's space for
-    /// new_size elements.
-    fn make_some_room(&mut self, new_size: uint) {
-        let (grow_at, shrink_at) = self.resize_policy.capacity_range(new_size);
-        let cap = self.table.capacity();
+    /// Shrinks the capacity of the map as much as possible. It will drop
+    /// down as much as possible while maintaining the internal rules
+    /// and possibly leaving some space in accordance with the resize policy.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    ///
+    /// let mut map: HashMap<int, int> = HashMap::with_capacity(100);
+    /// map.insert(1, 2);
+    /// map.insert(3, 4);
+    /// assert!(map.capacity() >= 100);
+    /// map.shrink_to_fit();
+    /// assert!(map.capacity() >= 2);
+    /// ```
+    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    pub fn shrink_to_fit(&mut self) {
+        let min_capacity = self.resize_policy.min_capacity(self.len());
+        let min_capacity = max(min_capacity.next_power_of_two(), INITIAL_CAPACITY);
 
         // An invalid value shouldn't make us run out of space.
-        debug_assert!(grow_at >= new_size);
+        debug_assert!(self.len() <= min_capacity);
 
-        if cap <= grow_at {
-            let new_capacity = max(cap << 1, INITIAL_CAPACITY);
-            self.resize(new_capacity);
-        } else if shrink_at <= cap {
-            let new_capacity = cap >> 1;
-            self.resize(new_capacity);
+        if self.table.capacity() != min_capacity {
+            let old_table = replace(&mut self.table, RawTable::new(min_capacity));
+            let old_size = old_table.size();
+
+            // Shrink the table. Naive algorithm for resizing:
+            for (h, k, v) in old_table.into_iter() {
+                self.insert_hashed_nocheck(h, k, v);
+            }
+
+            debug_assert_eq!(self.table.size(), old_size);
         }
     }
 
@@ -702,34 +750,32 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
         self.insert_or_replace_with(hash, k, v, |_, _, _| ())
     }
 
-    fn insert_or_replace_with<'a>(&'a mut self,
-                                  hash: SafeHash,
-                                  k: K,
-                                  v: V,
-                                  found_existing: |&mut K, &mut V, V|)
-                                  -> &'a mut V {
+    fn insert_or_replace_with<'a, F>(&'a mut self,
+                                     hash: SafeHash,
+                                     k: K,
+                                     v: V,
+                                     mut found_existing: F)
+                                     -> &'a mut V where
+        F: FnMut(&mut K, &mut V, V),
+    {
         // Worst case, we'll find one empty bucket among `size + 1` buckets.
         let size = self.table.size();
-        let mut probe = Bucket::new(&mut self.table, &hash);
+        let mut probe = Bucket::new(&mut self.table, hash);
         let ib = probe.index();
 
         loop {
             let mut bucket = match probe.peek() {
                 Empty(bucket) => {
                     // Found a hole!
-                    let bucket = bucket.put(hash, k, v);
-                    let (_, val) = bucket.into_mut_refs();
-                    return val;
-                },
+                    return bucket.put(hash, k, v).into_mut_refs().1;
+                }
                 Full(bucket) => bucket
             };
 
+            // hash matches?
             if bucket.hash() == hash {
-                let found_match = {
-                    let (bucket_k, _) = bucket.read_mut();
-                    k == *bucket_k
-                };
-                if found_match {
+                // key matches?
+                if k == *bucket.read_mut().0 {
                     let (bucket_k, bucket_v) = bucket.into_mut_refs();
                     debug_assert!(k == *bucket_k);
                     // Key already exists. Get its reference.
@@ -759,13 +805,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// Deprecated: use `get` and `BorrowFrom` instead.
     #[deprecated = "use get and BorrowFrom instead"]
     pub fn find_equiv<'a, Sized? Q: Hash<S> + Equiv<K>>(&'a self, k: &Q) -> Option<&'a V> {
-        match self.search_equiv(k) {
-            None      => None,
-            Some(bucket) => {
-                let (_, v_ref) = bucket.into_refs();
-                Some(v_ref)
-            }
-        }
+        self.search_equiv(k).map(|bucket| bucket.into_refs().1)
     }
 
     /// Deprecated: use `remove` and `BorrowFrom` instead.
@@ -775,16 +815,9 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
             return None
         }
 
-        let potential_new_size = self.table.size() - 1;
-        self.make_some_room(potential_new_size);
+        self.reserve(1);
 
-        match self.search_equiv_mut(k) {
-            Some(bucket) => {
-                let (_k, val) = pop_internal(bucket);
-                Some(val)
-            }
-            _ => None
-        }
+        self.search_equiv_mut(k).map(|bucket| pop_internal(bucket).1)
     }
 
     /// An iterator visiting all keys in arbitrary order.
@@ -805,8 +838,11 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// }
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn keys(&self) -> Keys<K, V> {
-        self.iter().map(|(k, _v)| k)
+    pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
+        fn first<A, B>((a, _): (A, B)) -> A { a }
+        let first: fn((&'a K,&'a V)) -> &'a K = first; // coerce to fn ptr
+
+        Keys { inner: self.iter().map(first) }
     }
 
     /// An iterator visiting all values in arbitrary order.
@@ -827,8 +863,11 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// }
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn values(&self) -> Values<K, V> {
-        self.iter().map(|(_k, v)| v)
+    pub fn values<'a>(&'a self) -> Values<'a, K, V> {
+        fn second<A, B>((_, b): (A, B)) -> B { b }
+        let second: fn((&'a K,&'a V)) -> &'a V = second; // coerce to fn ptr
+
+        Values { inner: self.iter().map(second) }
     }
 
     /// An iterator visiting all key-value pairs in arbitrary order.
@@ -877,8 +916,8 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// }
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn iter_mut(&mut self) -> MutEntries<K, V> {
-        MutEntries { inner: self.table.iter_mut() }
+    pub fn iter_mut(&mut self) -> IterMut<K, V> {
+        IterMut { inner: self.table.iter_mut() }
     }
 
     /// Creates a consuming iterator, that is, one that moves each key-value
@@ -899,20 +938,19 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// let vec: Vec<(&str, int)> = map.into_iter().collect();
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn into_iter(self) -> MoveEntries<K, V> {
-        MoveEntries {
-            inner: self.table.into_iter().map(|(_, k, v)| (k, v))
+    pub fn into_iter(self) -> IntoIter<K, V> {
+        fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
+        let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two;
+
+        IntoIter {
+            inner: self.table.into_iter().map(last_two)
         }
     }
 
     /// Gets the given key's corresponding entry in the map for in-place manipulation
     pub fn entry<'a>(&'a mut self, key: K) -> Entry<'a, K, V> {
-        // Gotta resize now, and we don't know which direction, so try both?
-        let size = self.table.size();
-        self.make_some_room(size + 1);
-        if size > 0 {
-            self.make_some_room(size - 1);
-        }
+        // Gotta resize now.
+        self.reserve(1);
 
         let hash = self.make_hash(&key);
         search_entry_hashed(&mut self.table, hash, key)
@@ -949,6 +987,36 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn is_empty(&self) -> bool { self.len() == 0 }
 
+    /// Clears the map, returning all key-value pairs as an iterator. Keeps the
+    /// allocated memory for reuse.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    ///
+    /// let mut a = HashMap::new();
+    /// a.insert(1u, "a");
+    /// a.insert(2u, "b");
+    ///
+    /// for (k, v) in a.drain().take(1) {
+    ///     assert!(k == 1 || k == 2);
+    ///     assert!(v == "a" || v == "b");
+    /// }
+    ///
+    /// assert!(a.is_empty());
+    /// ```
+    #[inline]
+    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    pub fn drain(&mut self) -> Drain<K, V> {
+        fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
+        let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two; // coerce to fn pointer
+
+        Drain {
+            inner: self.table.drain().map(last_two),
+        }
+    }
+
     /// Clears the map, removing all key-value pairs. Keeps the allocated memory
     /// for reuse.
     ///
@@ -963,23 +1031,9 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// assert!(a.is_empty());
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[inline]
     pub fn clear(&mut self) {
-        // Prevent reallocations from happening from now on. Makes it possible
-        // for the map to be reused but has a downside: reserves permanently.
-        self.resize_policy.reserve(self.table.size());
-
-        let cap = self.table.capacity();
-        let mut buckets = Bucket::first(&mut self.table);
-
-        while buckets.index() != cap {
-            buckets = match buckets.peek() {
-                Empty(b)  => b.next(),
-                Full(full) => {
-                    let (b, _, _) = full.take();
-                    b.next()
-                }
-            };
-        }
+        self.drain();
     }
 
     /// Deprecated: Renamed to `get`.
@@ -1008,10 +1062,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     pub fn get<Sized? Q>(&self, k: &Q) -> Option<&V>
         where Q: Hash<S> + Eq + BorrowFrom<K>
     {
-        self.search(k).map(|bucket| {
-            let (_, v) = bucket.into_refs();
-            v
-        })
+        self.search(k).map(|bucket| bucket.into_refs().1)
     }
 
     /// Returns true if the map contains a value for the specified key.
@@ -1066,13 +1117,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     pub fn get_mut<Sized? Q>(&mut self, k: &Q) -> Option<&mut V>
         where Q: Hash<S> + Eq + BorrowFrom<K>
     {
-        match self.search_mut(k) {
-            Some(bucket) => {
-                let (_, v) = bucket.into_mut_refs();
-                Some(v)
-            }
-            _ => None
-        }
+        self.search_mut(k).map(|bucket| bucket.into_mut_refs().1)
     }
 
     /// Deprecated: Renamed to `insert`.
@@ -1100,8 +1145,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn insert(&mut self, k: K, v: V) -> Option<V> {
         let hash = self.make_hash(&k);
-        let potential_new_size = self.table.size() + 1;
-        self.make_some_room(potential_new_size);
+        self.reserve(1);
 
         let mut retval = None;
         self.insert_or_replace_with(hash, k, v, |_, val_ref, val| {
@@ -1141,13 +1185,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
             return None
         }
 
-        let potential_new_size = self.table.size() - 1;
-        self.make_some_room(potential_new_size);
-
-        self.search_mut(k).map(|bucket| {
-            let (_k, val) = pop_internal(bucket);
-            val
-        })
+        self.search_mut(k).map(|bucket| pop_internal(bucket).1)
     }
 }
 
@@ -1155,7 +1193,7 @@ fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable<K,V>, hash: SafeHas
         -> Entry<'a, K, V> {
     // Worst case, we'll find one empty bucket among `size + 1` buckets.
     let size = table.size();
-    let mut probe = Bucket::new(table, &hash);
+    let mut probe = Bucket::new(table, hash);
     let ib = probe.index();
 
     loop {
@@ -1171,13 +1209,10 @@ fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable<K,V>, hash: SafeHas
             Full(bucket) => bucket
         };
 
+        // hash matches?
         if bucket.hash() == hash {
-            let is_eq = {
-                let (bucket_k, _) = bucket.read();
-                k == *bucket_k
-            };
-
-            if is_eq {
+            // key matches?
+            if k == *bucket.read().0 {
                 return Occupied(OccupiedEntry{
                     elem: bucket,
                 });
@@ -1243,7 +1278,9 @@ impl<K: Eq + Hash<S> + Show, V: Show, S, H: Hasher<S>> Show for HashMap<K, V, H>
     }
 }
 
+#[stable]
 impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> Default for HashMap<K, V, H> {
+    #[stable]
     fn default() -> HashMap<K, V, H> {
         HashMap::with_hasher(Default::default())
     }
@@ -1263,10 +1300,7 @@ impl<K: Hash<S> + Eq, Sized? Q, V, S, H: Hasher<S>> IndexMut<Q, V> for HashMap<K
 {
     #[inline]
     fn index_mut<'a>(&'a mut self, index: &Q) -> &'a mut V {
-        match self.get_mut(index) {
-            Some(v) => v,
-            None => panic!("no entry found for key")
-        }
+        self.get_mut(index).expect("no entry found for key")
     }
 }
 
@@ -1276,13 +1310,38 @@ pub struct Entries<'a, K: 'a, V: 'a> {
 }
 
 /// HashMap mutable values iterator
-pub struct MutEntries<'a, K: 'a, V: 'a> {
-    inner: table::MutEntries<'a, K, V>
+pub struct IterMut<'a, K: 'a, V: 'a> {
+    inner: table::IterMut<'a, K, V>
 }
 
 /// HashMap move iterator
-pub struct MoveEntries<K, V> {
-    inner: iter::Map<'static, (SafeHash, K, V), (K, V), table::MoveEntries<K, V>>
+pub struct IntoIter<K, V> {
+    inner: iter::Map<
+        (SafeHash, K, V),
+        (K, V),
+        table::IntoIter<K, V>,
+        fn((SafeHash, K, V)) -> (K, V),
+    >
+}
+
+/// HashMap keys iterator
+pub struct Keys<'a, K: 'a, V: 'a> {
+    inner: Map<(&'a K, &'a V), &'a K, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>
+}
+
+/// HashMap values iterator
+pub struct Values<'a, K: 'a, V: 'a> {
+    inner: Map<(&'a K, &'a V), &'a V, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>
+}
+
+/// HashMap drain iterator
+pub struct Drain<'a, K: 'a, V: 'a> {
+    inner: iter::Map<
+        (SafeHash, K, V),
+        (K, V),
+        table::Drain<'a, K, V>,
+        fn((SafeHash, K, V)) -> (K, V),
+    >
 }
 
 /// A view into a single occupied location in a HashMap
@@ -1315,28 +1374,31 @@ enum VacantEntryState<K, V, M> {
 }
 
 impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> {
-    #[inline]
-    fn next(&mut self) -> Option<(&'a K, &'a V)> {
-        self.inner.next()
-    }
-    #[inline]
-    fn size_hint(&self) -> (uint, Option<uint>) {
-        self.inner.size_hint()
-    }
+    #[inline] fn next(&mut self) -> Option<(&'a K, &'a V)> { self.inner.next() }
+    #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
 }
 
-impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> {
-    #[inline]
-    fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
-        self.inner.next()
-    }
-    #[inline]
-    fn size_hint(&self) -> (uint, Option<uint>) {
-        self.inner.size_hint()
-    }
+impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for IterMut<'a, K, V> {
+    #[inline] fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.inner.next() }
+    #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
+}
+
+impl<K, V> Iterator<(K, V)> for IntoIter<K, V> {
+    #[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next() }
+    #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
+}
+
+impl<'a, K, V> Iterator<&'a K> for Keys<'a, K, V> {
+    #[inline] fn next(&mut self) -> Option<(&'a K)> { self.inner.next() }
+    #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
 }
 
-impl<K, V> Iterator<(K, V)> for MoveEntries<K, V> {
+impl<'a, K, V> Iterator<&'a V> for Values<'a, K, V> {
+    #[inline] fn next(&mut self) -> Option<(&'a V)> { self.inner.next() }
+    #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
+}
+
+impl<'a, K: 'a, V: 'a> Iterator<(K, V)> for Drain<'a, K, V> {
     #[inline]
     fn next(&mut self) -> Option<(K, V)> {
         self.inner.next()
@@ -1350,21 +1412,18 @@ impl<K, V> Iterator<(K, V)> for MoveEntries<K, V> {
 impl<'a, K, V> OccupiedEntry<'a, K, V> {
     /// Gets a reference to the value in the entry
     pub fn get(&self) -> &V {
-        let (_, v) = self.elem.read();
-        v
+        self.elem.read().1
     }
 
     /// Gets a mutable reference to the value in the entry
     pub fn get_mut(&mut self) -> &mut V {
-        let (_, v) = self.elem.read_mut();
-        v
+        self.elem.read_mut().1
     }
 
     /// Converts the OccupiedEntry into a mutable reference to the value in the entry
     /// with a lifetime bound to the map itself
     pub fn into_mut(self) -> &'a mut V {
-        let (_, v) = self.elem.into_mut_refs();
-        v
+        self.elem.into_mut_refs().1
     }
 
     /// Sets the value of the entry, and returns the entry's old value
@@ -1376,8 +1435,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
 
     /// Takes the value out of the entry, and returns it
     pub fn take(self) -> V {
-        let (_, _, v) = self.elem.take();
-        v
+        pop_internal(self.elem).1
     }
 }
 
@@ -1390,25 +1448,15 @@ impl<'a, K, V> VacantEntry<'a, K, V> {
                 robin_hood(bucket, ib, self.hash, self.key, value)
             }
             NoElem(bucket) => {
-                let full = bucket.put(self.hash, self.key, value);
-                let (_, v) = full.into_mut_refs();
-                v
+                bucket.put(self.hash, self.key, value).into_mut_refs().1
             }
         }
     }
 }
 
-/// HashMap keys iterator
-pub type Keys<'a, K, V> =
-    iter::Map<'static, (&'a K, &'a V), &'a K, Entries<'a, K, V>>;
-
-/// HashMap values iterator
-pub type Values<'a, K, V> =
-    iter::Map<'static, (&'a K, &'a V), &'a V, Entries<'a, K, V>>;
-
 impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> FromIterator<(K, V)> for HashMap<K, V, H> {
     fn from_iter<T: Iterator<(K, V)>>(iter: T) -> HashMap<K, V, H> {
-        let (lower, _) = iter.size_hint();
+        let lower = iter.size_hint().0;
         let mut map = HashMap::with_capacity_and_hasher(lower, Default::default());
         map.extend(iter);
         map
@@ -1428,11 +1476,11 @@ mod test_map {
     use prelude::*;
 
     use super::HashMap;
-    use super::{Occupied, Vacant};
-    use cmp::Equiv;
+    use super::Entry::{Occupied, Vacant};
     use hash;
-    use iter::{Iterator,range_inclusive,range_step_inclusive};
+    use iter::{range_inclusive, range_step_inclusive};
     use cell::RefCell;
+    use rand::{weak_rng, Rng};
 
     struct KindaIntLike(int);
 
@@ -1471,7 +1519,7 @@ mod test_map {
         assert_eq!(*m.get(&2).unwrap(), 4);
     }
 
-    local_data_key!(drop_vector: RefCell<Vec<int>>)
+    thread_local! { static DROP_VECTOR: RefCell<Vec<int>> = RefCell::new(Vec::new()) }
 
     #[deriving(Hash, PartialEq, Eq)]
     struct Dropable {
@@ -1480,8 +1528,9 @@ mod test_map {
 
     impl Dropable {
         fn new(k: uint) -> Dropable {
-            let v = drop_vector.get().unwrap();
-            v.borrow_mut().as_mut_slice()[k] += 1;
+            DROP_VECTOR.with(|slot| {
+                slot.borrow_mut()[k] += 1;
+            });
 
             Dropable { k: k }
         }
@@ -1489,8 +1538,9 @@ mod test_map {
 
     impl Drop for Dropable {
         fn drop(&mut self) {
-            let v = drop_vector.get().unwrap();
-            v.borrow_mut().as_mut_slice()[self.k] -= 1;
+            DROP_VECTOR.with(|slot| {
+                slot.borrow_mut()[self.k] -= 1;
+            });
         }
     }
 
@@ -1502,16 +1552,18 @@ mod test_map {
 
     #[test]
     fn test_drops() {
-        drop_vector.replace(Some(RefCell::new(Vec::from_elem(200, 0i))));
+        DROP_VECTOR.with(|slot| {
+            *slot.borrow_mut() = Vec::from_elem(200, 0i);
+        });
 
         {
             let mut m = HashMap::new();
 
-            let v = drop_vector.get().unwrap();
-            for i in range(0u, 200) {
-                assert_eq!(v.borrow().as_slice()[i], 0);
-            }
-            drop(v);
+            DROP_VECTOR.with(|v| {
+                for i in range(0u, 200) {
+                    assert_eq!(v.borrow()[i], 0);
+                }
+            });
 
             for i in range(0u, 100) {
                 let d1 = Dropable::new(i);
@@ -1519,11 +1571,11 @@ mod test_map {
                 m.insert(d1, d2);
             }
 
-            let v = drop_vector.get().unwrap();
-            for i in range(0u, 200) {
-                assert_eq!(v.borrow().as_slice()[i], 1);
-            }
-            drop(v);
+            DROP_VECTOR.with(|v| {
+                for i in range(0u, 200) {
+                    assert_eq!(v.borrow()[i], 1);
+                }
+            });
 
             for i in range(0u, 50) {
                 let k = Dropable::new(i);
@@ -1531,41 +1583,46 @@ mod test_map {
 
                 assert!(v.is_some());
 
-                let v = drop_vector.get().unwrap();
-                assert_eq!(v.borrow().as_slice()[i], 1);
-                assert_eq!(v.borrow().as_slice()[i+100], 1);
+                DROP_VECTOR.with(|v| {
+                    assert_eq!(v.borrow()[i], 1);
+                    assert_eq!(v.borrow()[i+100], 1);
+                });
             }
 
-            let v = drop_vector.get().unwrap();
-            for i in range(0u, 50) {
-                assert_eq!(v.borrow().as_slice()[i], 0);
-                assert_eq!(v.borrow().as_slice()[i+100], 0);
-            }
+            DROP_VECTOR.with(|v| {
+                for i in range(0u, 50) {
+                    assert_eq!(v.borrow()[i], 0);
+                    assert_eq!(v.borrow()[i+100], 0);
+                }
 
-            for i in range(50u, 100) {
-                assert_eq!(v.borrow().as_slice()[i], 1);
-                assert_eq!(v.borrow().as_slice()[i+100], 1);
-            }
+                for i in range(50u, 100) {
+                    assert_eq!(v.borrow()[i], 1);
+                    assert_eq!(v.borrow()[i+100], 1);
+                }
+            });
         }
 
-        let v = drop_vector.get().unwrap();
-        for i in range(0u, 200) {
-            assert_eq!(v.borrow().as_slice()[i], 0);
-        }
+        DROP_VECTOR.with(|v| {
+            for i in range(0u, 200) {
+                assert_eq!(v.borrow()[i], 0);
+            }
+        });
     }
 
     #[test]
     fn test_move_iter_drops() {
-        drop_vector.replace(Some(RefCell::new(Vec::from_elem(200, 0i))));
+        DROP_VECTOR.with(|v| {
+            *v.borrow_mut() = Vec::from_elem(200, 0i);
+        });
 
         let hm = {
             let mut hm = HashMap::new();
 
-            let v = drop_vector.get().unwrap();
-            for i in range(0u, 200) {
-                assert_eq!(v.borrow().as_slice()[i], 0);
-            }
-            drop(v);
+            DROP_VECTOR.with(|v| {
+                for i in range(0u, 200) {
+                    assert_eq!(v.borrow()[i], 0);
+                }
+            });
 
             for i in range(0u, 100) {
                 let d1 = Dropable::new(i);
@@ -1573,11 +1630,11 @@ mod test_map {
                 hm.insert(d1, d2);
             }
 
-            let v = drop_vector.get().unwrap();
-            for i in range(0u, 200) {
-                assert_eq!(v.borrow().as_slice()[i], 1);
-            }
-            drop(v);
+            DROP_VECTOR.with(|v| {
+                for i in range(0u, 200) {
+                    assert_eq!(v.borrow()[i], 1);
+                }
+            });
 
             hm
         };
@@ -1588,31 +1645,33 @@ mod test_map {
         {
             let mut half = hm.into_iter().take(50);
 
-            let v = drop_vector.get().unwrap();
-            for i in range(0u, 200) {
-                assert_eq!(v.borrow().as_slice()[i], 1);
-            }
-            drop(v);
+            DROP_VECTOR.with(|v| {
+                for i in range(0u, 200) {
+                    assert_eq!(v.borrow()[i], 1);
+                }
+            });
 
             for _ in half {}
 
-            let v = drop_vector.get().unwrap();
-            let nk = range(0u, 100).filter(|&i| {
-                v.borrow().as_slice()[i] == 1
-            }).count();
+            DROP_VECTOR.with(|v| {
+                let nk = range(0u, 100).filter(|&i| {
+                    v.borrow()[i] == 1
+                }).count();
 
-            let nv = range(0u, 100).filter(|&i| {
-                v.borrow().as_slice()[i+100] == 1
-            }).count();
+                let nv = range(0u, 100).filter(|&i| {
+                    v.borrow()[i+100] == 1
+                }).count();
 
-            assert_eq!(nk, 50);
-            assert_eq!(nv, 50);
+                assert_eq!(nk, 50);
+                assert_eq!(nv, 50);
+            });
         };
 
-        let v = drop_vector.get().unwrap();
-        for i in range(0u, 200) {
-            assert_eq!(v.borrow().as_slice()[i], 0);
-        }
+        DROP_VECTOR.with(|v| {
+            for i in range(0u, 200) {
+                assert_eq!(v.borrow()[i], 0);
+            }
+        });
     }
 
     #[test]
@@ -1859,8 +1918,8 @@ mod test_map {
 
         let map_str = format!("{}", map);
 
-        assert!(map_str == "{1: 2, 3: 4}".to_string() || map_str == "{3: 4, 1: 2}".to_string());
-        assert_eq!(format!("{}", empty), "{}".to_string());
+        assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}");
+        assert_eq!(format!("{}", empty), "{}");
     }
 
     #[test]
@@ -1882,7 +1941,7 @@ mod test_map {
     }
 
     #[test]
-    fn test_resize_policy() {
+    fn test_behavior_resize_policy() {
         let mut m = HashMap::new();
 
         assert_eq!(m.len(), 0);
@@ -1893,7 +1952,7 @@ mod test_map {
         m.remove(&0);
         assert!(m.is_empty());
         let initial_cap = m.table.capacity();
-        m.reserve(initial_cap * 2);
+        m.reserve(initial_cap);
         let cap = m.table.capacity();
 
         assert_eq!(cap, initial_cap * 2);
@@ -1923,15 +1982,55 @@ mod test_map {
             assert_eq!(m.table.capacity(), new_cap);
         }
         // A little more than one quarter full.
-        // Shrinking starts as we remove more elements:
+        m.shrink_to_fit();
+        assert_eq!(m.table.capacity(), cap);
+        // again, a little more than half full
         for _ in range(0, cap / 2 - 1) {
             i -= 1;
             m.remove(&i);
         }
+        m.shrink_to_fit();
 
         assert_eq!(m.len(), i);
         assert!(!m.is_empty());
-        assert_eq!(m.table.capacity(), cap);
+        assert_eq!(m.table.capacity(), initial_cap);
+    }
+
+    #[test]
+    fn test_reserve_shrink_to_fit() {
+        let mut m = HashMap::new();
+        m.insert(0u, 0u);
+        m.remove(&0);
+        assert!(m.capacity() >= m.len());
+        for i in range(0, 128) {
+            m.insert(i, i);
+        }
+        m.reserve(256);
+
+        let usable_cap = m.capacity();
+        for i in range(128, 128+256) {
+            m.insert(i, i);
+            assert_eq!(m.capacity(), usable_cap);
+        }
+
+        for i in range(100, 128+256) {
+            assert_eq!(m.remove(&i), Some(i));
+        }
+        m.shrink_to_fit();
+
+        assert_eq!(m.len(), 100);
+        assert!(!m.is_empty());
+        assert!(m.capacity() >= m.len());
+
+        for i in range(0, 100) {
+            assert_eq!(m.remove(&i), Some(i));
+        }
+        m.shrink_to_fit();
+        m.insert(0, 0);
+
+        assert_eq!(m.len(), 1);
+        assert!(m.capacity() >= m.len());
+        assert_eq!(m.remove(&0), Some(0));
     }
 
     #[test]
@@ -2062,4 +2161,37 @@ mod test_map {
         assert_eq!(map.get(&10).unwrap(), &1000);
         assert_eq!(map.len(), 6);
     }
+
+    #[test]
+    fn test_entry_take_doesnt_corrupt() {
+        // Test for #19292
+        fn check(m: &HashMap<int, ()>) {
+            for k in m.keys() {
+                assert!(m.contains_key(k),
+                        "{} is in keys() but not in the map?", k);
+            }
+        }
+
+        let mut m = HashMap::new();
+        let mut rng = weak_rng();
+
+        // Populate the map with some items.
+        for _ in range(0u, 50) {
+            let x = rng.gen_range(-10, 10);
+            m.insert(x, ());
+        }
+
+        for i in range(0u, 1000) {
+            let x = rng.gen_range(-10, 10);
+            match m.entry(x) {
+                Vacant(_) => {},
+                Occupied(e) => {
+                    println!("{}: remove {}", i, x);
+                    e.take();
+                },
+            }
+
+            check(&m);
+        }
+    }
 }
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index 2fbcb464358..6d83d5510b3 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -11,22 +11,19 @@
 // ignore-lexer-test FIXME #15883
 
 use borrow::BorrowFrom;
+use clone::Clone;
 use cmp::{Eq, Equiv, PartialEq};
 use core::kinds::Sized;
 use default::Default;
 use fmt::Show;
 use fmt;
 use hash::{Hash, Hasher, RandomSipHasher};
-use iter::{Iterator, FromIterator, FilterMap, Chain, Repeat, Zip, Extend};
-use iter;
-use option::{Some, None};
-use result::{Ok, Err};
-
-use super::map::{HashMap, Entries, MoveEntries, INITIAL_CAPACITY};
-
-// FIXME(conventions): implement BitOr, BitAnd, BitXor, and Sub
-// FIXME(conventions): update capacity management to match other collections (no auto-shrink)
+use iter::{Iterator, IteratorExt, IteratorCloneExt, FromIterator, Map, Chain, Extend};
+use ops::{BitOr, BitAnd, BitXor, Sub};
+use option::Option::{Some, None, mod};
+use result::Result::{Ok, Err};
 
+use super::map::{mod, HashMap, Keys, INITIAL_CAPACITY};
 
 // Future Optimization (FIXME!)
 // =============================
@@ -172,7 +169,28 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
         HashSet { map: HashMap::with_capacity_and_hasher(capacity, hasher) }
     }
 
-    /// Reserve space for at least `n` elements in the hash table.
+    /// Returns the number of elements the set can hold without reallocating.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use std::collections::HashSet;
+    /// let set: HashSet<int> = HashSet::with_capacity(100);
+    /// assert!(set.capacity() >= 100);
+    /// ```
+    #[inline]
+    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    pub fn capacity(&self) -> uint {
+        self.map.capacity()
+    }
+
+    /// Reserves capacity for at least `additional` more elements to be inserted
+    /// in the `HashSet`. The collection may reserve more space to avoid
+    /// frequent reallocations.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the new allocation size overflows `uint`.
     ///
     /// # Example
     ///
@@ -181,8 +199,30 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// let mut set: HashSet<int> = HashSet::new();
     /// set.reserve(10);
     /// ```
-    pub fn reserve(&mut self, n: uint) {
-        self.map.reserve(n)
+    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    pub fn reserve(&mut self, additional: uint) {
+        self.map.reserve(additional)
+    }
+
+    /// Shrinks the capacity of the set as much as possible. It will drop
+    /// down as much as possible while maintaining the internal rules
+    /// and possibly leaving some space in accordance with the resize policy.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use std::collections::HashSet;
+    ///
+    /// let mut set: HashSet<int> = HashSet::with_capacity(100);
+    /// set.insert(1);
+    /// set.insert(2);
+    /// assert!(set.capacity() >= 100);
+    /// set.shrink_to_fit();
+    /// assert!(set.capacity() >= 2);
+    /// ```
+    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    pub fn shrink_to_fit(&mut self) {
+        self.map.shrink_to_fit()
     }
 
     /// Deprecated: use `contains` and `BorrowFrom`.
@@ -209,8 +249,8 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// }
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn iter<'a>(&'a self) -> SetItems<'a, T> {
-        self.map.keys()
+    pub fn iter<'a>(&'a self) -> Iter<'a, T> {
+        Iter { iter: self.map.keys() }
     }
 
     /// Creates a consuming iterator, that is, one that moves each value out
@@ -234,8 +274,11 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// }
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn into_iter(self) -> SetMoveItems<T> {
-        self.map.into_iter().map(|(k, _)| k)
+    pub fn into_iter(self) -> IntoIter<T> {
+        fn first<A, B>((a, _): (A, B)) -> A { a }
+        let first: fn((T, ())) -> T = first;
+
+        IntoIter { iter: self.map.into_iter().map(first) }
     }
 
     /// Visit the values representing the difference.
@@ -261,11 +304,11 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// assert_eq!(diff, [4i].iter().map(|&x| x).collect());
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn difference<'a>(&'a self, other: &'a HashSet<T, H>) -> SetAlgebraItems<'a, T, H> {
-        Repeat::new(other).zip(self.iter())
-            .filter_map(|(other, elt)| {
-                if !other.contains(elt) { Some(elt) } else { None }
-            })
+    pub fn difference<'a>(&'a self, other: &'a HashSet<T, H>) -> Difference<'a, T, H> {
+        Difference {
+            iter: self.iter(),
+            other: other,
+        }
     }
 
     /// Visit the values representing the symmetric difference.
@@ -290,8 +333,8 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, H>)
-        -> Chain<SetAlgebraItems<'a, T, H>, SetAlgebraItems<'a, T, H>> {
-        self.difference(other).chain(other.difference(self))
+        -> SymmetricDifference<'a, T, H> {
+        SymmetricDifference { iter: self.difference(other).chain(other.difference(self)) }
     }
 
     /// Visit the values representing the intersection.
@@ -312,12 +355,11 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// assert_eq!(diff, [2i, 3].iter().map(|&x| x).collect());
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn intersection<'a>(&'a self, other: &'a HashSet<T, H>)
-        -> SetAlgebraItems<'a, T, H> {
-        Repeat::new(other).zip(self.iter())
-            .filter_map(|(other, elt)| {
-                if other.contains(elt) { Some(elt) } else { None }
-            })
+    pub fn intersection<'a>(&'a self, other: &'a HashSet<T, H>) -> Intersection<'a, T, H> {
+        Intersection {
+            iter: self.iter(),
+            other: other,
+        }
     }
 
     /// Visit the values representing the union.
@@ -338,9 +380,8 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// assert_eq!(diff, [1i, 2, 3, 4].iter().map(|&x| x).collect());
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn union<'a>(&'a self, other: &'a HashSet<T, H>)
-        -> Chain<SetItems<'a, T>, SetAlgebraItems<'a, T, H>> {
-        self.iter().chain(other.difference(self))
+    pub fn union<'a>(&'a self, other: &'a HashSet<T, H>) -> Union<'a, T, H> {
+        Union { iter: self.iter().chain(other.difference(self)) }
     }
 
     /// Return the number of elements in the set
@@ -373,6 +414,16 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn is_empty(&self) -> bool { self.map.len() == 0 }
 
+    /// Clears the set, returning all elements in an iterator.
+    #[inline]
+    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    pub fn drain(&mut self) -> Drain<T> {
+        fn first<A, B>((a, _): (A, B)) -> A { a }
+        let first: fn((T, ())) -> T = first; // coerce to fn pointer
+
+        Drain { iter: self.map.drain().map(first) }
+    }
+
     /// Clears the set, removing all values.
     ///
     /// # Example
@@ -546,7 +597,7 @@ impl<T: Eq + Hash<S> + fmt::Show, S, H: Hasher<S>> fmt::Show for HashSet<T, H> {
 
 impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> FromIterator<T> for HashSet<T, H> {
     fn from_iter<I: Iterator<T>>(iter: I) -> HashSet<T, H> {
-        let (lower, _) = iter.size_hint();
+        let lower = iter.size_hint().0;
         let mut set = HashSet::with_capacity_and_hasher(lower, Default::default());
         set.extend(iter);
         set
@@ -561,33 +612,241 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Extend<T> for HashSet<T, H> {
     }
 }
 
+#[stable]
 impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Default for HashSet<T, H> {
+    #[stable]
     fn default() -> HashSet<T, H> {
         HashSet::with_hasher(Default::default())
     }
 }
 
+#[unstable = "matches collection reform specification, waiting for dust to settle"]
+impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default>
+BitOr<&'b HashSet<T, H>, HashSet<T, H>> for &'a HashSet<T, H> {
+    /// Returns the union of `self` and `rhs` as a new `HashSet<T, H>`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashSet;
+    ///
+    /// let a: HashSet<int> = vec![1, 2, 3].into_iter().collect();
+    /// let b: HashSet<int> = vec![3, 4, 5].into_iter().collect();
+    ///
+    /// let set: HashSet<int> = &a | &b;
+    ///
+    /// let mut i = 0;
+    /// let expected = [1, 2, 3, 4, 5];
+    /// for x in set.iter() {
+    ///     assert!(expected.contains(x));
+    ///     i += 1;
+    /// }
+    /// assert_eq!(i, expected.len());
+    /// ```
+    fn bitor(self, rhs: &HashSet<T, H>) -> HashSet<T, H> {
+        self.union(rhs).cloned().collect()
+    }
+}
+
+#[unstable = "matches collection reform specification, waiting for dust to settle"]
+impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default>
+BitAnd<&'b HashSet<T, H>, HashSet<T, H>> for &'a HashSet<T, H> {
+    /// Returns the intersection of `self` and `rhs` as a new `HashSet<T, H>`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashSet;
+    ///
+    /// let a: HashSet<int> = vec![1, 2, 3].into_iter().collect();
+    /// let b: HashSet<int> = vec![2, 3, 4].into_iter().collect();
+    ///
+    /// let set: HashSet<int> = &a & &b;
+    ///
+    /// let mut i = 0;
+    /// let expected = [2, 3];
+    /// for x in set.iter() {
+    ///     assert!(expected.contains(x));
+    ///     i += 1;
+    /// }
+    /// assert_eq!(i, expected.len());
+    /// ```
+    fn bitand(self, rhs: &HashSet<T, H>) -> HashSet<T, H> {
+        self.intersection(rhs).cloned().collect()
+    }
+}
+
+#[unstable = "matches collection reform specification, waiting for dust to settle"]
+impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default>
+BitXor<&'b HashSet<T, H>, HashSet<T, H>> for &'a HashSet<T, H> {
+    /// Returns the symmetric difference of `self` and `rhs` as a new `HashSet<T, H>`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashSet;
+    ///
+    /// let a: HashSet<int> = vec![1, 2, 3].into_iter().collect();
+    /// let b: HashSet<int> = vec![3, 4, 5].into_iter().collect();
+    ///
+    /// let set: HashSet<int> = &a ^ &b;
+    ///
+    /// let mut i = 0;
+    /// let expected = [1, 2, 4, 5];
+    /// for x in set.iter() {
+    ///     assert!(expected.contains(x));
+    ///     i += 1;
+    /// }
+    /// assert_eq!(i, expected.len());
+    /// ```
+    fn bitxor(self, rhs: &HashSet<T, H>) -> HashSet<T, H> {
+        self.symmetric_difference(rhs).cloned().collect()
+    }
+}
+
+#[unstable = "matches collection reform specification, waiting for dust to settle"]
+impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default>
+Sub<&'b HashSet<T, H>, HashSet<T, H>> for &'a HashSet<T, H> {
+    /// Returns the difference of `self` and `rhs` as a new `HashSet<T, H>`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashSet;
+    ///
+    /// let a: HashSet<int> = vec![1, 2, 3].into_iter().collect();
+    /// let b: HashSet<int> = vec![3, 4, 5].into_iter().collect();
+    ///
+    /// let set: HashSet<int> = &a - &b;
+    ///
+    /// let mut i = 0;
+    /// let expected = [1, 2];
+    /// for x in set.iter() {
+    ///     assert!(expected.contains(x));
+    ///     i += 1;
+    /// }
+    /// assert_eq!(i, expected.len());
+    /// ```
+    fn sub(self, rhs: &HashSet<T, H>) -> HashSet<T, H> {
+        self.difference(rhs).cloned().collect()
+    }
+}
+
 /// HashSet iterator
-pub type SetItems<'a, K> =
-    iter::Map<'static, (&'a K, &'a ()), &'a K, Entries<'a, K, ()>>;
+pub struct Iter<'a, K: 'a> {
+    iter: Keys<'a, K, ()>
+}
 
 /// HashSet move iterator
-pub type SetMoveItems<K> =
-    iter::Map<'static, (K, ()), K, MoveEntries<K, ()>>;
+pub struct IntoIter<K> {
+    iter: Map<(K, ()), K, map::IntoIter<K, ()>, fn((K, ())) -> K>
+}
+
+/// HashSet drain iterator
+pub struct Drain<'a, K: 'a> {
+    iter: Map<(K, ()), K, map::Drain<'a, K, ()>, fn((K, ())) -> K>,
+}
+
+/// Intersection iterator
+pub struct Intersection<'a, T: 'a, H: 'a> {
+    // iterator of the first set
+    iter: Iter<'a, T>,
+    // the second set
+    other: &'a HashSet<T, H>,
+}
+
+/// Difference iterator
+pub struct Difference<'a, T: 'a, H: 'a> {
+    // iterator of the first set
+    iter: Iter<'a, T>,
+    // the second set
+    other: &'a HashSet<T, H>,
+}
 
-// `Repeat` is used to feed the filter closure an explicit capture
-// of a reference to the other set
-/// Set operations iterator
-pub type SetAlgebraItems<'a, T, H> =
-    FilterMap<'static, (&'a HashSet<T, H>, &'a T), &'a T,
-              Zip<Repeat<&'a HashSet<T, H>>, SetItems<'a, T>>>;
+/// Symmetric difference iterator.
+pub struct SymmetricDifference<'a, T: 'a, H: 'a> {
+    iter: Chain<Difference<'a, T, H>, Difference<'a, T, H>>
+}
+
+/// Set union iterator.
+pub struct Union<'a, T: 'a, H: 'a> {
+    iter: Chain<Iter<'a, T>, Difference<'a, T, H>>
+}
+
+impl<'a, K> Iterator<&'a K> for Iter<'a, K> {
+    fn next(&mut self) -> Option<&'a K> { self.iter.next() }
+    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+}
+
+impl<K> Iterator<K> for IntoIter<K> {
+    fn next(&mut self) -> Option<K> { self.iter.next() }
+    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+}
+
+impl<'a, K: 'a> Iterator<K> for Drain<'a, K> {
+    fn next(&mut self) -> Option<K> { self.iter.next() }
+    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+}
+
+impl<'a, T, S, H> Iterator<&'a T> for Intersection<'a, T, H>
+    where T: Eq + Hash<S>, H: Hasher<S>
+{
+    fn next(&mut self) -> Option<&'a T> {
+        loop {
+            match self.iter.next() {
+                None => return None,
+                Some(elt) => if self.other.contains(elt) {
+                    return Some(elt)
+                },
+            }
+        }
+    }
+
+    fn size_hint(&self) -> (uint, Option<uint>) {
+        let (_, upper) = self.iter.size_hint();
+        (0, upper)
+    }
+}
+
+impl<'a, T, S, H> Iterator<&'a T> for Difference<'a, T, H>
+    where T: Eq + Hash<S>, H: Hasher<S>
+{
+    fn next(&mut self) -> Option<&'a T> {
+        loop {
+            match self.iter.next() {
+                None => return None,
+                Some(elt) => if !self.other.contains(elt) {
+                    return Some(elt)
+                },
+            }
+        }
+    }
+
+    fn size_hint(&self) -> (uint, Option<uint>) {
+        let (_, upper) = self.iter.size_hint();
+        (0, upper)
+    }
+}
+
+impl<'a, T, S, H> Iterator<&'a T> for SymmetricDifference<'a, T, H>
+    where T: Eq + Hash<S>, H: Hasher<S>
+{
+    fn next(&mut self) -> Option<&'a T> { self.iter.next() }
+    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+}
+
+impl<'a, T, S, H> Iterator<&'a T> for Union<'a, T, H>
+    where T: Eq + Hash<S>, H: Hasher<S>
+{
+    fn next(&mut self) -> Option<&'a T> { self.iter.next() }
+    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+}
 
 #[cfg(test)]
 mod test_set {
     use prelude::*;
 
     use super::HashSet;
-    use slice::PartialEqSlicePrelude;
 
     #[test]
     fn test_disjoint() {
@@ -785,7 +1044,7 @@ mod test_set {
         };
 
         let v = hs.into_iter().collect::<Vec<char>>();
-        assert!(['a', 'b'][] == v.as_slice() || ['b', 'a'][] == v.as_slice());
+        assert!(['a', 'b'] == v || ['b', 'a'] == v);
     }
 
     #[test]
@@ -820,7 +1079,44 @@ mod test_set {
 
         let set_str = format!("{}", set);
 
-        assert!(set_str == "{1, 2}".to_string() || set_str == "{2, 1}".to_string());
-        assert_eq!(format!("{}", empty), "{}".to_string());
+        assert!(set_str == "{1, 2}" || set_str == "{2, 1}");
+        assert_eq!(format!("{}", empty), "{}");
+    }
+
+    #[test]
+    fn test_trivial_drain() {
+        let mut s = HashSet::<int>::new();
+        for _ in s.drain() {}
+        assert!(s.is_empty());
+        drop(s);
+
+        let mut s = HashSet::<int>::new();
+        drop(s.drain());
+        assert!(s.is_empty());
+    }
+
+    #[test]
+    fn test_drain() {
+        let mut s: HashSet<int> = range(1, 100).collect();
+
+        // try this a bunch of times to make sure we don't screw up internal state.
+        for _ in range(0i, 20) {
+            assert_eq!(s.len(), 99);
+
+            {
+                let mut last_i = 0;
+                let mut d = s.drain();
+                for (i, x) in d.by_ref().take(50).enumerate() {
+                    last_i = i;
+                    assert!(x != 0);
+                }
+                assert_eq!(last_i, 49);
+            }
+
+            for _ in s.iter() { panic!("s should be empty!"); }
+
+            // reset to try again.
+            s.extend(range(1, 100));
+        }
     }
 }
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index f41ccea0aaf..8f2152c5a9d 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -10,18 +10,19 @@
 //
 // ignore-lexer-test FIXME #15883
 
-pub use self::BucketState::*;
+use self::BucketState::*;
 
 use clone::Clone;
 use cmp;
 use hash::{Hash, Hasher};
 use iter::{Iterator, count};
-use kinds::{Sized, marker};
+use kinds::{Copy, Sized, marker};
 use mem::{min_align_of, size_of};
 use mem;
 use num::{Int, UnsignedInt};
 use ops::{Deref, DerefMut, Drop};
-use option::{Some, None, Option};
+use option::Option;
+use option::Option::{Some, None};
 use ptr::{RawPtr, copy_nonoverlapping_memory, zero_memory};
 use ptr;
 use rt::heap::{allocate, deallocate};
@@ -80,12 +81,16 @@ struct RawBucket<K, V> {
     val:  *mut V
 }
 
+impl<K,V> Copy for RawBucket<K,V> {}
+
 pub struct Bucket<K, V, M> {
     raw:   RawBucket<K, V>,
     idx:   uint,
     table: M
 }
 
+impl<K,V,M:Copy> Copy for Bucket<K,V,M> {}
+
 pub struct EmptyBucket<K, V, M> {
     raw:   RawBucket<K, V>,
     idx:   uint,
@@ -119,7 +124,7 @@ struct GapThenFull<K, V, M> {
 
 /// A hash that is not zero, since we use a hash of zero to represent empty
 /// buckets.
-#[deriving(PartialEq)]
+#[deriving(PartialEq, Copy)]
 pub struct SafeHash {
     hash: u64,
 }
@@ -206,7 +211,7 @@ impl<K, V, M> Bucket<K, V, M> {
 }
 
 impl<K, V, M: Deref<RawTable<K, V>>> Bucket<K, V, M> {
-    pub fn new(table: M, hash: &SafeHash) -> Bucket<K, V, M> {
+    pub fn new(table: M, hash: SafeHash) -> Bucket<K, V, M> {
         Bucket::at_index(table, hash.inspect() as uint)
     }
 
@@ -659,17 +664,17 @@ impl<K, V> RawTable<K, V> {
         }
     }
 
-    pub fn iter_mut(&mut self) -> MutEntries<K, V> {
-        MutEntries {
+    pub fn iter_mut(&mut self) -> IterMut<K, V> {
+        IterMut {
             iter: self.raw_buckets(),
             elems_left: self.size(),
         }
     }
 
-    pub fn into_iter(self) -> MoveEntries<K, V> {
+    pub fn into_iter(self) -> IntoIter<K, V> {
         let RawBuckets { raw, hashes_end, .. } = self.raw_buckets();
         // Replace the marker regardless of lifetime bounds on parameters.
-        MoveEntries {
+        IntoIter {
             iter: RawBuckets {
                 raw: raw,
                 hashes_end: hashes_end,
@@ -679,6 +684,19 @@ impl<K, V> RawTable<K, V> {
         }
     }
 
+    pub fn drain(&mut self) -> Drain<K, V> {
+        let RawBuckets { raw, hashes_end, .. } = self.raw_buckets();
+        // Replace the marker regardless of lifetime bounds on parameters.
+        Drain {
+            iter: RawBuckets {
+                raw: raw,
+                hashes_end: hashes_end,
+                marker: marker::ContravariantLifetime::<'static>,
+            },
+            table: self,
+        }
+    }
+
     /// Returns an iterator that copies out each entry. Used while the table
     /// is being dropped.
     unsafe fn rev_move_buckets(&mut self) -> RevMoveBuckets<K, V> {
@@ -758,17 +776,23 @@ pub struct Entries<'a, K: 'a, V: 'a> {
 }
 
 /// Iterator over mutable references to entries in a table.
-pub struct MutEntries<'a, K: 'a, V: 'a> {
+pub struct IterMut<'a, K: 'a, V: 'a> {
     iter: RawBuckets<'a, K, V>,
     elems_left: uint,
 }
 
 /// Iterator over the entries in a table, consuming the table.
-pub struct MoveEntries<K, V> {
+pub struct IntoIter<K, V> {
     table: RawTable<K, V>,
     iter: RawBuckets<'static, K, V>
 }
 
+/// Iterator over the entries in a table, clearing the table.
+pub struct Drain<'a, K: 'a, V: 'a> {
+    table: &'a mut RawTable<K, V>,
+    iter: RawBuckets<'static, K, V>,
+}
+
 impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> {
     fn next(&mut self) -> Option<(&'a K, &'a V)> {
         self.iter.next().map(|bucket| {
@@ -785,7 +809,7 @@ impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> {
     }
 }
 
-impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> {
+impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for IterMut<'a, K, V> {
     fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
         self.iter.next().map(|bucket| {
             self.elems_left -= 1;
@@ -801,7 +825,7 @@ impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> {
     }
 }
 
-impl<K, V> Iterator<(SafeHash, K, V)> for MoveEntries<K, V> {
+impl<K, V> Iterator<(SafeHash, K, V)> for IntoIter<K, V> {
     fn next(&mut self) -> Option<(SafeHash, K, V)> {
         self.iter.next().map(|bucket| {
             self.table.size -= 1;
@@ -823,6 +847,36 @@ impl<K, V> Iterator<(SafeHash, K, V)> for MoveEntries<K, V> {
     }
 }
 
+impl<'a, K: 'a, V: 'a> Iterator<(SafeHash, K, V)> for Drain<'a, K, V> {
+    #[inline]
+    fn next(&mut self) -> Option<(SafeHash, K, V)> {
+        self.iter.next().map(|bucket| {
+            self.table.size -= 1;
+            unsafe {
+                (
+                    SafeHash {
+                        hash: ptr::replace(bucket.hash, EMPTY_BUCKET),
+                    },
+                    ptr::read(bucket.key as *const K),
+                    ptr::read(bucket.val as *const V)
+                )
+            }
+        })
+    }
+
+    fn size_hint(&self) -> (uint, Option<uint>) {
+        let size = self.table.size();
+        (size, Some(size))
+    }
+}
+
+#[unsafe_destructor]
+impl<'a, K: 'a, V: 'a> Drop for Drain<'a, K, V> {
+    fn drop(&mut self) {
+        for _ in *self {}
+    }
+}
+
 impl<K: Clone, V: Clone> Clone for RawTable<K, V> {
     fn clone(&self) -> RawTable<K, V> {
         unsafe {
diff --git a/src/libstd/collections/lru_cache.rs b/src/libstd/collections/lru_cache.rs
deleted file mode 100644
index 94bea37d187..00000000000
--- a/src/libstd/collections/lru_cache.rs
+++ /dev/null
@@ -1,470 +0,0 @@
-// Copyright 2013 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.
-
-
-//! A cache that holds a limited number of key-value pairs. When the
-//! capacity of the cache is exceeded, the least-recently-used
-//! (where "used" means a look-up or putting the pair into the cache)
-//! pair is automatically removed.
-//!
-//! # Example
-//!
-//! ```rust
-//! use std::collections::LruCache;
-//!
-//! let mut cache: LruCache<int, int> = LruCache::new(2);
-//! cache.insert(1, 10);
-//! cache.insert(2, 20);
-//! cache.insert(3, 30);
-//! assert!(cache.get(&1).is_none());
-//! assert_eq!(*cache.get(&2).unwrap(), 20);
-//! assert_eq!(*cache.get(&3).unwrap(), 30);
-//!
-//! cache.insert(2, 22);
-//! assert_eq!(*cache.get(&2).unwrap(), 22);
-//!
-//! cache.insert(6, 60);
-//! assert!(cache.get(&3).is_none());
-//!
-//! cache.set_capacity(1);
-//! assert!(cache.get(&2).is_none());
-//! ```
-
-use cmp::{PartialEq, Eq};
-use collections::HashMap;
-use fmt;
-use hash::Hash;
-use iter::{range, Iterator, Extend};
-use mem;
-use ops::Drop;
-use option::{Some, None, Option};
-use boxed::Box;
-use ptr;
-use result::{Ok, Err};
-
-// FIXME(conventions): implement iterators?
-// FIXME(conventions): implement indexing?
-
-struct KeyRef<K> { k: *const K }
-
-struct LruEntry<K, V> {
-    next: *mut LruEntry<K, V>,
-    prev: *mut LruEntry<K, V>,
-    key: K,
-    value: V,
-}
-
-/// An LRU Cache.
-pub struct LruCache<K, V> {
-    map: HashMap<KeyRef<K>, Box<LruEntry<K, V>>>,
-    max_size: uint,
-    head: *mut LruEntry<K, V>,
-}
-
-impl<S, K: Hash<S>> Hash<S> for KeyRef<K> {
-    fn hash(&self, state: &mut S) {
-        unsafe { (*self.k).hash(state) }
-    }
-}
-
-impl<K: PartialEq> PartialEq for KeyRef<K> {
-    fn eq(&self, other: &KeyRef<K>) -> bool {
-        unsafe{ (*self.k).eq(&*other.k) }
-    }
-}
-
-impl<K: Eq> Eq for KeyRef<K> {}
-
-impl<K, V> LruEntry<K, V> {
-    fn new(k: K, v: V) -> LruEntry<K, V> {
-        LruEntry {
-            key: k,
-            value: v,
-            next: ptr::null_mut(),
-            prev: ptr::null_mut(),
-        }
-    }
-}
-
-impl<K: Hash + Eq, V> LruCache<K, V> {
-    /// Create an LRU Cache that holds at most `capacity` items.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::LruCache;
-    /// let mut cache: LruCache<int, &str> = LruCache::new(10);
-    /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn new(capacity: uint) -> LruCache<K, V> {
-        let cache = LruCache {
-            map: HashMap::new(),
-            max_size: capacity,
-            head: unsafe{ mem::transmute(box mem::uninitialized::<LruEntry<K, V>>()) },
-        };
-        unsafe {
-            (*cache.head).next = cache.head;
-            (*cache.head).prev = cache.head;
-        }
-        return cache;
-    }
-
-    /// Deprecated: Replaced with `insert`.
-    #[deprecated = "Replaced with `insert`"]
-    pub fn put(&mut self, k: K, v: V) {
-        self.insert(k, v);
-    }
-
-    /// Inserts a key-value pair into the cache. If the key already existed, the old value is
-    /// returned.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::LruCache;
-    /// let mut cache = LruCache::new(2);
-    ///
-    /// cache.insert(1i, "a");
-    /// cache.insert(2, "b");
-    /// assert_eq!(cache.get(&1), Some(&"a"));
-    /// assert_eq!(cache.get(&2), Some(&"b"));
-    /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn insert(&mut self, k: K, v: V) -> Option<V> {
-        let (node_ptr, node_opt, old_val) = match self.map.get_mut(&KeyRef{k: &k}) {
-            Some(node) => {
-                let old_val = mem::replace(&mut node.value, v);
-                let node_ptr: *mut LruEntry<K, V> = &mut **node;
-                (node_ptr, None, Some(old_val))
-            }
-            None => {
-                let mut node = box LruEntry::new(k, v);
-                let node_ptr: *mut LruEntry<K, V> = &mut *node;
-                (node_ptr, Some(node), None)
-            }
-        };
-        match node_opt {
-            None => {
-                // Existing node, just update LRU position
-                self.detach(node_ptr);
-                self.attach(node_ptr);
-            }
-            Some(node) => {
-                let keyref = unsafe { &(*node_ptr).key };
-                self.map.insert(KeyRef{k: keyref}, node);
-                self.attach(node_ptr);
-                if self.len() > self.capacity() {
-                    self.remove_lru();
-                }
-            }
-        }
-        old_val
-    }
-
-    /// Return a value corresponding to the key in the cache.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::LruCache;
-    /// let mut cache = LruCache::new(2);
-    ///
-    /// cache.insert(1i, "a");
-    /// cache.insert(2, "b");
-    /// cache.insert(2, "c");
-    /// cache.insert(3, "d");
-    ///
-    /// assert_eq!(cache.get(&1), None);
-    /// assert_eq!(cache.get(&2), Some(&"c"));
-    /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn get(&mut self, k: &K) -> Option<&V> {
-        let (value, node_ptr_opt) = match self.map.get_mut(&KeyRef{k: k}) {
-            None => (None, None),
-            Some(node) => {
-                let node_ptr: *mut LruEntry<K, V> = &mut **node;
-                (Some(unsafe { &(*node_ptr).value }), Some(node_ptr))
-            }
-        };
-        match node_ptr_opt {
-            None => (),
-            Some(node_ptr) => {
-                self.detach(node_ptr);
-                self.attach(node_ptr);
-            }
-        }
-        return value;
-    }
-
-    /// Deprecated: Renamed to `remove`.
-    #[deprecated = "Renamed to `remove`"]
-    pub fn pop(&mut self, k: &K) -> Option<V> {
-        self.remove(k)
-    }
-
-    /// Remove and return a value corresponding to the key from the cache.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::LruCache;
-    /// let mut cache = LruCache::new(2);
-    ///
-    /// cache.insert(2i, "a");
-    ///
-    /// assert_eq!(cache.remove(&1), None);
-    /// assert_eq!(cache.remove(&2), Some("a"));
-    /// assert_eq!(cache.remove(&2), None);
-    /// assert_eq!(cache.len(), 0);
-    /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn remove(&mut self, k: &K) -> Option<V> {
-        match self.map.remove(&KeyRef{k: k}) {
-            None => None,
-            Some(lru_entry) => Some(lru_entry.value)
-        }
-    }
-
-    /// Return the maximum number of key-value pairs the cache can hold.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::LruCache;
-    /// let mut cache: LruCache<int, &str> = LruCache::new(2);
-    /// assert_eq!(cache.capacity(), 2);
-    /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn capacity(&self) -> uint {
-        self.max_size
-    }
-
-    /// Deprecated: Renamed to `set_capacity`.
-    #[deprecated = "Renamed to `set_capacity`"]
-    pub fn change_capacity(&mut self, capacity: uint) {
-        self.set_capacity(capacity)
-    }
-
-    /// Change the number of key-value pairs the cache can hold. Remove
-    /// least-recently-used key-value pairs if necessary.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::LruCache;
-    /// let mut cache = LruCache::new(2);
-    ///
-    /// cache.insert(1i, "a");
-    /// cache.insert(2, "b");
-    /// cache.insert(3, "c");
-    ///
-    /// assert_eq!(cache.get(&1), None);
-    /// assert_eq!(cache.get(&2), Some(&"b"));
-    /// assert_eq!(cache.get(&3), Some(&"c"));
-    ///
-    /// cache.set_capacity(3);
-    /// cache.insert(1i, "a");
-    /// cache.insert(2, "b");
-    ///
-    /// assert_eq!(cache.get(&1), Some(&"a"));
-    /// assert_eq!(cache.get(&2), Some(&"b"));
-    /// assert_eq!(cache.get(&3), Some(&"c"));
-    ///
-    /// cache.set_capacity(1);
-    ///
-    /// assert_eq!(cache.get(&1), None);
-    /// assert_eq!(cache.get(&2), None);
-    /// assert_eq!(cache.get(&3), Some(&"c"));
-    /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn set_capacity(&mut self, capacity: uint) {
-        for _ in range(capacity, self.len()) {
-            self.remove_lru();
-        }
-        self.max_size = capacity;
-    }
-
-    #[inline]
-    fn remove_lru(&mut self) {
-        if self.len() > 0 {
-            let lru = unsafe { (*self.head).prev };
-            self.detach(lru);
-            self.map.remove(&KeyRef{k: unsafe { &(*lru).key }});
-        }
-    }
-
-    #[inline]
-    fn detach(&mut self, node: *mut LruEntry<K, V>) {
-        unsafe {
-            (*(*node).prev).next = (*node).next;
-            (*(*node).next).prev = (*node).prev;
-        }
-    }
-
-    #[inline]
-    fn attach(&mut self, node: *mut LruEntry<K, V>) {
-        unsafe {
-            (*node).next = (*self.head).next;
-            (*node).prev = self.head;
-            (*self.head).next = node;
-            (*(*node).next).prev = node;
-        }
-    }
-
-    /// Return the number of key-value pairs in the cache.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn len(&self) -> uint { self.map.len() }
-
-    /// Returns whether the cache is currently empty.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn is_empty(&self) -> bool { self.len() == 0 }
-
-    /// Clear the cache of all key-value pairs.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn clear(&mut self) { self.map.clear(); }
-
-}
-
-impl<K: Hash + Eq, V> Extend<(K, V)> for LruCache<K, V> {
-    fn extend<T: Iterator<(K, V)>>(&mut self, mut iter: T) {
-        for (k, v) in iter{
-            self.insert(k, v);
-        }
-    }
-}
-
-impl<A: fmt::Show + Hash + Eq, B: fmt::Show> fmt::Show for LruCache<A, B> {
-    /// Return a string that lists the key-value pairs from most-recently
-    /// used to least-recently used.
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "{{"));
-        let mut cur = self.head;
-        for i in range(0, self.len()) {
-            if i > 0 { try!(write!(f, ", ")) }
-            unsafe {
-                cur = (*cur).next;
-                try!(write!(f, "{}", (*cur).key));
-            }
-            try!(write!(f, ": "));
-            unsafe {
-                try!(write!(f, "{}", (*cur).value));
-            }
-        }
-        write!(f, r"}}")
-    }
-}
-
-#[unsafe_destructor]
-impl<K, V> Drop for LruCache<K, V> {
-    fn drop(&mut self) {
-        unsafe {
-            let node: Box<LruEntry<K, V>> = mem::transmute(self.head);
-            // Prevent compiler from trying to drop the un-initialized field in the sigil node.
-            let box internal_node = node;
-            let LruEntry { next: _, prev: _, key: k, value: v } = internal_node;
-            mem::forget(k);
-            mem::forget(v);
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use prelude::*;
-    use super::LruCache;
-
-    fn assert_opt_eq<V: PartialEq>(opt: Option<&V>, v: V) {
-        assert!(opt.is_some());
-        assert!(opt.unwrap() == &v);
-    }
-
-    #[test]
-    fn test_put_and_get() {
-        let mut cache: LruCache<int, int> = LruCache::new(2);
-        cache.insert(1, 10);
-        cache.insert(2, 20);
-        assert_opt_eq(cache.get(&1), 10);
-        assert_opt_eq(cache.get(&2), 20);
-        assert_eq!(cache.len(), 2);
-    }
-
-    #[test]
-    fn test_put_update() {
-        let mut cache: LruCache<String, Vec<u8>> = LruCache::new(1);
-        cache.insert("1".to_string(), vec![10, 10]);
-        cache.insert("1".to_string(), vec![10, 19]);
-        assert_opt_eq(cache.get(&"1".to_string()), vec![10, 19]);
-        assert_eq!(cache.len(), 1);
-    }
-
-    #[test]
-    fn test_expire_lru() {
-        let mut cache: LruCache<String, String> = LruCache::new(2);
-        cache.insert("foo1".to_string(), "bar1".to_string());
-        cache.insert("foo2".to_string(), "bar2".to_string());
-        cache.insert("foo3".to_string(), "bar3".to_string());
-        assert!(cache.get(&"foo1".to_string()).is_none());
-        cache.insert("foo2".to_string(), "bar2update".to_string());
-        cache.insert("foo4".to_string(), "bar4".to_string());
-        assert!(cache.get(&"foo3".to_string()).is_none());
-    }
-
-    #[test]
-    fn test_pop() {
-        let mut cache: LruCache<int, int> = LruCache::new(2);
-        cache.insert(1, 10);
-        cache.insert(2, 20);
-        assert_eq!(cache.len(), 2);
-        let opt1 = cache.remove(&1);
-        assert!(opt1.is_some());
-        assert_eq!(opt1.unwrap(), 10);
-        assert!(cache.get(&1).is_none());
-        assert_eq!(cache.len(), 1);
-    }
-
-    #[test]
-    fn test_change_capacity() {
-        let mut cache: LruCache<int, int> = LruCache::new(2);
-        assert_eq!(cache.capacity(), 2);
-        cache.insert(1, 10);
-        cache.insert(2, 20);
-        cache.set_capacity(1);
-        assert!(cache.get(&1).is_none());
-        assert_eq!(cache.capacity(), 1);
-    }
-
-    #[test]
-    fn test_to_string() {
-        let mut cache: LruCache<int, int> = LruCache::new(3);
-        cache.insert(1, 10);
-        cache.insert(2, 20);
-        cache.insert(3, 30);
-        assert_eq!(cache.to_string(), "{3: 30, 2: 20, 1: 10}".to_string());
-        cache.insert(2, 22);
-        assert_eq!(cache.to_string(), "{2: 22, 3: 30, 1: 10}".to_string());
-        cache.insert(6, 60);
-        assert_eq!(cache.to_string(), "{6: 60, 2: 22, 3: 30}".to_string());
-        cache.get(&3);
-        assert_eq!(cache.to_string(), "{3: 30, 6: 60, 2: 22}".to_string());
-        cache.set_capacity(2);
-        assert_eq!(cache.to_string(), "{3: 30, 6: 60}".to_string());
-    }
-
-    #[test]
-    fn test_clear() {
-        let mut cache: LruCache<int, int> = LruCache::new(2);
-        cache.insert(1, 10);
-        cache.insert(2, 20);
-        cache.clear();
-        assert!(cache.get(&1).is_none());
-        assert!(cache.get(&2).is_none());
-        assert_eq!(cache.to_string(), "{}".to_string());
-    }
-}
diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs
index 3419a3d98a1..0d44e6d869a 100644
--- a/src/libstd/collections/mod.rs
+++ b/src/libstd/collections/mod.rs
@@ -24,8 +24,8 @@
 //! Rust's collections can be grouped into four major categories:
 //!
 //! * Sequences: `Vec`, `RingBuf`, `DList`, `BitV`
-//! * Maps: `HashMap`, `BTreeMap`, `TreeMap`, `TrieMap`, `VecMap`, `LruCache`
-//! * Sets: `HashSet`, `BTreeSet`, `TreeSet`, `TrieSet`, `BitVSet`, `EnumSet`
+//! * Maps: `HashMap`, `BTreeMap`, `VecMap`
+//! * Sets: `HashSet`, `BTreeSet`, `BitVSet`
 //! * Misc: `BinaryHeap`
 //!
 //! # When Should You Use Which Collection?
@@ -64,16 +64,6 @@
 //! * You want to be able to get all of the entries in order on-demand.
 //! * You want a sorted map.
 //!
-//! ### Use a `TreeMap` when:
-//! * You want a `BTreeMap`, but can't tolerate inconsistent performance.
-//! * You want a `BTreeMap`, but have *very large* keys or values.
-//! * You want a `BTreeMap`, but have keys that are expensive to compare.
-//! * You want a `BTreeMap`, but you accept arbitrary untrusted inputs.
-//!
-//! ### Use a `TrieMap` when:
-//! * You want a `HashMap`, but with many potentially large `uint` keys.
-//! * You want a `BTreeMap`, but with potentially large `uint` keys.
-//!
 //! ### Use a `VecMap` when:
 //! * You want a `HashMap` but with known to be small `uint` keys.
 //! * You want a `BTreeMap`, but with known to be small `uint` keys.
@@ -90,18 +80,11 @@
 //! ### Use a `BitVSet` when:
 //! * You want a `VecSet`.
 //!
-//! ### Use an `EnumSet` when:
-//! * You want a C-like enum, stored in a single `uint`.
-//!
 //! ### Use a `BinaryHeap` when:
 //! * You want to store a bunch of elements, but only ever want to process the "biggest"
 //! or "most important" one at any given time.
 //! * You want a priority queue.
 //!
-//! ### Use an `LruCache` when:
-//! * You want a cache that discards infrequently used items when it becomes full.
-//! * You want a least-recently-used cache.
-//!
 //! # Correct and Efficient Usage of Collections
 //!
 //! Of course, knowing which collection is the right one for the job doesn't instantly
@@ -329,15 +312,21 @@
 #![experimental]
 
 pub use core_collections::{BinaryHeap, Bitv, BitvSet, BTreeMap, BTreeSet};
-pub use core_collections::{DList, EnumSet, RingBuf};
-pub use core_collections::{TreeMap, TreeSet, TrieMap, TrieSet, VecMap};
+pub use core_collections::{DList, RingBuf, VecMap};
 
-pub use core_collections::{binary_heap, bitv, bitv_set, btree_map, btree_set, dlist, enum_set};
-pub use core_collections::{ring_buf, tree_map, tree_set, trie_map, trie_set, vec_map};
+/// Deprecated: Moved to collect-rs: https://github.com/Gankro/collect-rs/
+#[deprecated = "Moved to collect-rs: https://github.com/Gankro/collect-rs/"]
+pub use core_collections::EnumSet;
+
+pub use core_collections::{binary_heap, bitv, bitv_set, btree_map, btree_set};
+pub use core_collections::{dlist, ring_buf, vec_map};
+
+/// Deprecated: Moved to collect-rs: https://github.com/Gankro/collect-rs/
+#[deprecated = "Moved to collect-rs: https://github.com/Gankro/collect-rs/"]
+pub use core_collections::enum_set;
 
 pub use self::hash_map::HashMap;
 pub use self::hash_set::HashSet;
-pub use self::lru_cache::LruCache;
 
 mod hash;
 
@@ -350,5 +339,3 @@ pub mod hash_set {
     //! A hashset
     pub use super::hash::set::*;
 }
-
-pub mod lru_cache;
diff --git a/src/libstd/comm/blocking.rs b/src/libstd/comm/blocking.rs
new file mode 100644
index 00000000000..c477acd70aa
--- /dev/null
+++ b/src/libstd/comm/blocking.rs
@@ -0,0 +1,83 @@
+// 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.
+
+//! Generic support for building blocking abstractions.
+
+use thread::Thread;
+use sync::atomic::{AtomicBool, INIT_ATOMIC_BOOL, Ordering};
+use sync::Arc;
+use kinds::marker::{NoSend, NoSync};
+use mem;
+use clone::Clone;
+
+struct Inner {
+    thread: Thread,
+    woken: AtomicBool,
+}
+
+#[deriving(Clone)]
+pub struct SignalToken {
+    inner: Arc<Inner>,
+}
+
+pub struct WaitToken {
+    inner: Arc<Inner>,
+    no_send: NoSend,
+    no_sync: NoSync,
+}
+
+pub fn tokens() -> (WaitToken, SignalToken) {
+    let inner = Arc::new(Inner {
+        thread: Thread::current(),
+        woken: INIT_ATOMIC_BOOL,
+    });
+    let wait_token = WaitToken {
+        inner: inner.clone(),
+        no_send: NoSend,
+        no_sync: NoSync,
+    };
+    let signal_token = SignalToken {
+        inner: inner
+    };
+    (wait_token, signal_token)
+}
+
+impl SignalToken {
+    pub fn signal(&self) -> bool {
+        let wake = !self.inner.woken.compare_and_swap(false, true, Ordering::SeqCst);
+        if wake {
+            self.inner.thread.unpark();
+        }
+        wake
+    }
+
+    /// Convert to an unsafe uint value. Useful for storing in a pipe's state
+    /// flag.
+    #[inline]
+    pub unsafe fn cast_to_uint(self) -> uint {
+        mem::transmute(self.inner)
+    }
+
+    /// Convert from an unsafe uint value. Useful for retrieving a pipe's state
+    /// flag.
+    #[inline]
+    pub unsafe fn cast_from_uint(signal_ptr: uint) -> SignalToken {
+        SignalToken { inner: mem::transmute(signal_ptr) }
+    }
+
+}
+
+impl WaitToken {
+    pub fn wait(self) {
+        while !self.inner.woken.load(Ordering::SeqCst) {
+            Thread::park()
+        }
+    }
+}
diff --git a/src/libstd/comm/mod.rs b/src/libstd/comm/mod.rs
new file mode 100644
index 00000000000..7352cdfbfe7
--- /dev/null
+++ b/src/libstd/comm/mod.rs
@@ -0,0 +1,2028 @@
+// 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.
+
+//! Communication primitives for concurrent tasks
+//!
+//! Rust makes it very difficult to share data among tasks to prevent race
+//! conditions and to improve parallelism, but there is often a need for
+//! communication between concurrent tasks. The primitives defined in this
+//! module are the building blocks for synchronization in rust.
+//!
+//! This module provides message-based communication over channels, concretely
+//! defined among three types:
+//!
+//! * `Sender`
+//! * `SyncSender`
+//! * `Receiver`
+//!
+//! A `Sender` or `SyncSender` is used to send data to a `Receiver`. Both
+//! senders are clone-able such that many tasks can send simultaneously to one
+//! receiver.  These channels are *task blocking*, not *thread blocking*. This
+//! means that if one task is blocked on a channel, other tasks can continue to
+//! make progress.
+//!
+//! Rust channels come in one of two flavors:
+//!
+//! 1. An asynchronous, infinitely buffered channel. The `channel()` function
+//!    will return a `(Sender, Receiver)` tuple where all sends will be
+//!    **asynchronous** (they never block). The channel conceptually has an
+//!    infinite buffer.
+//!
+//! 2. A synchronous, bounded channel. The `sync_channel()` function will return
+//!    a `(SyncSender, Receiver)` tuple where the storage for pending messages
+//!    is a pre-allocated buffer of a fixed size. All sends will be
+//!    **synchronous** by blocking until there is buffer space available. Note
+//!    that a bound of 0 is allowed, causing the channel to become a
+//!    "rendezvous" channel where each sender atomically hands off a message to
+//!    a receiver.
+//!
+//! ## Panic Propagation
+//!
+//! In addition to being a core primitive for communicating in rust, channels
+//! are the points at which panics are propagated among tasks.  Whenever the one
+//! half of channel is closed, the other half will have its next operation
+//! `panic!`. The purpose of this is to allow propagation of panics among tasks
+//! that are linked to one another via channels.
+//!
+//! There are methods on both of senders and receivers to perform their
+//! respective operations without panicking, however.
+//!
+//! # Example
+//!
+//! Simple usage:
+//!
+//! ```
+//! use std::thread::Thread;
+//!
+//! // Create a simple streaming channel
+//! let (tx, rx) = channel();
+//! Thread::spawn(move|| {
+//!     tx.send(10i);
+//! }).detach();
+//! assert_eq!(rx.recv(), 10i);
+//! ```
+//!
+//! Shared usage:
+//!
+//! ```
+//! use std::thread::Thread;
+//!
+//! // Create a shared channel that can be sent along from many threads
+//! // where tx is the sending half (tx for transmission), and rx is the receiving
+//! // half (rx for receiving).
+//! let (tx, rx) = channel();
+//! for i in range(0i, 10i) {
+//!     let tx = tx.clone();
+//!     Thread::spawn(move|| {
+//!         tx.send(i);
+//!     }).detach()
+//! }
+//!
+//! for _ in range(0i, 10i) {
+//!     let j = rx.recv();
+//!     assert!(0 <= j && j < 10);
+//! }
+//! ```
+//!
+//! Propagating panics:
+//!
+//! ```should_fail
+//! // The call to recv() will panic!() because the channel has already hung
+//! // up (or been deallocated)
+//! let (tx, rx) = channel::<int>();
+//! drop(tx);
+//! rx.recv();
+//! ```
+//!
+//! Synchronous channels:
+//!
+//! ```
+//! use std::thread::Thread;
+//!
+//! let (tx, rx) = sync_channel::<int>(0);
+//! Thread::spawn(move|| {
+//!     // This will wait for the parent task to start receiving
+//!     tx.send(53);
+//! }).detach();
+//! rx.recv();
+//! ```
+//!
+//! Reading from a channel with a timeout requires to use a Timer together
+//! with the channel. You can use the select! macro to select either and
+//! handle the timeout case. This first example will break out of the loop
+//! after 10 seconds no matter what:
+//!
+//! ```no_run
+//! use std::io::timer::Timer;
+//! use std::time::Duration;
+//!
+//! let (tx, rx) = channel::<int>();
+//! let mut timer = Timer::new().unwrap();
+//! let timeout = timer.oneshot(Duration::seconds(10));
+//!
+//! loop {
+//!     select! {
+//!         val = rx.recv() => println!("Received {}", val),
+//!         () = timeout.recv() => {
+//!             println!("timed out, total time was more than 10 seconds");
+//!             break;
+//!         }
+//!     }
+//! }
+//! ```
+//!
+//! This second example is more costly since it allocates a new timer every
+//! time a message is received, but it allows you to timeout after the channel
+//! has been inactive for 5 seconds:
+//!
+//! ```no_run
+//! use std::io::timer::Timer;
+//! use std::time::Duration;
+//!
+//! let (tx, rx) = channel::<int>();
+//! let mut timer = Timer::new().unwrap();
+//!
+//! loop {
+//!     let timeout = timer.oneshot(Duration::seconds(5));
+//!
+//!     select! {
+//!         val = rx.recv() => println!("Received {}", val),
+//!         () = timeout.recv() => {
+//!             println!("timed out, no message received in 5 seconds");
+//!             break;
+//!         }
+//!     }
+//! }
+//! ```
+
+// A description of how Rust's channel implementation works
+//
+// Channels are supposed to be the basic building block for all other
+// concurrent primitives that are used in Rust. As a result, the channel type
+// needs to be highly optimized, flexible, and broad enough for use everywhere.
+//
+// The choice of implementation of all channels is to be built on lock-free data
+// structures. The channels themselves are then consequently also lock-free data
+// structures. As always with lock-free code, this is a very "here be dragons"
+// territory, especially because I'm unaware of any academic papers that have
+// gone into great length about channels of these flavors.
+//
+// ## Flavors of channels
+//
+// From the perspective of a consumer of this library, there is only one flavor
+// of channel. This channel can be used as a stream and cloned to allow multiple
+// senders. Under the hood, however, there are actually three flavors of
+// channels in play.
+//
+// * Oneshots - these channels are highly optimized for the one-send use case.
+//              They contain as few atomics as possible and involve one and
+//              exactly one allocation.
+// * Streams - these channels are optimized for the non-shared use case. They
+//             use a different concurrent queue that is more tailored for this
+//             use case. The initial allocation of this flavor of channel is not
+//             optimized.
+// * Shared - this is the most general form of channel that this module offers,
+//            a channel with multiple senders. This type is as optimized as it
+//            can be, but the previous two types mentioned are much faster for
+//            their use-cases.
+//
+// ## Concurrent queues
+//
+// The basic idea of Rust's Sender/Receiver types is that send() never blocks, but
+// recv() obviously blocks. This means that under the hood there must be some
+// shared and concurrent queue holding all of the actual data.
+//
+// With two flavors of channels, two flavors of queues are also used. We have
+// chosen to use queues from a well-known author that are abbreviated as SPSC
+// and MPSC (single producer, single consumer and multiple producer, single
+// consumer). SPSC queues are used for streams while MPSC queues are used for
+// shared channels.
+//
+// ### SPSC optimizations
+//
+// The SPSC queue found online is essentially a linked list of nodes where one
+// half of the nodes are the "queue of data" and the other half of nodes are a
+// cache of unused nodes. The unused nodes are used such that an allocation is
+// not required on every push() and a free doesn't need to happen on every
+// pop().
+//
+// As found online, however, the cache of nodes is of an infinite size. This
+// means that if a channel at one point in its life had 50k items in the queue,
+// then the queue will always have the capacity for 50k items. I believed that
+// this was an unnecessary limitation of the implementation, so I have altered
+// the queue to optionally have a bound on the cache size.
+//
+// By default, streams will have an unbounded SPSC queue with a small-ish cache
+// size. The hope is that the cache is still large enough to have very fast
+// send() operations while not too large such that millions of channels can
+// coexist at once.
+//
+// ### MPSC optimizations
+//
+// Right now the MPSC queue has not been optimized. Like the SPSC queue, it uses
+// a linked list under the hood to earn its unboundedness, but I have not put
+// forth much effort into having a cache of nodes similar to the SPSC queue.
+//
+// For now, I believe that this is "ok" because shared channels are not the most
+// common type, but soon we may wish to revisit this queue choice and determine
+// another candidate for backend storage of shared channels.
+//
+// ## Overview of the Implementation
+//
+// Now that there's a little background on the concurrent queues used, it's
+// worth going into much more detail about the channels themselves. The basic
+// pseudocode for a send/recv are:
+//
+//
+//      send(t)                             recv()
+//        queue.push(t)                       return if queue.pop()
+//        if increment() == -1                deschedule {
+//          wakeup()                            if decrement() > 0
+//                                                cancel_deschedule()
+//                                            }
+//                                            queue.pop()
+//
+// As mentioned before, there are no locks in this implementation, only atomic
+// instructions are used.
+//
+// ### The internal atomic counter
+//
+// Every channel has a shared counter with each half to keep track of the size
+// of the queue. This counter is used to abort descheduling by the receiver and
+// to know when to wake up on the sending side.
+//
+// As seen in the pseudocode, senders will increment this count and receivers
+// will decrement the count. The theory behind this is that if a sender sees a
+// -1 count, it will wake up the receiver, and if the receiver sees a 1+ count,
+// then it doesn't need to block.
+//
+// The recv() method has a beginning call to pop(), and if successful, it needs
+// to decrement the count. It is a crucial implementation detail that this
+// decrement does *not* happen to the shared counter. If this were the case,
+// then it would be possible for the counter to be very negative when there were
+// no receivers waiting, in which case the senders would have to determine when
+// it was actually appropriate to wake up a receiver.
+//
+// Instead, the "steal count" is kept track of separately (not atomically
+// because it's only used by receivers), and then the decrement() call when
+// descheduling will lump in all of the recent steals into one large decrement.
+//
+// The implication of this is that if a sender sees a -1 count, then there's
+// guaranteed to be a waiter waiting!
+//
+// ## Native Implementation
+//
+// A major goal of these channels is to work seamlessly on and off the runtime.
+// All of the previous race conditions have been worded in terms of
+// scheduler-isms (which is obviously not available without the runtime).
+//
+// For now, native usage of channels (off the runtime) will fall back onto
+// mutexes/cond vars for descheduling/atomic decisions. The no-contention path
+// is still entirely lock-free, the "deschedule" blocks above are surrounded by
+// a mutex and the "wakeup" blocks involve grabbing a mutex and signaling on a
+// condition variable.
+//
+// ## Select
+//
+// Being able to support selection over channels has greatly influenced this
+// design, and not only does selection need to work inside the runtime, but also
+// outside the runtime.
+//
+// The implementation is fairly straightforward. The goal of select() is not to
+// return some data, but only to return which channel can receive data without
+// blocking. The implementation is essentially the entire blocking procedure
+// followed by an increment as soon as its woken up. The cancellation procedure
+// involves an increment and swapping out of to_wake to acquire ownership of the
+// task to unblock.
+//
+// Sadly this current implementation requires multiple allocations, so I have
+// seen the throughput of select() be much worse than it should be. I do not
+// believe that there is anything fundamental that needs to change about these
+// channels, however, in order to support a more efficient select().
+//
+// # Conclusion
+//
+// And now that you've seen all the races that I found and attempted to fix,
+// here's the code for you to find some more!
+
+use core::prelude::*;
+
+pub use self::TryRecvError::*;
+pub use self::TrySendError::*;
+use self::Flavor::*;
+
+use alloc::arc::Arc;
+use core::kinds::marker;
+use core::mem;
+use core::cell::UnsafeCell;
+
+pub use self::select::{Select, Handle};
+use self::select::StartResult;
+use self::select::StartResult::*;
+use self::blocking::SignalToken;
+
+macro_rules! test {
+    { fn $name:ident() $b:block $(#[$a:meta])*} => (
+        mod $name {
+            #![allow(unused_imports)]
+
+            use prelude::*;
+            use rt;
+
+            use comm::*;
+            use super::*;
+            use thread::Thread;
+
+            $(#[$a])* #[test] fn f() { $b }
+        }
+    )
+}
+
+mod blocking;
+mod oneshot;
+mod select;
+mod shared;
+mod stream;
+mod sync;
+mod mpsc_queue;
+mod spsc_queue;
+
+/// The receiving-half of Rust's channel type. This half can only be owned by
+/// one task
+#[unstable]
+pub struct Receiver<T> {
+    inner: UnsafeCell<Flavor<T>>,
+    // can't share in an arc
+    _marker: marker::NoSync,
+}
+
+/// An iterator over messages on a receiver, this iterator will block
+/// whenever `next` is called, waiting for a new message, and `None` will be
+/// returned when the corresponding channel has hung up.
+#[unstable]
+pub struct Messages<'a, T:'a> {
+    rx: &'a Receiver<T>
+}
+
+/// The sending-half of Rust's asynchronous channel type. This half can only be
+/// owned by one task, but it can be cloned to send to other tasks.
+#[unstable]
+pub struct Sender<T> {
+    inner: UnsafeCell<Flavor<T>>,
+    // can't share in an arc
+    _marker: marker::NoSync,
+}
+
+/// The sending-half of Rust's synchronous channel type. This half can only be
+/// owned by one task, but it can be cloned to send to other tasks.
+#[unstable = "this type may be renamed, but it will always exist"]
+pub struct SyncSender<T> {
+    inner: Arc<UnsafeCell<sync::Packet<T>>>,
+    // can't share in an arc
+    _marker: marker::NoSync,
+}
+
+/// This enumeration is the list of the possible reasons that try_recv could not
+/// return data when called.
+#[deriving(PartialEq, Clone, Copy, Show)]
+#[experimental = "this is likely to be removed in changing try_recv()"]
+pub enum TryRecvError {
+    /// This channel is currently empty, but the sender(s) have not yet
+    /// disconnected, so data may yet become available.
+    Empty,
+    /// This channel's sending half has become disconnected, and there will
+    /// never be any more data received on this channel
+    Disconnected,
+}
+
+/// This enumeration is the list of the possible error outcomes for the
+/// `SyncSender::try_send` method.
+#[deriving(PartialEq, Clone, Show)]
+#[experimental = "this is likely to be removed in changing try_send()"]
+pub enum TrySendError<T> {
+    /// The data could not be sent on the channel because it would require that
+    /// the callee block to send the data.
+    ///
+    /// If this is a buffered channel, then the buffer is full at this time. If
+    /// this is not a buffered channel, then there is no receiver available to
+    /// acquire the data.
+    Full(T),
+    /// This channel's receiving half has disconnected, so the data could not be
+    /// sent. The data is returned back to the callee in this case.
+    RecvDisconnected(T),
+}
+
+enum Flavor<T> {
+    Oneshot(Arc<UnsafeCell<oneshot::Packet<T>>>),
+    Stream(Arc<UnsafeCell<stream::Packet<T>>>),
+    Shared(Arc<UnsafeCell<shared::Packet<T>>>),
+    Sync(Arc<UnsafeCell<sync::Packet<T>>>),
+}
+
+#[doc(hidden)]
+trait UnsafeFlavor<T> {
+    fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>>;
+    unsafe fn inner_mut<'a>(&'a self) -> &'a mut Flavor<T> {
+        &mut *self.inner_unsafe().get()
+    }
+    unsafe fn inner<'a>(&'a self) -> &'a Flavor<T> {
+        &*self.inner_unsafe().get()
+    }
+}
+impl<T> UnsafeFlavor<T> for Sender<T> {
+    fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>> {
+        &self.inner
+    }
+}
+impl<T> UnsafeFlavor<T> for Receiver<T> {
+    fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>> {
+        &self.inner
+    }
+}
+
+/// Creates a new asynchronous channel, returning the sender/receiver halves.
+///
+/// All data sent on the sender will become available on the receiver, and no
+/// send will block the calling task (this channel has an "infinite buffer").
+///
+/// # Example
+///
+/// ```
+/// use std::thread::Thread;
+///
+/// // tx is is the sending half (tx for transmission), and rx is the receiving
+/// // half (rx for receiving).
+/// let (tx, rx) = channel();
+///
+/// // Spawn off an expensive computation
+/// Thread::spawn(move|| {
+/// #   fn expensive_computation() {}
+///     tx.send(expensive_computation());
+/// }).detach();
+///
+/// // Do some useful work for awhile
+///
+/// // Let's see what that answer was
+/// println!("{}", rx.recv());
+/// ```
+#[unstable]
+pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
+    let a = Arc::new(UnsafeCell::new(oneshot::Packet::new()));
+    (Sender::new(Oneshot(a.clone())), Receiver::new(Oneshot(a)))
+}
+
+/// Creates a new synchronous, bounded channel.
+///
+/// Like asynchronous channels, the `Receiver` will block until a message
+/// becomes available. These channels differ greatly in the semantics of the
+/// sender from asynchronous channels, however.
+///
+/// This channel has an internal buffer on which messages will be queued. When
+/// the internal buffer becomes full, future sends will *block* waiting for the
+/// buffer to open up. Note that a buffer size of 0 is valid, in which case this
+/// becomes  "rendezvous channel" where each send will not return until a recv
+/// is paired with it.
+///
+/// As with asynchronous channels, all senders will panic in `send` if the
+/// `Receiver` has been destroyed.
+///
+/// # Example
+///
+/// ```
+/// use std::thread::Thread;
+///
+/// let (tx, rx) = sync_channel(1);
+///
+/// // this returns immediately
+/// tx.send(1i);
+///
+/// Thread::spawn(move|| {
+///     // this will block until the previous message has been received
+///     tx.send(2i);
+/// }).detach();
+///
+/// assert_eq!(rx.recv(), 1i);
+/// assert_eq!(rx.recv(), 2i);
+/// ```
+#[unstable = "this function may be renamed to more accurately reflect the type \
+              of channel that is is creating"]
+pub fn sync_channel<T: Send>(bound: uint) -> (SyncSender<T>, Receiver<T>) {
+    let a = Arc::new(UnsafeCell::new(sync::Packet::new(bound)));
+    (SyncSender::new(a.clone()), Receiver::new(Sync(a)))
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Sender
+////////////////////////////////////////////////////////////////////////////////
+
+impl<T: Send> Sender<T> {
+    fn new(inner: Flavor<T>) -> Sender<T> {
+        Sender {
+            inner: UnsafeCell::new(inner),
+            _marker: marker::NoSync,
+        }
+    }
+
+    /// Sends a value along this channel to be received by the corresponding
+    /// receiver.
+    ///
+    /// Rust channels are infinitely buffered so this method will never block.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if the other end of the channel has hung up.
+    /// This means that if the corresponding receiver has fallen out of scope,
+    /// this function will trigger a panic message saying that a message is
+    /// being sent on a closed channel.
+    ///
+    /// Note that if this function does *not* panic, it does not mean that the
+    /// data will be successfully received. All sends are placed into a queue,
+    /// so it is possible for a send to succeed (the other end is alive), but
+    /// then the other end could immediately disconnect.
+    ///
+    /// The purpose of this functionality is to propagate panics among tasks.
+    /// If a panic is not desired, then consider using the `send_opt` method
+    #[experimental = "this function is being considered candidate for removal \
+                      to adhere to the general guidelines of rust"]
+    pub fn send(&self, t: T) {
+        if self.send_opt(t).is_err() {
+            panic!("sending on a closed channel");
+        }
+    }
+
+    /// Attempts to send a value on this channel, returning it back if it could
+    /// not be sent.
+    ///
+    /// A successful send occurs when it is determined that the other end of
+    /// the channel has not hung up already. An unsuccessful send would be one
+    /// where the corresponding receiver has already been deallocated. Note
+    /// that a return value of `Err` means that the data will never be
+    /// received, but a return value of `Ok` does *not* mean that the data
+    /// will be received.  It is possible for the corresponding receiver to
+    /// hang up immediately after this function returns `Ok`.
+    ///
+    /// Like `send`, this method will never block.
+    ///
+    /// # Panics
+    ///
+    /// This method will never panic, it will return the message back to the
+    /// caller if the other end is disconnected
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// let (tx, rx) = channel();
+    ///
+    /// // This send is always successful
+    /// assert_eq!(tx.send_opt(1i), Ok(()));
+    ///
+    /// // This send will fail because the receiver is gone
+    /// drop(rx);
+    /// assert_eq!(tx.send_opt(1i), Err(1));
+    /// ```
+    #[unstable = "this function may be renamed to send() in the future"]
+    pub fn send_opt(&self, t: T) -> Result<(), T> {
+        let (new_inner, ret) = match *unsafe { self.inner() } {
+            Oneshot(ref p) => {
+                unsafe {
+                    let p = p.get();
+                    if !(*p).sent() {
+                        return (*p).send(t);
+                    } else {
+                        let a = Arc::new(UnsafeCell::new(stream::Packet::new()));
+                        match (*p).upgrade(Receiver::new(Stream(a.clone()))) {
+                            oneshot::UpSuccess => {
+                                let ret = (*a.get()).send(t);
+                                (a, ret)
+                            }
+                            oneshot::UpDisconnected => (a, Err(t)),
+                            oneshot::UpWoke(token) => {
+                                // This send cannot panic because the thread is
+                                // asleep (we're looking at it), so the receiver
+                                // can't go away.
+                                (*a.get()).send(t).ok().unwrap();
+                                token.signal();
+                                (a, Ok(()))
+                            }
+                        }
+                    }
+                }
+            }
+            Stream(ref p) => return unsafe { (*p.get()).send(t) },
+            Shared(ref p) => return unsafe { (*p.get()).send(t) },
+            Sync(..) => unreachable!(),
+        };
+
+        unsafe {
+            let tmp = Sender::new(Stream(new_inner));
+            mem::swap(self.inner_mut(), tmp.inner_mut());
+        }
+        return ret;
+    }
+}
+
+#[stable]
+impl<T: Send> Clone for Sender<T> {
+    fn clone(&self) -> Sender<T> {
+        let (packet, sleeper, guard) = match *unsafe { self.inner() } {
+            Oneshot(ref p) => {
+                let a = Arc::new(UnsafeCell::new(shared::Packet::new()));
+                unsafe {
+                    let guard = (*a.get()).postinit_lock();
+                    match (*p.get()).upgrade(Receiver::new(Shared(a.clone()))) {
+                        oneshot::UpSuccess |
+                        oneshot::UpDisconnected => (a, None, guard),
+                        oneshot::UpWoke(task) => (a, Some(task), guard)
+                    }
+                }
+            }
+            Stream(ref p) => {
+                let a = Arc::new(UnsafeCell::new(shared::Packet::new()));
+                unsafe {
+                    let guard = (*a.get()).postinit_lock();
+                    match (*p.get()).upgrade(Receiver::new(Shared(a.clone()))) {
+                        stream::UpSuccess |
+                        stream::UpDisconnected => (a, None, guard),
+                        stream::UpWoke(task) => (a, Some(task), guard),
+                    }
+                }
+            }
+            Shared(ref p) => {
+                unsafe { (*p.get()).clone_chan(); }
+                return Sender::new(Shared(p.clone()));
+            }
+            Sync(..) => unreachable!(),
+        };
+
+        unsafe {
+            (*packet.get()).inherit_blocker(sleeper, guard);
+
+            let tmp = Sender::new(Shared(packet.clone()));
+            mem::swap(self.inner_mut(), tmp.inner_mut());
+        }
+        Sender::new(Shared(packet))
+    }
+}
+
+#[unsafe_destructor]
+impl<T: Send> Drop for Sender<T> {
+    fn drop(&mut self) {
+        match *unsafe { self.inner_mut() } {
+            Oneshot(ref mut p) => unsafe { (*p.get()).drop_chan(); },
+            Stream(ref mut p) => unsafe { (*p.get()).drop_chan(); },
+            Shared(ref mut p) => unsafe { (*p.get()).drop_chan(); },
+            Sync(..) => unreachable!(),
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// SyncSender
+////////////////////////////////////////////////////////////////////////////////
+
+impl<T: Send> SyncSender<T> {
+    fn new(inner: Arc<UnsafeCell<sync::Packet<T>>>) -> SyncSender<T> {
+        SyncSender { inner: inner, _marker: marker::NoSync }
+    }
+
+    /// Sends a value on this synchronous channel.
+    ///
+    /// This function will *block* until space in the internal buffer becomes
+    /// available or a receiver is available to hand off the message to.
+    ///
+    /// Note that a successful send does *not* guarantee that the receiver will
+    /// ever see the data if there is a buffer on this channel. Messages may be
+    /// enqueued in the internal buffer for the receiver to receive at a later
+    /// time. If the buffer size is 0, however, it can be guaranteed that the
+    /// receiver has indeed received the data if this function returns success.
+    ///
+    /// # Panics
+    ///
+    /// Similarly to `Sender::send`, this function will panic if the
+    /// corresponding `Receiver` for this channel has disconnected. This
+    /// behavior is used to propagate panics among tasks.
+    ///
+    /// If a panic is not desired, you can achieve the same semantics with the
+    /// `SyncSender::send_opt` method which will not panic if the receiver
+    /// disconnects.
+    #[experimental = "this function is being considered candidate for removal \
+                      to adhere to the general guidelines of rust"]
+    pub fn send(&self, t: T) {
+        if self.send_opt(t).is_err() {
+            panic!("sending on a closed channel");
+        }
+    }
+
+    /// Send a value on a channel, returning it back if the receiver
+    /// disconnected
+    ///
+    /// This method will *block* to send the value `t` on the channel, but if
+    /// the value could not be sent due to the receiver disconnecting, the value
+    /// is returned back to the callee. This function is similar to `try_send`,
+    /// except that it will block if the channel is currently full.
+    ///
+    /// # Panics
+    ///
+    /// This function cannot panic.
+    #[unstable = "this function may be renamed to send() in the future"]
+    pub fn send_opt(&self, t: T) -> Result<(), T> {
+        unsafe { (*self.inner.get()).send(t) }
+    }
+
+    /// Attempts to send a value on this channel without blocking.
+    ///
+    /// This method differs from `send_opt` by returning immediately if the
+    /// channel's buffer is full or no receiver is waiting to acquire some
+    /// data. Compared with `send_opt`, this function has two failure cases
+    /// instead of one (one for disconnection, one for a full buffer).
+    ///
+    /// See `SyncSender::send` for notes about guarantees of whether the
+    /// receiver has received the data or not if this function is successful.
+    ///
+    /// # Panics
+    ///
+    /// This function cannot panic
+    #[unstable = "the return type of this function is candidate for \
+                  modification"]
+    pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
+        unsafe { (*self.inner.get()).try_send(t) }
+    }
+}
+
+#[stable]
+impl<T: Send> Clone for SyncSender<T> {
+    fn clone(&self) -> SyncSender<T> {
+        unsafe { (*self.inner.get()).clone_chan(); }
+        return SyncSender::new(self.inner.clone());
+    }
+}
+
+#[unsafe_destructor]
+impl<T: Send> Drop for SyncSender<T> {
+    fn drop(&mut self) {
+        unsafe { (*self.inner.get()).drop_chan(); }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Receiver
+////////////////////////////////////////////////////////////////////////////////
+
+impl<T: Send> Receiver<T> {
+    fn new(inner: Flavor<T>) -> Receiver<T> {
+        Receiver { inner: UnsafeCell::new(inner), _marker: marker::NoSync }
+    }
+
+    /// Blocks waiting for a value on this receiver
+    ///
+    /// This function will block if necessary to wait for a corresponding send
+    /// on the channel from its paired `Sender` structure. This receiver will
+    /// be woken up when data is ready, and the data will be returned.
+    ///
+    /// # Panics
+    ///
+    /// Similar to channels, this method will trigger a task panic if the
+    /// other end of the channel has hung up (been deallocated). The purpose of
+    /// this is to propagate panics among tasks.
+    ///
+    /// If a panic is not desired, then there are two options:
+    ///
+    /// * If blocking is still desired, the `recv_opt` method will return `None`
+    ///   when the other end hangs up
+    ///
+    /// * If blocking is not desired, then the `try_recv` method will attempt to
+    ///   peek at a value on this receiver.
+    #[experimental = "this function is being considered candidate for removal \
+                      to adhere to the general guidelines of rust"]
+    pub fn recv(&self) -> T {
+        match self.recv_opt() {
+            Ok(t) => t,
+            Err(()) => panic!("receiving on a closed channel"),
+        }
+    }
+
+    /// Attempts to return a pending value on this receiver without blocking
+    ///
+    /// This method will never block the caller in order to wait for data to
+    /// become available. Instead, this will always return immediately with a
+    /// possible option of pending data on the channel.
+    ///
+    /// This is useful for a flavor of "optimistic check" before deciding to
+    /// block on a receiver.
+    ///
+    /// # Panics
+    ///
+    /// This function cannot panic.
+    #[unstable = "the return type of this function may be altered"]
+    pub fn try_recv(&self) -> Result<T, TryRecvError> {
+        loop {
+            let new_port = match *unsafe { self.inner() } {
+                Oneshot(ref p) => {
+                    match unsafe { (*p.get()).try_recv() } {
+                        Ok(t) => return Ok(t),
+                        Err(oneshot::Empty) => return Err(Empty),
+                        Err(oneshot::Disconnected) => return Err(Disconnected),
+                        Err(oneshot::Upgraded(rx)) => rx,
+                    }
+                }
+                Stream(ref p) => {
+                    match unsafe { (*p.get()).try_recv() } {
+                        Ok(t) => return Ok(t),
+                        Err(stream::Empty) => return Err(Empty),
+                        Err(stream::Disconnected) => return Err(Disconnected),
+                        Err(stream::Upgraded(rx)) => rx,
+                    }
+                }
+                Shared(ref p) => {
+                    match unsafe { (*p.get()).try_recv() } {
+                        Ok(t) => return Ok(t),
+                        Err(shared::Empty) => return Err(Empty),
+                        Err(shared::Disconnected) => return Err(Disconnected),
+                    }
+                }
+                Sync(ref p) => {
+                    match unsafe { (*p.get()).try_recv() } {
+                        Ok(t) => return Ok(t),
+                        Err(sync::Empty) => return Err(Empty),
+                        Err(sync::Disconnected) => return Err(Disconnected),
+                    }
+                }
+            };
+            unsafe {
+                mem::swap(self.inner_mut(),
+                          new_port.inner_mut());
+            }
+        }
+    }
+
+    /// Attempt to wait for a value on this receiver, but does not panic if the
+    /// corresponding channel has hung up.
+    ///
+    /// This implementation of iterators for ports will always block if there is
+    /// not data available on the receiver, but it will not panic in the case
+    /// that the channel has been deallocated.
+    ///
+    /// In other words, this function has the same semantics as the `recv`
+    /// method except for the panic aspect.
+    ///
+    /// If the channel has hung up, then `Err` is returned. Otherwise `Ok` of
+    /// the value found on the receiver is returned.
+    #[unstable = "this function may be renamed to recv()"]
+    pub fn recv_opt(&self) -> Result<T, ()> {
+        loop {
+            let new_port = match *unsafe { self.inner() } {
+                Oneshot(ref p) => {
+                    match unsafe { (*p.get()).recv() } {
+                        Ok(t) => return Ok(t),
+                        Err(oneshot::Empty) => return unreachable!(),
+                        Err(oneshot::Disconnected) => return Err(()),
+                        Err(oneshot::Upgraded(rx)) => rx,
+                    }
+                }
+                Stream(ref p) => {
+                    match unsafe { (*p.get()).recv() } {
+                        Ok(t) => return Ok(t),
+                        Err(stream::Empty) => return unreachable!(),
+                        Err(stream::Disconnected) => return Err(()),
+                        Err(stream::Upgraded(rx)) => rx,
+                    }
+                }
+                Shared(ref p) => {
+                    match unsafe { (*p.get()).recv() } {
+                        Ok(t) => return Ok(t),
+                        Err(shared::Empty) => return unreachable!(),
+                        Err(shared::Disconnected) => return Err(()),
+                    }
+                }
+                Sync(ref p) => return unsafe { (*p.get()).recv() }
+            };
+            unsafe {
+                mem::swap(self.inner_mut(), new_port.inner_mut());
+            }
+        }
+    }
+
+    /// Returns an iterator that will block waiting for messages, but never
+    /// `panic!`. It will return `None` when the channel has hung up.
+    #[unstable]
+    pub fn iter<'a>(&'a self) -> Messages<'a, T> {
+        Messages { rx: self }
+    }
+}
+
+impl<T: Send> select::Packet for Receiver<T> {
+    fn can_recv(&self) -> bool {
+        loop {
+            let new_port = match *unsafe { self.inner() } {
+                Oneshot(ref p) => {
+                    match unsafe { (*p.get()).can_recv() } {
+                        Ok(ret) => return ret,
+                        Err(upgrade) => upgrade,
+                    }
+                }
+                Stream(ref p) => {
+                    match unsafe { (*p.get()).can_recv() } {
+                        Ok(ret) => return ret,
+                        Err(upgrade) => upgrade,
+                    }
+                }
+                Shared(ref p) => {
+                    return unsafe { (*p.get()).can_recv() };
+                }
+                Sync(ref p) => {
+                    return unsafe { (*p.get()).can_recv() };
+                }
+            };
+            unsafe {
+                mem::swap(self.inner_mut(),
+                          new_port.inner_mut());
+            }
+        }
+    }
+
+    fn start_selection(&self, mut token: SignalToken) -> StartResult {
+        loop {
+            let (t, new_port) = match *unsafe { self.inner() } {
+                Oneshot(ref p) => {
+                    match unsafe { (*p.get()).start_selection(token) } {
+                        oneshot::SelSuccess => return Installed,
+                        oneshot::SelCanceled => return Abort,
+                        oneshot::SelUpgraded(t, rx) => (t, rx),
+                    }
+                }
+                Stream(ref p) => {
+                    match unsafe { (*p.get()).start_selection(token) } {
+                        stream::SelSuccess => return Installed,
+                        stream::SelCanceled => return Abort,
+                        stream::SelUpgraded(t, rx) => (t, rx),
+                    }
+                }
+                Shared(ref p) => {
+                    return unsafe { (*p.get()).start_selection(token) };
+                }
+                Sync(ref p) => {
+                    return unsafe { (*p.get()).start_selection(token) };
+                }
+            };
+            token = t;
+            unsafe {
+                mem::swap(self.inner_mut(), new_port.inner_mut());
+            }
+        }
+    }
+
+    fn abort_selection(&self) -> bool {
+        let mut was_upgrade = false;
+        loop {
+            let result = match *unsafe { self.inner() } {
+                Oneshot(ref p) => unsafe { (*p.get()).abort_selection() },
+                Stream(ref p) => unsafe {
+                    (*p.get()).abort_selection(was_upgrade)
+                },
+                Shared(ref p) => return unsafe {
+                    (*p.get()).abort_selection(was_upgrade)
+                },
+                Sync(ref p) => return unsafe {
+                    (*p.get()).abort_selection()
+                },
+            };
+            let new_port = match result { Ok(b) => return b, Err(p) => p };
+            was_upgrade = true;
+            unsafe {
+                mem::swap(self.inner_mut(),
+                          new_port.inner_mut());
+            }
+        }
+    }
+}
+
+#[unstable]
+impl<'a, T: Send> Iterator<T> for Messages<'a, T> {
+    fn next(&mut self) -> Option<T> { self.rx.recv_opt().ok() }
+}
+
+#[unsafe_destructor]
+impl<T: Send> Drop for Receiver<T> {
+    fn drop(&mut self) {
+        match *unsafe { self.inner_mut() } {
+            Oneshot(ref mut p) => unsafe { (*p.get()).drop_port(); },
+            Stream(ref mut p) => unsafe { (*p.get()).drop_port(); },
+            Shared(ref mut p) => unsafe { (*p.get()).drop_port(); },
+            Sync(ref mut p) => unsafe { (*p.get()).drop_port(); },
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use prelude::*;
+
+    use os;
+    use super::*;
+
+    pub fn stress_factor() -> uint {
+        match os::getenv("RUST_TEST_STRESS") {
+            Some(val) => from_str::<uint>(val.as_slice()).unwrap(),
+            None => 1,
+        }
+    }
+
+    test! { fn smoke() {
+        let (tx, rx) = channel::<int>();
+        tx.send(1);
+        assert_eq!(rx.recv(), 1);
+    } }
+
+    test! { fn drop_full() {
+        let (tx, _rx) = channel();
+        tx.send(box 1i);
+    } }
+
+    test! { fn drop_full_shared() {
+        let (tx, _rx) = channel();
+        drop(tx.clone());
+        drop(tx.clone());
+        tx.send(box 1i);
+    } }
+
+    test! { fn smoke_shared() {
+        let (tx, rx) = channel::<int>();
+        tx.send(1);
+        assert_eq!(rx.recv(), 1);
+        let tx = tx.clone();
+        tx.send(1);
+        assert_eq!(rx.recv(), 1);
+    } }
+
+    test! { fn smoke_threads() {
+        let (tx, rx) = channel::<int>();
+        spawn(move|| {
+            tx.send(1);
+        });
+        assert_eq!(rx.recv(), 1);
+    } }
+
+    test! { fn smoke_port_gone() {
+        let (tx, rx) = channel::<int>();
+        drop(rx);
+        tx.send(1);
+    } #[should_fail] }
+
+    test! { fn smoke_shared_port_gone() {
+        let (tx, rx) = channel::<int>();
+        drop(rx);
+        tx.send(1);
+    } #[should_fail] }
+
+    test! { fn smoke_shared_port_gone2() {
+        let (tx, rx) = channel::<int>();
+        drop(rx);
+        let tx2 = tx.clone();
+        drop(tx);
+        tx2.send(1);
+    } #[should_fail] }
+
+    test! { fn port_gone_concurrent() {
+        let (tx, rx) = channel::<int>();
+        spawn(move|| {
+            rx.recv();
+        });
+        loop { tx.send(1) }
+    } #[should_fail] }
+
+    test! { fn port_gone_concurrent_shared() {
+        let (tx, rx) = channel::<int>();
+        let tx2 = tx.clone();
+        spawn(move|| {
+            rx.recv();
+        });
+        loop {
+            tx.send(1);
+            tx2.send(1);
+        }
+    } #[should_fail] }
+
+    test! { fn smoke_chan_gone() {
+        let (tx, rx) = channel::<int>();
+        drop(tx);
+        rx.recv();
+    } #[should_fail] }
+
+    test! { fn smoke_chan_gone_shared() {
+        let (tx, rx) = channel::<()>();
+        let tx2 = tx.clone();
+        drop(tx);
+        drop(tx2);
+        rx.recv();
+    } #[should_fail] }
+
+    test! { fn chan_gone_concurrent() {
+        let (tx, rx) = channel::<int>();
+        spawn(move|| {
+            tx.send(1);
+            tx.send(1);
+        });
+        loop { rx.recv(); }
+    } #[should_fail] }
+
+    test! { fn stress() {
+        let (tx, rx) = channel::<int>();
+        spawn(move|| {
+            for _ in range(0u, 10000) { tx.send(1i); }
+        });
+        for _ in range(0u, 10000) {
+            assert_eq!(rx.recv(), 1);
+        }
+    } }
+
+    test! { fn stress_shared() {
+        static AMT: uint = 10000;
+        static NTHREADS: uint = 8;
+        let (tx, rx) = channel::<int>();
+        let (dtx, drx) = channel::<()>();
+
+        spawn(move|| {
+            for _ in range(0, AMT * NTHREADS) {
+                assert_eq!(rx.recv(), 1);
+            }
+            match rx.try_recv() {
+                Ok(..) => panic!(),
+                _ => {}
+            }
+            dtx.send(());
+        });
+
+        for _ in range(0, NTHREADS) {
+            let tx = tx.clone();
+            spawn(move|| {
+                for _ in range(0, AMT) { tx.send(1); }
+            });
+        }
+        drop(tx);
+        drx.recv();
+    } }
+
+    #[test]
+    fn send_from_outside_runtime() {
+        let (tx1, rx1) = channel::<()>();
+        let (tx2, rx2) = channel::<int>();
+        let (tx3, rx3) = channel::<()>();
+        let tx4 = tx3.clone();
+        spawn(move|| {
+            tx1.send(());
+            for _ in range(0i, 40) {
+                assert_eq!(rx2.recv(), 1);
+            }
+            tx3.send(());
+        });
+        rx1.recv();
+        spawn(move|| {
+            for _ in range(0i, 40) {
+                tx2.send(1);
+            }
+            tx4.send(());
+        });
+        rx3.recv();
+        rx3.recv();
+    }
+
+    #[test]
+    fn recv_from_outside_runtime() {
+        let (tx, rx) = channel::<int>();
+        let (dtx, drx) = channel();
+        spawn(move|| {
+            for _ in range(0i, 40) {
+                assert_eq!(rx.recv(), 1);
+            }
+            dtx.send(());
+        });
+        for _ in range(0u, 40) {
+            tx.send(1);
+        }
+        drx.recv();
+    }
+
+    #[test]
+    fn no_runtime() {
+        let (tx1, rx1) = channel::<int>();
+        let (tx2, rx2) = channel::<int>();
+        let (tx3, rx3) = channel::<()>();
+        let tx4 = tx3.clone();
+        spawn(move|| {
+            assert_eq!(rx1.recv(), 1);
+            tx2.send(2);
+            tx4.send(());
+        });
+        spawn(move|| {
+            tx1.send(1);
+            assert_eq!(rx2.recv(), 2);
+            tx3.send(());
+        });
+        rx3.recv();
+        rx3.recv();
+    }
+
+    test! { fn oneshot_single_thread_close_port_first() {
+        // Simple test of closing without sending
+        let (_tx, rx) = channel::<int>();
+        drop(rx);
+    } }
+
+    test! { fn oneshot_single_thread_close_chan_first() {
+        // Simple test of closing without sending
+        let (tx, _rx) = channel::<int>();
+        drop(tx);
+    } }
+
+    test! { fn oneshot_single_thread_send_port_close() {
+        // Testing that the sender cleans up the payload if receiver is closed
+        let (tx, rx) = channel::<Box<int>>();
+        drop(rx);
+        tx.send(box 0);
+    } #[should_fail] }
+
+    test! { fn oneshot_single_thread_recv_chan_close() {
+        // Receiving on a closed chan will panic
+        let res = Thread::spawn(move|| {
+            let (tx, rx) = channel::<int>();
+            drop(tx);
+            rx.recv();
+        }).join();
+        // What is our res?
+        assert!(res.is_err());
+    } }
+
+    test! { fn oneshot_single_thread_send_then_recv() {
+        let (tx, rx) = channel::<Box<int>>();
+        tx.send(box 10);
+        assert!(rx.recv() == box 10);
+    } }
+
+    test! { fn oneshot_single_thread_try_send_open() {
+        let (tx, rx) = channel::<int>();
+        assert!(tx.send_opt(10).is_ok());
+        assert!(rx.recv() == 10);
+    } }
+
+    test! { fn oneshot_single_thread_try_send_closed() {
+        let (tx, rx) = channel::<int>();
+        drop(rx);
+        assert!(tx.send_opt(10).is_err());
+    } }
+
+    test! { fn oneshot_single_thread_try_recv_open() {
+        let (tx, rx) = channel::<int>();
+        tx.send(10);
+        assert!(rx.recv_opt() == Ok(10));
+    } }
+
+    test! { fn oneshot_single_thread_try_recv_closed() {
+        let (tx, rx) = channel::<int>();
+        drop(tx);
+        assert!(rx.recv_opt() == Err(()));
+    } }
+
+    test! { fn oneshot_single_thread_peek_data() {
+        let (tx, rx) = channel::<int>();
+        assert_eq!(rx.try_recv(), Err(Empty));
+        tx.send(10);
+        assert_eq!(rx.try_recv(), Ok(10));
+    } }
+
+    test! { fn oneshot_single_thread_peek_close() {
+        let (tx, rx) = channel::<int>();
+        drop(tx);
+        assert_eq!(rx.try_recv(), Err(Disconnected));
+        assert_eq!(rx.try_recv(), Err(Disconnected));
+    } }
+
+    test! { fn oneshot_single_thread_peek_open() {
+        let (_tx, rx) = channel::<int>();
+        assert_eq!(rx.try_recv(), Err(Empty));
+    } }
+
+    test! { fn oneshot_multi_task_recv_then_send() {
+        let (tx, rx) = channel::<Box<int>>();
+        spawn(move|| {
+            assert!(rx.recv() == box 10);
+        });
+
+        tx.send(box 10);
+    } }
+
+    test! { fn oneshot_multi_task_recv_then_close() {
+        let (tx, rx) = channel::<Box<int>>();
+        spawn(move|| {
+            drop(tx);
+        });
+        let res = Thread::spawn(move|| {
+            assert!(rx.recv() == box 10);
+        }).join();
+        assert!(res.is_err());
+    } }
+
+    test! { fn oneshot_multi_thread_close_stress() {
+        for _ in range(0, stress_factor()) {
+            let (tx, rx) = channel::<int>();
+            spawn(move|| {
+                drop(rx);
+            });
+            drop(tx);
+        }
+    } }
+
+    test! { fn oneshot_multi_thread_send_close_stress() {
+        for _ in range(0, stress_factor()) {
+            let (tx, rx) = channel::<int>();
+            spawn(move|| {
+                drop(rx);
+            });
+            let _ = Thread::spawn(move|| {
+                tx.send(1);
+            }).join();
+        }
+    } }
+
+    test! { fn oneshot_multi_thread_recv_close_stress() {
+        for _ in range(0, stress_factor()) {
+            let (tx, rx) = channel::<int>();
+            spawn(move|| {
+                let res = Thread::spawn(move|| {
+                    rx.recv();
+                }).join();
+                assert!(res.is_err());
+            });
+            spawn(move|| {
+                spawn(move|| {
+                    drop(tx);
+                });
+            });
+        }
+    } }
+
+    test! { fn oneshot_multi_thread_send_recv_stress() {
+        for _ in range(0, stress_factor()) {
+            let (tx, rx) = channel();
+            spawn(move|| {
+                tx.send(box 10i);
+            });
+            spawn(move|| {
+                assert!(rx.recv() == box 10i);
+            });
+        }
+    } }
+
+    test! { fn stream_send_recv_stress() {
+        for _ in range(0, stress_factor()) {
+            let (tx, rx) = channel();
+
+            send(tx, 0);
+            recv(rx, 0);
+
+            fn send(tx: Sender<Box<int>>, i: int) {
+                if i == 10 { return }
+
+                spawn(move|| {
+                    tx.send(box i);
+                    send(tx, i + 1);
+                });
+            }
+
+            fn recv(rx: Receiver<Box<int>>, i: int) {
+                if i == 10 { return }
+
+                spawn(move|| {
+                    assert!(rx.recv() == box i);
+                    recv(rx, i + 1);
+                });
+            }
+        }
+    } }
+
+    test! { fn recv_a_lot() {
+        // Regression test that we don't run out of stack in scheduler context
+        let (tx, rx) = channel();
+        for _ in range(0i, 10000) { tx.send(()); }
+        for _ in range(0i, 10000) { rx.recv(); }
+    } }
+
+    test! { fn shared_chan_stress() {
+        let (tx, rx) = channel();
+        let total = stress_factor() + 100;
+        for _ in range(0, total) {
+            let tx = tx.clone();
+            spawn(move|| {
+                tx.send(());
+            });
+        }
+
+        for _ in range(0, total) {
+            rx.recv();
+        }
+    } }
+
+    test! { fn test_nested_recv_iter() {
+        let (tx, rx) = channel::<int>();
+        let (total_tx, total_rx) = channel::<int>();
+
+        spawn(move|| {
+            let mut acc = 0;
+            for x in rx.iter() {
+                acc += x;
+            }
+            total_tx.send(acc);
+        });
+
+        tx.send(3);
+        tx.send(1);
+        tx.send(2);
+        drop(tx);
+        assert_eq!(total_rx.recv(), 6);
+    } }
+
+    test! { fn test_recv_iter_break() {
+        let (tx, rx) = channel::<int>();
+        let (count_tx, count_rx) = channel();
+
+        spawn(move|| {
+            let mut count = 0;
+            for x in rx.iter() {
+                if count >= 3 {
+                    break;
+                } else {
+                    count += x;
+                }
+            }
+            count_tx.send(count);
+        });
+
+        tx.send(2);
+        tx.send(2);
+        tx.send(2);
+        let _ = tx.send_opt(2);
+        drop(tx);
+        assert_eq!(count_rx.recv(), 4);
+    } }
+
+    test! { fn try_recv_states() {
+        let (tx1, rx1) = channel::<int>();
+        let (tx2, rx2) = channel::<()>();
+        let (tx3, rx3) = channel::<()>();
+        spawn(move|| {
+            rx2.recv();
+            tx1.send(1);
+            tx3.send(());
+            rx2.recv();
+            drop(tx1);
+            tx3.send(());
+        });
+
+        assert_eq!(rx1.try_recv(), Err(Empty));
+        tx2.send(());
+        rx3.recv();
+        assert_eq!(rx1.try_recv(), Ok(1));
+        assert_eq!(rx1.try_recv(), Err(Empty));
+        tx2.send(());
+        rx3.recv();
+        assert_eq!(rx1.try_recv(), Err(Disconnected));
+    } }
+
+    // This bug used to end up in a livelock inside of the Receiver destructor
+    // because the internal state of the Shared packet was corrupted
+    test! { fn destroy_upgraded_shared_port_when_sender_still_active() {
+        let (tx, rx) = channel();
+        let (tx2, rx2) = channel();
+        spawn(move|| {
+            rx.recv(); // wait on a oneshot
+            drop(rx);  // destroy a shared
+            tx2.send(());
+        });
+        // make sure the other task has gone to sleep
+        for _ in range(0u, 5000) { Thread::yield_now(); }
+
+        // upgrade to a shared chan and send a message
+        let t = tx.clone();
+        drop(tx);
+        t.send(());
+
+        // wait for the child task to exit before we exit
+        rx2.recv();
+    }}
+}
+
+#[cfg(test)]
+mod sync_tests {
+    use prelude::*;
+    use os;
+
+    pub fn stress_factor() -> uint {
+        match os::getenv("RUST_TEST_STRESS") {
+            Some(val) => from_str::<uint>(val.as_slice()).unwrap(),
+            None => 1,
+        }
+    }
+
+    test! { fn smoke() {
+        let (tx, rx) = sync_channel::<int>(1);
+        tx.send(1);
+        assert_eq!(rx.recv(), 1);
+    } }
+
+    test! { fn drop_full() {
+        let (tx, _rx) = sync_channel(1);
+        tx.send(box 1i);
+    } }
+
+    test! { fn smoke_shared() {
+        let (tx, rx) = sync_channel::<int>(1);
+        tx.send(1);
+        assert_eq!(rx.recv(), 1);
+        let tx = tx.clone();
+        tx.send(1);
+        assert_eq!(rx.recv(), 1);
+    } }
+
+    test! { fn smoke_threads() {
+        let (tx, rx) = sync_channel::<int>(0);
+        spawn(move|| {
+            tx.send(1);
+        });
+        assert_eq!(rx.recv(), 1);
+    } }
+
+    test! { fn smoke_port_gone() {
+        let (tx, rx) = sync_channel::<int>(0);
+        drop(rx);
+        tx.send(1);
+    } #[should_fail] }
+
+    test! { fn smoke_shared_port_gone2() {
+        let (tx, rx) = sync_channel::<int>(0);
+        drop(rx);
+        let tx2 = tx.clone();
+        drop(tx);
+        tx2.send(1);
+    } #[should_fail] }
+
+    test! { fn port_gone_concurrent() {
+        let (tx, rx) = sync_channel::<int>(0);
+        spawn(move|| {
+            rx.recv();
+        });
+        loop { tx.send(1) }
+    } #[should_fail] }
+
+    test! { fn port_gone_concurrent_shared() {
+        let (tx, rx) = sync_channel::<int>(0);
+        let tx2 = tx.clone();
+        spawn(move|| {
+            rx.recv();
+        });
+        loop {
+            tx.send(1);
+            tx2.send(1);
+        }
+    } #[should_fail] }
+
+    test! { fn smoke_chan_gone() {
+        let (tx, rx) = sync_channel::<int>(0);
+        drop(tx);
+        rx.recv();
+    } #[should_fail] }
+
+    test! { fn smoke_chan_gone_shared() {
+        let (tx, rx) = sync_channel::<()>(0);
+        let tx2 = tx.clone();
+        drop(tx);
+        drop(tx2);
+        rx.recv();
+    } #[should_fail] }
+
+    test! { fn chan_gone_concurrent() {
+        let (tx, rx) = sync_channel::<int>(0);
+        spawn(move|| {
+            tx.send(1);
+            tx.send(1);
+        });
+        loop { rx.recv(); }
+    } #[should_fail] }
+
+    test! { fn stress() {
+        let (tx, rx) = sync_channel::<int>(0);
+        spawn(move|| {
+            for _ in range(0u, 10000) { tx.send(1); }
+        });
+        for _ in range(0u, 10000) {
+            assert_eq!(rx.recv(), 1);
+        }
+    } }
+
+    test! { fn stress_shared() {
+        static AMT: uint = 1000;
+        static NTHREADS: uint = 8;
+        let (tx, rx) = sync_channel::<int>(0);
+        let (dtx, drx) = sync_channel::<()>(0);
+
+        spawn(move|| {
+            for _ in range(0, AMT * NTHREADS) {
+                assert_eq!(rx.recv(), 1);
+            }
+            match rx.try_recv() {
+                Ok(..) => panic!(),
+                _ => {}
+            }
+            dtx.send(());
+        });
+
+        for _ in range(0, NTHREADS) {
+            let tx = tx.clone();
+            spawn(move|| {
+                for _ in range(0, AMT) { tx.send(1); }
+            });
+        }
+        drop(tx);
+        drx.recv();
+    } }
+
+    test! { fn oneshot_single_thread_close_port_first() {
+        // Simple test of closing without sending
+        let (_tx, rx) = sync_channel::<int>(0);
+        drop(rx);
+    } }
+
+    test! { fn oneshot_single_thread_close_chan_first() {
+        // Simple test of closing without sending
+        let (tx, _rx) = sync_channel::<int>(0);
+        drop(tx);
+    } }
+
+    test! { fn oneshot_single_thread_send_port_close() {
+        // Testing that the sender cleans up the payload if receiver is closed
+        let (tx, rx) = sync_channel::<Box<int>>(0);
+        drop(rx);
+        tx.send(box 0);
+    } #[should_fail] }
+
+    test! { fn oneshot_single_thread_recv_chan_close() {
+        // Receiving on a closed chan will panic
+        let res = Thread::spawn(move|| {
+            let (tx, rx) = sync_channel::<int>(0);
+            drop(tx);
+            rx.recv();
+        }).join();
+        // What is our res?
+        assert!(res.is_err());
+    } }
+
+    test! { fn oneshot_single_thread_send_then_recv() {
+        let (tx, rx) = sync_channel::<Box<int>>(1);
+        tx.send(box 10);
+        assert!(rx.recv() == box 10);
+    } }
+
+    test! { fn oneshot_single_thread_try_send_open() {
+        let (tx, rx) = sync_channel::<int>(1);
+        assert_eq!(tx.try_send(10), Ok(()));
+        assert!(rx.recv() == 10);
+    } }
+
+    test! { fn oneshot_single_thread_try_send_closed() {
+        let (tx, rx) = sync_channel::<int>(0);
+        drop(rx);
+        assert_eq!(tx.try_send(10), Err(RecvDisconnected(10)));
+    } }
+
+    test! { fn oneshot_single_thread_try_send_closed2() {
+        let (tx, _rx) = sync_channel::<int>(0);
+        assert_eq!(tx.try_send(10), Err(Full(10)));
+    } }
+
+    test! { fn oneshot_single_thread_try_recv_open() {
+        let (tx, rx) = sync_channel::<int>(1);
+        tx.send(10);
+        assert!(rx.recv_opt() == Ok(10));
+    } }
+
+    test! { fn oneshot_single_thread_try_recv_closed() {
+        let (tx, rx) = sync_channel::<int>(0);
+        drop(tx);
+        assert!(rx.recv_opt() == Err(()));
+    } }
+
+    test! { fn oneshot_single_thread_peek_data() {
+        let (tx, rx) = sync_channel::<int>(1);
+        assert_eq!(rx.try_recv(), Err(Empty));
+        tx.send(10);
+        assert_eq!(rx.try_recv(), Ok(10));
+    } }
+
+    test! { fn oneshot_single_thread_peek_close() {
+        let (tx, rx) = sync_channel::<int>(0);
+        drop(tx);
+        assert_eq!(rx.try_recv(), Err(Disconnected));
+        assert_eq!(rx.try_recv(), Err(Disconnected));
+    } }
+
+    test! { fn oneshot_single_thread_peek_open() {
+        let (_tx, rx) = sync_channel::<int>(0);
+        assert_eq!(rx.try_recv(), Err(Empty));
+    } }
+
+    test! { fn oneshot_multi_task_recv_then_send() {
+        let (tx, rx) = sync_channel::<Box<int>>(0);
+        spawn(move|| {
+            assert!(rx.recv() == box 10);
+        });
+
+        tx.send(box 10);
+    } }
+
+    test! { fn oneshot_multi_task_recv_then_close() {
+        let (tx, rx) = sync_channel::<Box<int>>(0);
+        spawn(move|| {
+            drop(tx);
+        });
+        let res = Thread::spawn(move|| {
+            assert!(rx.recv() == box 10);
+        }).join();
+        assert!(res.is_err());
+    } }
+
+    test! { fn oneshot_multi_thread_close_stress() {
+        for _ in range(0, stress_factor()) {
+            let (tx, rx) = sync_channel::<int>(0);
+            spawn(move|| {
+                drop(rx);
+            });
+            drop(tx);
+        }
+    } }
+
+    test! { fn oneshot_multi_thread_send_close_stress() {
+        for _ in range(0, stress_factor()) {
+            let (tx, rx) = sync_channel::<int>(0);
+            spawn(move|| {
+                drop(rx);
+            });
+            let _ = Thread::spawn(move || {
+                tx.send(1);
+            }).join();
+        }
+    } }
+
+    test! { fn oneshot_multi_thread_recv_close_stress() {
+        for _ in range(0, stress_factor()) {
+            let (tx, rx) = sync_channel::<int>(0);
+            spawn(move|| {
+                let res = Thread::spawn(move|| {
+                    rx.recv();
+                }).join();
+                assert!(res.is_err());
+            });
+            spawn(move|| {
+                spawn(move|| {
+                    drop(tx);
+                });
+            });
+        }
+    } }
+
+    test! { fn oneshot_multi_thread_send_recv_stress() {
+        for _ in range(0, stress_factor()) {
+            let (tx, rx) = sync_channel::<Box<int>>(0);
+            spawn(move|| {
+                tx.send(box 10i);
+            });
+            spawn(move|| {
+                assert!(rx.recv() == box 10i);
+            });
+        }
+    } }
+
+    test! { fn stream_send_recv_stress() {
+        for _ in range(0, stress_factor()) {
+            let (tx, rx) = sync_channel::<Box<int>>(0);
+
+            send(tx, 0);
+            recv(rx, 0);
+
+            fn send(tx: SyncSender<Box<int>>, i: int) {
+                if i == 10 { return }
+
+                spawn(move|| {
+                    tx.send(box i);
+                    send(tx, i + 1);
+                });
+            }
+
+            fn recv(rx: Receiver<Box<int>>, i: int) {
+                if i == 10 { return }
+
+                spawn(move|| {
+                    assert!(rx.recv() == box i);
+                    recv(rx, i + 1);
+                });
+            }
+        }
+    } }
+
+    test! { fn recv_a_lot() {
+        // Regression test that we don't run out of stack in scheduler context
+        let (tx, rx) = sync_channel(10000);
+        for _ in range(0u, 10000) { tx.send(()); }
+        for _ in range(0u, 10000) { rx.recv(); }
+    } }
+
+    test! { fn shared_chan_stress() {
+        let (tx, rx) = sync_channel(0);
+        let total = stress_factor() + 100;
+        for _ in range(0, total) {
+            let tx = tx.clone();
+            spawn(move|| {
+                tx.send(());
+            });
+        }
+
+        for _ in range(0, total) {
+            rx.recv();
+        }
+    } }
+
+    test! { fn test_nested_recv_iter() {
+        let (tx, rx) = sync_channel::<int>(0);
+        let (total_tx, total_rx) = sync_channel::<int>(0);
+
+        spawn(move|| {
+            let mut acc = 0;
+            for x in rx.iter() {
+                acc += x;
+            }
+            total_tx.send(acc);
+        });
+
+        tx.send(3);
+        tx.send(1);
+        tx.send(2);
+        drop(tx);
+        assert_eq!(total_rx.recv(), 6);
+    } }
+
+    test! { fn test_recv_iter_break() {
+        let (tx, rx) = sync_channel::<int>(0);
+        let (count_tx, count_rx) = sync_channel(0);
+
+        spawn(move|| {
+            let mut count = 0;
+            for x in rx.iter() {
+                if count >= 3 {
+                    break;
+                } else {
+                    count += x;
+                }
+            }
+            count_tx.send(count);
+        });
+
+        tx.send(2);
+        tx.send(2);
+        tx.send(2);
+        let _ = tx.try_send(2);
+        drop(tx);
+        assert_eq!(count_rx.recv(), 4);
+    } }
+
+    test! { fn try_recv_states() {
+        let (tx1, rx1) = sync_channel::<int>(1);
+        let (tx2, rx2) = sync_channel::<()>(1);
+        let (tx3, rx3) = sync_channel::<()>(1);
+        spawn(move|| {
+            rx2.recv();
+            tx1.send(1);
+            tx3.send(());
+            rx2.recv();
+            drop(tx1);
+            tx3.send(());
+        });
+
+        assert_eq!(rx1.try_recv(), Err(Empty));
+        tx2.send(());
+        rx3.recv();
+        assert_eq!(rx1.try_recv(), Ok(1));
+        assert_eq!(rx1.try_recv(), Err(Empty));
+        tx2.send(());
+        rx3.recv();
+        assert_eq!(rx1.try_recv(), Err(Disconnected));
+    } }
+
+    // This bug used to end up in a livelock inside of the Receiver destructor
+    // because the internal state of the Shared packet was corrupted
+    test! { fn destroy_upgraded_shared_port_when_sender_still_active() {
+        let (tx, rx) = sync_channel::<()>(0);
+        let (tx2, rx2) = sync_channel::<()>(0);
+        spawn(move|| {
+            rx.recv(); // wait on a oneshot
+            drop(rx);  // destroy a shared
+            tx2.send(());
+        });
+        // make sure the other task has gone to sleep
+        for _ in range(0u, 5000) { Thread::yield_now(); }
+
+        // upgrade to a shared chan and send a message
+        let t = tx.clone();
+        drop(tx);
+        t.send(());
+
+        // wait for the child task to exit before we exit
+        rx2.recv();
+    } }
+
+    test! { fn send_opt1() {
+        let (tx, rx) = sync_channel::<int>(0);
+        spawn(move|| { rx.recv(); });
+        assert_eq!(tx.send_opt(1), Ok(()));
+    } }
+
+    test! { fn send_opt2() {
+        let (tx, rx) = sync_channel::<int>(0);
+        spawn(move|| { drop(rx); });
+        assert_eq!(tx.send_opt(1), Err(1));
+    } }
+
+    test! { fn send_opt3() {
+        let (tx, rx) = sync_channel::<int>(1);
+        assert_eq!(tx.send_opt(1), Ok(()));
+        spawn(move|| { drop(rx); });
+        assert_eq!(tx.send_opt(1), Err(1));
+    } }
+
+    test! { fn send_opt4() {
+        let (tx, rx) = sync_channel::<int>(0);
+        let tx2 = tx.clone();
+        let (done, donerx) = channel();
+        let done2 = done.clone();
+        spawn(move|| {
+            assert_eq!(tx.send_opt(1), Err(1));
+            done.send(());
+        });
+        spawn(move|| {
+            assert_eq!(tx2.send_opt(2), Err(2));
+            done2.send(());
+        });
+        drop(rx);
+        donerx.recv();
+        donerx.recv();
+    } }
+
+    test! { fn try_send1() {
+        let (tx, _rx) = sync_channel::<int>(0);
+        assert_eq!(tx.try_send(1), Err(Full(1)));
+    } }
+
+    test! { fn try_send2() {
+        let (tx, _rx) = sync_channel::<int>(1);
+        assert_eq!(tx.try_send(1), Ok(()));
+        assert_eq!(tx.try_send(1), Err(Full(1)));
+    } }
+
+    test! { fn try_send3() {
+        let (tx, rx) = sync_channel::<int>(1);
+        assert_eq!(tx.try_send(1), Ok(()));
+        drop(rx);
+        assert_eq!(tx.try_send(1), Err(RecvDisconnected(1)));
+    } }
+
+    test! { fn try_send4() {
+        let (tx, rx) = sync_channel::<int>(0);
+        spawn(move|| {
+            for _ in range(0u, 1000) { Thread::yield_now(); }
+            assert_eq!(tx.try_send(1), Ok(()));
+        });
+        assert_eq!(rx.recv(), 1);
+    } #[ignore(reason = "flaky on libnative")] }
+
+    test! { fn issue_15761() {
+        fn repro() {
+            let (tx1, rx1) = sync_channel::<()>(3);
+            let (tx2, rx2) = sync_channel::<()>(3);
+
+            spawn(move|| {
+                rx1.recv();
+                tx2.try_send(()).unwrap();
+            });
+
+            tx1.try_send(()).unwrap();
+            rx2.recv();
+        }
+
+        for _ in range(0u, 100) {
+            repro()
+        }
+    } }
+}
diff --git a/src/libstd/comm/mpsc_queue.rs b/src/libstd/comm/mpsc_queue.rs
new file mode 100644
index 00000000000..db4e3eac449
--- /dev/null
+++ b/src/libstd/comm/mpsc_queue.rs
@@ -0,0 +1,201 @@
+/* Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *    1. Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *
+ *    2. Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are
+ * those of the authors and should not be interpreted as representing official
+ * policies, either expressed or implied, of Dmitry Vyukov.
+ */
+
+//! A mostly lock-free multi-producer, single consumer queue.
+//!
+//! This module contains an implementation of a concurrent MPSC queue. This
+//! queue can be used to share data between tasks, and is also used as the
+//! building block of channels in rust.
+//!
+//! Note that the current implementation of this queue has a caveat of the `pop`
+//! method, and see the method for more information about it. Due to this
+//! caveat, this queue may not be appropriate for all use-cases.
+
+#![experimental]
+
+// http://www.1024cores.net/home/lock-free-algorithms
+//                         /queues/non-intrusive-mpsc-node-based-queue
+
+pub use self::PopResult::*;
+
+use core::prelude::*;
+
+use alloc::boxed::Box;
+use core::mem;
+use core::cell::UnsafeCell;
+
+use sync::atomic::{AtomicPtr, Release, Acquire, AcqRel, Relaxed};
+
+/// A result of the `pop` function.
+pub enum PopResult<T> {
+    /// Some data has been popped
+    Data(T),
+    /// The queue is empty
+    Empty,
+    /// The queue is in an inconsistent state. Popping data should succeed, but
+    /// some pushers have yet to make enough progress in order allow a pop to
+    /// succeed. It is recommended that a pop() occur "in the near future" in
+    /// order to see if the sender has made progress or not
+    Inconsistent,
+}
+
+struct Node<T> {
+    next: AtomicPtr<Node<T>>,
+    value: Option<T>,
+}
+
+/// The multi-producer single-consumer structure. This is not cloneable, but it
+/// may be safely shared so long as it is guaranteed that there is only one
+/// popper at a time (many pushers are allowed).
+pub struct Queue<T> {
+    head: AtomicPtr<Node<T>>,
+    tail: UnsafeCell<*mut Node<T>>,
+}
+
+impl<T> Node<T> {
+    unsafe fn new(v: Option<T>) -> *mut Node<T> {
+        mem::transmute(box Node {
+            next: AtomicPtr::new(0 as *mut Node<T>),
+            value: v,
+        })
+    }
+}
+
+impl<T: Send> Queue<T> {
+    /// Creates a new queue that is safe to share among multiple producers and
+    /// one consumer.
+    pub fn new() -> Queue<T> {
+        let stub = unsafe { Node::new(None) };
+        Queue {
+            head: AtomicPtr::new(stub),
+            tail: UnsafeCell::new(stub),
+        }
+    }
+
+    /// Pushes a new value onto this queue.
+    pub fn push(&self, t: T) {
+        unsafe {
+            let n = Node::new(Some(t));
+            let prev = self.head.swap(n, AcqRel);
+            (*prev).next.store(n, Release);
+        }
+    }
+
+    /// Pops some data from this queue.
+    ///
+    /// Note that the current implementation means that this function cannot
+    /// return `Option<T>`. It is possible for this queue to be in an
+    /// inconsistent state where many pushes have succeeded and completely
+    /// finished, but pops cannot return `Some(t)`. This inconsistent state
+    /// happens when a pusher is pre-empted at an inopportune moment.
+    ///
+    /// This inconsistent state means that this queue does indeed have data, but
+    /// it does not currently have access to it at this time.
+    pub fn pop(&self) -> PopResult<T> {
+        unsafe {
+            let tail = *self.tail.get();
+            let next = (*tail).next.load(Acquire);
+
+            if !next.is_null() {
+                *self.tail.get() = next;
+                assert!((*tail).value.is_none());
+                assert!((*next).value.is_some());
+                let ret = (*next).value.take().unwrap();
+                let _: Box<Node<T>> = mem::transmute(tail);
+                return Data(ret);
+            }
+
+            if self.head.load(Acquire) == tail {Empty} else {Inconsistent}
+        }
+    }
+}
+
+#[unsafe_destructor]
+impl<T: Send> Drop for Queue<T> {
+    fn drop(&mut self) {
+        unsafe {
+            let mut cur = *self.tail.get();
+            while !cur.is_null() {
+                let next = (*cur).next.load(Relaxed);
+                let _: Box<Node<T>> = mem::transmute(cur);
+                cur = next;
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use prelude::*;
+
+    use alloc::arc::Arc;
+
+    use super::{Queue, Data, Empty, Inconsistent};
+
+    #[test]
+    fn test_full() {
+        let q = Queue::new();
+        q.push(box 1i);
+        q.push(box 2i);
+    }
+
+    #[test]
+    fn test() {
+        let nthreads = 8u;
+        let nmsgs = 1000u;
+        let q = Queue::new();
+        match q.pop() {
+            Empty => {}
+            Inconsistent | Data(..) => panic!()
+        }
+        let (tx, rx) = channel();
+        let q = Arc::new(q);
+
+        for _ in range(0, nthreads) {
+            let tx = tx.clone();
+            let q = q.clone();
+            spawn(move|| {
+                for i in range(0, nmsgs) {
+                    q.push(i);
+                }
+                tx.send(());
+            });
+        }
+
+        let mut i = 0u;
+        while i < nthreads * nmsgs {
+            match q.pop() {
+                Empty | Inconsistent => {},
+                Data(_) => { i += 1 }
+            }
+        }
+        drop(tx);
+        for _ in range(0, nthreads) {
+            rx.recv();
+        }
+    }
+}
diff --git a/src/libstd/comm/oneshot.rs b/src/libstd/comm/oneshot.rs
new file mode 100644
index 00000000000..9c5a6518845
--- /dev/null
+++ b/src/libstd/comm/oneshot.rs
@@ -0,0 +1,375 @@
+// 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.
+
+/// Oneshot channels/ports
+///
+/// This is the initial flavor of channels/ports used for comm module. This is
+/// an optimization for the one-use case of a channel. The major optimization of
+/// this type is to have one and exactly one allocation when the chan/port pair
+/// is created.
+///
+/// Another possible optimization would be to not use an Arc box because
+/// in theory we know when the shared packet can be deallocated (no real need
+/// for the atomic reference counting), but I was having trouble how to destroy
+/// the data early in a drop of a Port.
+///
+/// # Implementation
+///
+/// Oneshots are implemented around one atomic uint variable. This variable
+/// indicates both the state of the port/chan but also contains any tasks
+/// blocked on the port. All atomic operations happen on this one word.
+///
+/// In order to upgrade a oneshot channel, an upgrade is considered a disconnect
+/// on behalf of the channel side of things (it can be mentally thought of as
+/// consuming the port). This upgrade is then also stored in the shared packet.
+/// The one caveat to consider is that when a port sees a disconnected channel
+/// it must check for data because there is no "data plus upgrade" state.
+
+pub use self::Failure::*;
+pub use self::UpgradeResult::*;
+pub use self::SelectionResult::*;
+use self::MyUpgrade::*;
+
+use core::prelude::*;
+
+use comm::Receiver;
+use comm::blocking::{mod, SignalToken};
+use core::mem;
+use sync::atomic;
+
+// Various states you can find a port in.
+const EMPTY: uint = 0;          // initial state: no data, no blocked reciever
+const DATA: uint = 1;           // data ready for receiver to take
+const DISCONNECTED: uint = 2;   // channel is disconnected OR upgraded
+// Any other value represents a pointer to a SignalToken value. The
+// protocol ensures that when the state moves *to* a pointer,
+// ownership of the token is given to the packet, and when the state
+// moves *from* a pointer, ownership of the token is transferred to
+// whoever changed the state.
+
+pub struct Packet<T> {
+    // Internal state of the chan/port pair (stores the blocked task as well)
+    state: atomic::AtomicUint,
+    // One-shot data slot location
+    data: Option<T>,
+    // when used for the second time, a oneshot channel must be upgraded, and
+    // this contains the slot for the upgrade
+    upgrade: MyUpgrade<T>,
+}
+
+pub enum Failure<T> {
+    Empty,
+    Disconnected,
+    Upgraded(Receiver<T>),
+}
+
+pub enum UpgradeResult {
+    UpSuccess,
+    UpDisconnected,
+    UpWoke(SignalToken),
+}
+
+pub enum SelectionResult<T> {
+    SelCanceled,
+    SelUpgraded(SignalToken, Receiver<T>),
+    SelSuccess,
+}
+
+enum MyUpgrade<T> {
+    NothingSent,
+    SendUsed,
+    GoUp(Receiver<T>),
+}
+
+impl<T: Send> Packet<T> {
+    pub fn new() -> Packet<T> {
+        Packet {
+            data: None,
+            upgrade: NothingSent,
+            state: atomic::AtomicUint::new(EMPTY),
+        }
+    }
+
+    pub fn send(&mut self, t: T) -> Result<(), T> {
+        // Sanity check
+        match self.upgrade {
+            NothingSent => {}
+            _ => panic!("sending on a oneshot that's already sent on "),
+        }
+        assert!(self.data.is_none());
+        self.data = Some(t);
+        self.upgrade = SendUsed;
+
+        match self.state.swap(DATA, atomic::SeqCst) {
+            // Sent the data, no one was waiting
+            EMPTY => Ok(()),
+
+            // Couldn't send the data, the port hung up first. Return the data
+            // back up the stack.
+            DISCONNECTED => {
+                Err(self.data.take().unwrap())
+            }
+
+            // Not possible, these are one-use channels
+            DATA => unreachable!(),
+
+            // There is a thread waiting on the other end. We leave the 'DATA'
+            // state inside so it'll pick it up on the other end.
+            ptr => unsafe {
+                SignalToken::cast_from_uint(ptr).signal();
+                Ok(())
+            }
+        }
+    }
+
+    // Just tests whether this channel has been sent on or not, this is only
+    // safe to use from the sender.
+    pub fn sent(&self) -> bool {
+        match self.upgrade {
+            NothingSent => false,
+            _ => true,
+        }
+    }
+
+    pub fn recv(&mut self) -> Result<T, Failure<T>> {
+        // Attempt to not block the task (it's a little expensive). If it looks
+        // like we're not empty, then immediately go through to `try_recv`.
+        if self.state.load(atomic::SeqCst) == EMPTY {
+            let (wait_token, signal_token) = blocking::tokens();
+            let ptr = unsafe { signal_token.cast_to_uint() };
+
+            // race with senders to enter the blocking state
+            if self.state.compare_and_swap(EMPTY, ptr, atomic::SeqCst) == EMPTY {
+                wait_token.wait();
+                debug_assert!(self.state.load(atomic::SeqCst) != EMPTY);
+            } else {
+                // drop the signal token, since we never blocked
+                drop(unsafe { SignalToken::cast_from_uint(ptr) });
+            }
+        }
+
+        self.try_recv()
+    }
+
+    pub fn try_recv(&mut self) -> Result<T, Failure<T>> {
+        match self.state.load(atomic::SeqCst) {
+            EMPTY => Err(Empty),
+
+            // We saw some data on the channel, but the channel can be used
+            // again to send us an upgrade. As a result, we need to re-insert
+            // into the channel that there's no data available (otherwise we'll
+            // just see DATA next time). This is done as a cmpxchg because if
+            // the state changes under our feet we'd rather just see that state
+            // change.
+            DATA => {
+                self.state.compare_and_swap(DATA, EMPTY, atomic::SeqCst);
+                match self.data.take() {
+                    Some(data) => Ok(data),
+                    None => unreachable!(),
+                }
+            }
+
+            // There's no guarantee that we receive before an upgrade happens,
+            // and an upgrade flags the channel as disconnected, so when we see
+            // this we first need to check if there's data available and *then*
+            // we go through and process the upgrade.
+            DISCONNECTED => {
+                match self.data.take() {
+                    Some(data) => Ok(data),
+                    None => {
+                        match mem::replace(&mut self.upgrade, SendUsed) {
+                            SendUsed | NothingSent => Err(Disconnected),
+                            GoUp(upgrade) => Err(Upgraded(upgrade))
+                        }
+                    }
+                }
+            }
+
+            // We are the sole receiver; there cannot be a blocking
+            // receiver already.
+            _ => unreachable!()
+        }
+    }
+
+    // Returns whether the upgrade was completed. If the upgrade wasn't
+    // completed, then the port couldn't get sent to the other half (it will
+    // never receive it).
+    pub fn upgrade(&mut self, up: Receiver<T>) -> UpgradeResult {
+        let prev = match self.upgrade {
+            NothingSent => NothingSent,
+            SendUsed => SendUsed,
+            _ => panic!("upgrading again"),
+        };
+        self.upgrade = GoUp(up);
+
+        match self.state.swap(DISCONNECTED, atomic::SeqCst) {
+            // If the channel is empty or has data on it, then we're good to go.
+            // Senders will check the data before the upgrade (in case we
+            // plastered over the DATA state).
+            DATA | EMPTY => UpSuccess,
+
+            // If the other end is already disconnected, then we failed the
+            // upgrade. Be sure to trash the port we were given.
+            DISCONNECTED => { self.upgrade = prev; UpDisconnected }
+
+            // If someone's waiting, we gotta wake them up
+            ptr => UpWoke(unsafe { SignalToken::cast_from_uint(ptr) })
+        }
+    }
+
+    pub fn drop_chan(&mut self) {
+        match self.state.swap(DISCONNECTED, atomic::SeqCst) {
+            DATA | DISCONNECTED | EMPTY => {}
+
+            // If someone's waiting, we gotta wake them up
+            ptr => unsafe {
+                SignalToken::cast_from_uint(ptr).signal();
+            }
+        }
+    }
+
+    pub fn drop_port(&mut self) {
+        match self.state.swap(DISCONNECTED, atomic::SeqCst) {
+            // An empty channel has nothing to do, and a remotely disconnected
+            // channel also has nothing to do b/c we're about to run the drop
+            // glue
+            DISCONNECTED | EMPTY => {}
+
+            // There's data on the channel, so make sure we destroy it promptly.
+            // This is why not using an arc is a little difficult (need the box
+            // to stay valid while we take the data).
+            DATA => { self.data.take().unwrap(); }
+
+            // We're the only ones that can block on this port
+            _ => unreachable!()
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // select implementation
+    ////////////////////////////////////////////////////////////////////////////
+
+    // If Ok, the value is whether this port has data, if Err, then the upgraded
+    // port needs to be checked instead of this one.
+    pub fn can_recv(&mut self) -> Result<bool, Receiver<T>> {
+        match self.state.load(atomic::SeqCst) {
+            EMPTY => Ok(false), // Welp, we tried
+            DATA => Ok(true),   // we have some un-acquired data
+            DISCONNECTED if self.data.is_some() => Ok(true), // we have data
+            DISCONNECTED => {
+                match mem::replace(&mut self.upgrade, SendUsed) {
+                    // The other end sent us an upgrade, so we need to
+                    // propagate upwards whether the upgrade can receive
+                    // data
+                    GoUp(upgrade) => Err(upgrade),
+
+                    // If the other end disconnected without sending an
+                    // upgrade, then we have data to receive (the channel is
+                    // disconnected).
+                    up => { self.upgrade = up; Ok(true) }
+                }
+            }
+            _ => unreachable!(), // we're the "one blocker"
+        }
+    }
+
+    // Attempts to start selection on this port. This can either succeed, fail
+    // because there is data, or fail because there is an upgrade pending.
+    pub fn start_selection(&mut self, token: SignalToken) -> SelectionResult<T> {
+        let ptr = unsafe { token.cast_to_uint() };
+        match self.state.compare_and_swap(EMPTY, ptr, atomic::SeqCst) {
+            EMPTY => SelSuccess,
+            DATA => {
+                drop(unsafe { SignalToken::cast_from_uint(ptr) });
+                SelCanceled
+            }
+            DISCONNECTED if self.data.is_some() => {
+                drop(unsafe { SignalToken::cast_from_uint(ptr) });
+                SelCanceled
+            }
+            DISCONNECTED => {
+                match mem::replace(&mut self.upgrade, SendUsed) {
+                    // The other end sent us an upgrade, so we need to
+                    // propagate upwards whether the upgrade can receive
+                    // data
+                    GoUp(upgrade) => {
+                        SelUpgraded(unsafe { SignalToken::cast_from_uint(ptr) }, upgrade)
+                    }
+
+                    // If the other end disconnected without sending an
+                    // upgrade, then we have data to receive (the channel is
+                    // disconnected).
+                    up => {
+                        self.upgrade = up;
+                        drop(unsafe { SignalToken::cast_from_uint(ptr) });
+                        SelCanceled
+                    }
+                }
+            }
+            _ => unreachable!(), // we're the "one blocker"
+        }
+    }
+
+    // Remove a previous selecting task from this port. This ensures that the
+    // blocked task will no longer be visible to any other threads.
+    //
+    // The return value indicates whether there's data on this port.
+    pub fn abort_selection(&mut self) -> Result<bool, Receiver<T>> {
+        let state = match self.state.load(atomic::SeqCst) {
+            // Each of these states means that no further activity will happen
+            // with regard to abortion selection
+            s @ EMPTY |
+            s @ DATA |
+            s @ DISCONNECTED => s,
+
+            // If we've got a blocked task, then use an atomic to gain ownership
+            // of it (may fail)
+            ptr => self.state.compare_and_swap(ptr, EMPTY, atomic::SeqCst)
+        };
+
+        // Now that we've got ownership of our state, figure out what to do
+        // about it.
+        match state {
+            EMPTY => unreachable!(),
+            // our task used for select was stolen
+            DATA => Ok(true),
+
+            // If the other end has hung up, then we have complete ownership
+            // of the port. First, check if there was data waiting for us. This
+            // is possible if the other end sent something and then hung up.
+            //
+            // We then need to check to see if there was an upgrade requested,
+            // and if so, the upgraded port needs to have its selection aborted.
+            DISCONNECTED => {
+                if self.data.is_some() {
+                    Ok(true)
+                } else {
+                    match mem::replace(&mut self.upgrade, SendUsed) {
+                        GoUp(port) => Err(port),
+                        _ => Ok(true),
+                    }
+                }
+            }
+
+            // We woke ourselves up from select.
+            ptr => unsafe {
+                drop(SignalToken::cast_from_uint(ptr));
+                Ok(false)
+            }
+        }
+    }
+}
+
+#[unsafe_destructor]
+impl<T: Send> Drop for Packet<T> {
+    fn drop(&mut self) {
+        assert_eq!(self.state.load(atomic::SeqCst), DISCONNECTED);
+    }
+}
diff --git a/src/libstd/comm/select.rs b/src/libstd/comm/select.rs
new file mode 100644
index 00000000000..690b5861c22
--- /dev/null
+++ b/src/libstd/comm/select.rs
@@ -0,0 +1,721 @@
+// 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.
+
+//! Selection over an array of receivers
+//!
+//! This module contains the implementation machinery necessary for selecting
+//! over a number of receivers. One large goal of this module is to provide an
+//! efficient interface to selecting over any receiver of any type.
+//!
+//! This is achieved through an architecture of a "receiver set" in which
+//! receivers are added to a set and then the entire set is waited on at once.
+//! The set can be waited on multiple times to prevent re-adding each receiver
+//! to the set.
+//!
+//! Usage of this module is currently encouraged to go through the use of the
+//! `select!` macro. This macro allows naturally binding of variables to the
+//! received values of receivers in a much more natural syntax then usage of the
+//! `Select` structure directly.
+//!
+//! # Example
+//!
+//! ```rust
+//! let (tx1, rx1) = channel();
+//! let (tx2, rx2) = channel();
+//!
+//! tx1.send(1i);
+//! tx2.send(2i);
+//!
+//! select! {
+//!     val = rx1.recv() => {
+//!         assert_eq!(val, 1i);
+//!     },
+//!     val = rx2.recv() => {
+//!         assert_eq!(val, 2i);
+//!     }
+//! }
+//! ```
+
+#![allow(dead_code)]
+#![experimental = "This implementation, while likely sufficient, is unsafe and \
+                   likely to be error prone. At some point in the future this \
+                   module will likely be replaced, and it is currently \
+                   unknown how much API breakage that will cause. The ability \
+                   to select over a number of channels will remain forever, \
+                   but no guarantees beyond this are being made"]
+
+
+use core::prelude::*;
+
+use core::cell::Cell;
+use core::kinds::marker;
+use core::mem;
+use core::uint;
+
+use comm::Receiver;
+use comm::blocking::{mod, SignalToken};
+
+/// The "receiver set" of the select interface. This structure is used to manage
+/// a set of receivers which are being selected over.
+pub struct Select {
+    head: *mut Handle<'static, ()>,
+    tail: *mut Handle<'static, ()>,
+    next_id: Cell<uint>,
+    marker1: marker::NoSend,
+}
+
+/// A handle to a receiver which is currently a member of a `Select` set of
+/// receivers.  This handle is used to keep the receiver in the set as well as
+/// interact with the underlying receiver.
+pub struct Handle<'rx, T:'rx> {
+    /// The ID of this handle, used to compare against the return value of
+    /// `Select::wait()`
+    id: uint,
+    selector: &'rx Select,
+    next: *mut Handle<'static, ()>,
+    prev: *mut Handle<'static, ()>,
+    added: bool,
+    packet: &'rx (Packet+'rx),
+
+    // due to our fun transmutes, we be sure to place this at the end. (nothing
+    // previous relies on T)
+    rx: &'rx Receiver<T>,
+}
+
+struct Packets { cur: *mut Handle<'static, ()> }
+
+#[doc(hidden)]
+#[deriving(PartialEq)]
+pub enum StartResult {
+    Installed,
+    Abort,
+}
+
+#[doc(hidden)]
+pub trait Packet {
+    fn can_recv(&self) -> bool;
+    fn start_selection(&self, token: SignalToken) -> StartResult;
+    fn abort_selection(&self) -> bool;
+}
+
+impl Select {
+    /// Creates a new selection structure. This set is initially empty and
+    /// `wait` will panic!() if called.
+    ///
+    /// Usage of this struct directly can sometimes be burdensome, and usage is
+    /// rather much easier through the `select!` macro.
+    pub fn new() -> Select {
+        Select {
+            marker1: marker::NoSend,
+            head: 0 as *mut Handle<'static, ()>,
+            tail: 0 as *mut Handle<'static, ()>,
+            next_id: Cell::new(1),
+        }
+    }
+
+    /// Creates a new handle into this receiver set for a new receiver. Note
+    /// that this does *not* add the receiver to the receiver set, for that you
+    /// must call the `add` method on the handle itself.
+    pub fn handle<'a, T: Send>(&'a self, rx: &'a Receiver<T>) -> Handle<'a, T> {
+        let id = self.next_id.get();
+        self.next_id.set(id + 1);
+        Handle {
+            id: id,
+            selector: self,
+            next: 0 as *mut Handle<'static, ()>,
+            prev: 0 as *mut Handle<'static, ()>,
+            added: false,
+            rx: rx,
+            packet: rx,
+        }
+    }
+
+    /// Waits for an event on this receiver set. The returned value is *not* an
+    /// index, but rather an id. This id can be queried against any active
+    /// `Handle` structures (each one has an `id` method). The handle with
+    /// the matching `id` will have some sort of event available on it. The
+    /// event could either be that data is available or the corresponding
+    /// channel has been closed.
+    pub fn wait(&self) -> uint {
+        self.wait2(true)
+    }
+
+    /// Helper method for skipping the preflight checks during testing
+    fn wait2(&self, do_preflight_checks: bool) -> uint {
+        // Note that this is currently an inefficient implementation. We in
+        // theory have knowledge about all receivers in the set ahead of time,
+        // so this method shouldn't really have to iterate over all of them yet
+        // again. The idea with this "receiver set" interface is to get the
+        // interface right this time around, and later this implementation can
+        // be optimized.
+        //
+        // This implementation can be summarized by:
+        //
+        //      fn select(receivers) {
+        //          if any receiver ready { return ready index }
+        //          deschedule {
+        //              block on all receivers
+        //          }
+        //          unblock on all receivers
+        //          return ready index
+        //      }
+        //
+        // Most notably, the iterations over all of the receivers shouldn't be
+        // necessary.
+        unsafe {
+            // Stage 1: preflight checks. Look for any packets ready to receive
+            if do_preflight_checks {
+                for handle in self.iter() {
+                    if (*handle).packet.can_recv() {
+                        return (*handle).id();
+                    }
+                }
+            }
+
+            // Stage 2: begin the blocking process
+            //
+            // Create a number of signal tokens, and install each one
+            // sequentially until one fails. If one fails, then abort the
+            // selection on the already-installed tokens.
+            let (wait_token, signal_token) = blocking::tokens();
+            for (i, handle) in self.iter().enumerate() {
+                match (*handle).packet.start_selection(signal_token.clone()) {
+                    StartResult::Installed => {}
+                    StartResult::Abort => {
+                        // Go back and abort the already-begun selections
+                        for handle in self.iter().take(i) {
+                            (*handle).packet.abort_selection();
+                        }
+                        return (*handle).id;
+                    }
+                }
+            }
+
+            // Stage 3: no messages available, actually block
+            wait_token.wait();
+
+            // Stage 4: there *must* be message available; find it.
+            //
+            // Abort the selection process on each receiver. If the abort
+            // process returns `true`, then that means that the receiver is
+            // ready to receive some data. Note that this also means that the
+            // receiver may have yet to have fully read the `to_wake` field and
+            // woken us up (although the wakeup is guaranteed to fail).
+            //
+            // This situation happens in the window of where a sender invokes
+            // increment(), sees -1, and then decides to wake up the task. After
+            // all this is done, the sending thread will set `selecting` to
+            // `false`. Until this is done, we cannot return. If we were to
+            // return, then a sender could wake up a receiver which has gone
+            // back to sleep after this call to `select`.
+            //
+            // Note that it is a "fairly small window" in which an increment()
+            // views that it should wake a thread up until the `selecting` bit
+            // is set to false. For now, the implementation currently just spins
+            // in a yield loop. This is very distasteful, but this
+            // implementation is already nowhere near what it should ideally be.
+            // A rewrite should focus on avoiding a yield loop, and for now this
+            // implementation is tying us over to a more efficient "don't
+            // iterate over everything every time" implementation.
+            let mut ready_id = uint::MAX;
+            for handle in self.iter() {
+                if (*handle).packet.abort_selection() {
+                    ready_id = (*handle).id;
+                }
+            }
+
+            // We must have found a ready receiver
+            assert!(ready_id != uint::MAX);
+            return ready_id;
+        }
+    }
+
+    fn iter(&self) -> Packets { Packets { cur: self.head } }
+}
+
+impl<'rx, T: Send> Handle<'rx, T> {
+    /// Retrieve the id of this handle.
+    #[inline]
+    pub fn id(&self) -> uint { self.id }
+
+    /// Receive a value on the underlying receiver. Has the same semantics as
+    /// `Receiver.recv`
+    pub fn recv(&mut self) -> T { self.rx.recv() }
+    /// Block to receive a value on the underlying receiver, returning `Some` on
+    /// success or `None` if the channel disconnects. This function has the same
+    /// semantics as `Receiver.recv_opt`
+    pub fn recv_opt(&mut self) -> Result<T, ()> { self.rx.recv_opt() }
+
+    /// Adds this handle to the receiver set that the handle was created from. This
+    /// method can be called multiple times, but it has no effect if `add` was
+    /// called previously.
+    ///
+    /// This method is unsafe because it requires that the `Handle` is not moved
+    /// while it is added to the `Select` set.
+    pub unsafe fn add(&mut self) {
+        if self.added { return }
+        let selector: &mut Select = mem::transmute(&*self.selector);
+        let me: *mut Handle<'static, ()> = mem::transmute(&*self);
+
+        if selector.head.is_null() {
+            selector.head = me;
+            selector.tail = me;
+        } else {
+            (*me).prev = selector.tail;
+            assert!((*me).next.is_null());
+            (*selector.tail).next = me;
+            selector.tail = me;
+        }
+        self.added = true;
+    }
+
+    /// Removes this handle from the `Select` set. This method is unsafe because
+    /// it has no guarantee that the `Handle` was not moved since `add` was
+    /// called.
+    pub unsafe fn remove(&mut self) {
+        if !self.added { return }
+
+        let selector: &mut Select = mem::transmute(&*self.selector);
+        let me: *mut Handle<'static, ()> = mem::transmute(&*self);
+
+        if self.prev.is_null() {
+            assert_eq!(selector.head, me);
+            selector.head = self.next;
+        } else {
+            (*self.prev).next = self.next;
+        }
+        if self.next.is_null() {
+            assert_eq!(selector.tail, me);
+            selector.tail = self.prev;
+        } else {
+            (*self.next).prev = self.prev;
+        }
+
+        self.next = 0 as *mut Handle<'static, ()>;
+        self.prev = 0 as *mut Handle<'static, ()>;
+
+        self.added = false;
+    }
+}
+
+#[unsafe_destructor]
+impl Drop for Select {
+    fn drop(&mut self) {
+        assert!(self.head.is_null());
+        assert!(self.tail.is_null());
+    }
+}
+
+#[unsafe_destructor]
+impl<'rx, T: Send> Drop for Handle<'rx, T> {
+    fn drop(&mut self) {
+        unsafe { self.remove() }
+    }
+}
+
+impl Iterator<*mut Handle<'static, ()>> for Packets {
+    fn next(&mut self) -> Option<*mut Handle<'static, ()>> {
+        if self.cur.is_null() {
+            None
+        } else {
+            let ret = Some(self.cur);
+            unsafe { self.cur = (*self.cur).next; }
+            ret
+        }
+    }
+}
+
+#[cfg(test)]
+#[allow(unused_imports)]
+mod test {
+    use prelude::*;
+
+    use super::*;
+
+    // Don't use the libstd version so we can pull in the right Select structure
+    // (std::comm points at the wrong one)
+    macro_rules! select {
+        (
+            $($name:pat = $rx:ident.$meth:ident() => $code:expr),+
+        ) => ({
+            use comm::Select;
+            let sel = Select::new();
+            $( let mut $rx = sel.handle(&$rx); )+
+            unsafe {
+                $( $rx.add(); )+
+            }
+            let ret = sel.wait();
+            $( if ret == $rx.id() { let $name = $rx.$meth(); $code } else )+
+            { unreachable!() }
+        })
+    }
+
+    test! { fn smoke() {
+        let (tx1, rx1) = channel::<int>();
+        let (tx2, rx2) = channel::<int>();
+        tx1.send(1);
+        select! {
+            foo = rx1.recv() => { assert_eq!(foo, 1); },
+            _bar = rx2.recv() => { panic!() }
+        }
+        tx2.send(2);
+        select! {
+            _foo = rx1.recv() => { panic!() },
+            bar = rx2.recv() => { assert_eq!(bar, 2) }
+        }
+        drop(tx1);
+        select! {
+            foo = rx1.recv_opt() => { assert_eq!(foo, Err(())); },
+            _bar = rx2.recv() => { panic!() }
+        }
+        drop(tx2);
+        select! {
+            bar = rx2.recv_opt() => { assert_eq!(bar, Err(())); }
+        }
+    } }
+
+    test! { fn smoke2() {
+        let (_tx1, rx1) = channel::<int>();
+        let (_tx2, rx2) = channel::<int>();
+        let (_tx3, rx3) = channel::<int>();
+        let (_tx4, rx4) = channel::<int>();
+        let (tx5, rx5) = channel::<int>();
+        tx5.send(4);
+        select! {
+            _foo = rx1.recv() => { panic!("1") },
+            _foo = rx2.recv() => { panic!("2") },
+            _foo = rx3.recv() => { panic!("3") },
+            _foo = rx4.recv() => { panic!("4") },
+            foo = rx5.recv() => { assert_eq!(foo, 4); }
+        }
+    } }
+
+    test! { fn closed() {
+        let (_tx1, rx1) = channel::<int>();
+        let (tx2, rx2) = channel::<int>();
+        drop(tx2);
+
+        select! {
+            _a1 = rx1.recv_opt() => { panic!() },
+            a2 = rx2.recv_opt() => { assert_eq!(a2, Err(())); }
+        }
+    } }
+
+    test! { fn unblocks() {
+        let (tx1, rx1) = channel::<int>();
+        let (_tx2, rx2) = channel::<int>();
+        let (tx3, rx3) = channel::<int>();
+
+        spawn(move|| {
+            for _ in range(0u, 20) { Thread::yield_now(); }
+            tx1.send(1);
+            rx3.recv();
+            for _ in range(0u, 20) { Thread::yield_now(); }
+        });
+
+        select! {
+            a = rx1.recv() => { assert_eq!(a, 1); },
+            _b = rx2.recv() => { panic!() }
+        }
+        tx3.send(1);
+        select! {
+            a = rx1.recv_opt() => { assert_eq!(a, Err(())); },
+            _b = rx2.recv() => { panic!() }
+        }
+    } }
+
+    test! { fn both_ready() {
+        let (tx1, rx1) = channel::<int>();
+        let (tx2, rx2) = channel::<int>();
+        let (tx3, rx3) = channel::<()>();
+
+        spawn(move|| {
+            for _ in range(0u, 20) { Thread::yield_now(); }
+            tx1.send(1);
+            tx2.send(2);
+            rx3.recv();
+        });
+
+        select! {
+            a = rx1.recv() => { assert_eq!(a, 1); },
+            a = rx2.recv() => { assert_eq!(a, 2); }
+        }
+        select! {
+            a = rx1.recv() => { assert_eq!(a, 1); },
+            a = rx2.recv() => { assert_eq!(a, 2); }
+        }
+        assert_eq!(rx1.try_recv(), Err(Empty));
+        assert_eq!(rx2.try_recv(), Err(Empty));
+        tx3.send(());
+    } }
+
+    test! { fn stress() {
+        static AMT: int = 10000;
+        let (tx1, rx1) = channel::<int>();
+        let (tx2, rx2) = channel::<int>();
+        let (tx3, rx3) = channel::<()>();
+
+        spawn(move|| {
+            for i in range(0, AMT) {
+                if i % 2 == 0 {
+                    tx1.send(i);
+                } else {
+                    tx2.send(i);
+                }
+                rx3.recv();
+            }
+        });
+
+        for i in range(0, AMT) {
+            select! {
+                i1 = rx1.recv() => { assert!(i % 2 == 0 && i == i1); },
+                i2 = rx2.recv() => { assert!(i % 2 == 1 && i == i2); }
+            }
+            tx3.send(());
+        }
+    } }
+
+    test! { fn cloning() {
+        let (tx1, rx1) = channel::<int>();
+        let (_tx2, rx2) = channel::<int>();
+        let (tx3, rx3) = channel::<()>();
+
+        spawn(move|| {
+            rx3.recv();
+            tx1.clone();
+            assert_eq!(rx3.try_recv(), Err(Empty));
+            tx1.send(2);
+            rx3.recv();
+        });
+
+        tx3.send(());
+        select! {
+            _i1 = rx1.recv() => {},
+            _i2 = rx2.recv() => panic!()
+        }
+        tx3.send(());
+    } }
+
+    test! { fn cloning2() {
+        let (tx1, rx1) = channel::<int>();
+        let (_tx2, rx2) = channel::<int>();
+        let (tx3, rx3) = channel::<()>();
+
+        spawn(move|| {
+            rx3.recv();
+            tx1.clone();
+            assert_eq!(rx3.try_recv(), Err(Empty));
+            tx1.send(2);
+            rx3.recv();
+        });
+
+        tx3.send(());
+        select! {
+            _i1 = rx1.recv() => {},
+            _i2 = rx2.recv() => panic!()
+        }
+        tx3.send(());
+    } }
+
+    test! { fn cloning3() {
+        let (tx1, rx1) = channel::<()>();
+        let (tx2, rx2) = channel::<()>();
+        let (tx3, rx3) = channel::<()>();
+        spawn(move|| {
+            let s = Select::new();
+            let mut h1 = s.handle(&rx1);
+            let mut h2 = s.handle(&rx2);
+            unsafe { h2.add(); }
+            unsafe { h1.add(); }
+            assert_eq!(s.wait(), h2.id);
+            tx3.send(());
+        });
+
+        for _ in range(0u, 1000) { Thread::yield_now(); }
+        drop(tx1.clone());
+        tx2.send(());
+        rx3.recv();
+    } }
+
+    test! { fn preflight1() {
+        let (tx, rx) = channel();
+        tx.send(());
+        select! {
+            () = rx.recv() => {}
+        }
+    } }
+
+    test! { fn preflight2() {
+        let (tx, rx) = channel();
+        tx.send(());
+        tx.send(());
+        select! {
+            () = rx.recv() => {}
+        }
+    } }
+
+    test! { fn preflight3() {
+        let (tx, rx) = channel();
+        drop(tx.clone());
+        tx.send(());
+        select! {
+            () = rx.recv() => {}
+        }
+    } }
+
+    test! { fn preflight4() {
+        let (tx, rx) = channel();
+        tx.send(());
+        let s = Select::new();
+        let mut h = s.handle(&rx);
+        unsafe { h.add(); }
+        assert_eq!(s.wait2(false), h.id);
+    } }
+
+    test! { fn preflight5() {
+        let (tx, rx) = channel();
+        tx.send(());
+        tx.send(());
+        let s = Select::new();
+        let mut h = s.handle(&rx);
+        unsafe { h.add(); }
+        assert_eq!(s.wait2(false), h.id);
+    } }
+
+    test! { fn preflight6() {
+        let (tx, rx) = channel();
+        drop(tx.clone());
+        tx.send(());
+        let s = Select::new();
+        let mut h = s.handle(&rx);
+        unsafe { h.add(); }
+        assert_eq!(s.wait2(false), h.id);
+    } }
+
+    test! { fn preflight7() {
+        let (tx, rx) = channel::<()>();
+        drop(tx);
+        let s = Select::new();
+        let mut h = s.handle(&rx);
+        unsafe { h.add(); }
+        assert_eq!(s.wait2(false), h.id);
+    } }
+
+    test! { fn preflight8() {
+        let (tx, rx) = channel();
+        tx.send(());
+        drop(tx);
+        rx.recv();
+        let s = Select::new();
+        let mut h = s.handle(&rx);
+        unsafe { h.add(); }
+        assert_eq!(s.wait2(false), h.id);
+    } }
+
+    test! { fn preflight9() {
+        let (tx, rx) = channel();
+        drop(tx.clone());
+        tx.send(());
+        drop(tx);
+        rx.recv();
+        let s = Select::new();
+        let mut h = s.handle(&rx);
+        unsafe { h.add(); }
+        assert_eq!(s.wait2(false), h.id);
+    } }
+
+    test! { fn oneshot_data_waiting() {
+        let (tx1, rx1) = channel();
+        let (tx2, rx2) = channel();
+        spawn(move|| {
+            select! {
+                () = rx1.recv() => {}
+            }
+            tx2.send(());
+        });
+
+        for _ in range(0u, 100) { Thread::yield_now() }
+        tx1.send(());
+        rx2.recv();
+    } }
+
+    test! { fn stream_data_waiting() {
+        let (tx1, rx1) = channel();
+        let (tx2, rx2) = channel();
+        tx1.send(());
+        tx1.send(());
+        rx1.recv();
+        rx1.recv();
+        spawn(move|| {
+            select! {
+                () = rx1.recv() => {}
+            }
+            tx2.send(());
+        });
+
+        for _ in range(0u, 100) { Thread::yield_now() }
+        tx1.send(());
+        rx2.recv();
+    } }
+
+    test! { fn shared_data_waiting() {
+        let (tx1, rx1) = channel();
+        let (tx2, rx2) = channel();
+        drop(tx1.clone());
+        tx1.send(());
+        rx1.recv();
+        spawn(move|| {
+            select! {
+                () = rx1.recv() => {}
+            }
+            tx2.send(());
+        });
+
+        for _ in range(0u, 100) { Thread::yield_now() }
+        tx1.send(());
+        rx2.recv();
+    } }
+
+    test! { fn sync1() {
+        let (tx, rx) = sync_channel::<int>(1);
+        tx.send(1);
+        select! {
+            n = rx.recv() => { assert_eq!(n, 1); }
+        }
+    } }
+
+    test! { fn sync2() {
+        let (tx, rx) = sync_channel::<int>(0);
+        spawn(move|| {
+            for _ in range(0u, 100) { Thread::yield_now() }
+            tx.send(1);
+        });
+        select! {
+            n = rx.recv() => { assert_eq!(n, 1); }
+        }
+    } }
+
+    test! { fn sync3() {
+        let (tx1, rx1) = sync_channel::<int>(0);
+        let (tx2, rx2): (Sender<int>, Receiver<int>) = channel();
+        spawn(move|| { tx1.send(1); });
+        spawn(move|| { tx2.send(2); });
+        select! {
+            n = rx1.recv() => {
+                assert_eq!(n, 1);
+                assert_eq!(rx2.recv(), 2);
+            },
+            n = rx2.recv() => {
+                assert_eq!(n, 2);
+                assert_eq!(rx1.recv(), 1);
+            }
+        }
+    } }
+}
diff --git a/src/libstd/comm/shared.rs b/src/libstd/comm/shared.rs
new file mode 100644
index 00000000000..1022694e634
--- /dev/null
+++ b/src/libstd/comm/shared.rs
@@ -0,0 +1,486 @@
+// 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.
+
+/// Shared channels
+///
+/// This is the flavor of channels which are not necessarily optimized for any
+/// particular use case, but are the most general in how they are used. Shared
+/// channels are cloneable allowing for multiple senders.
+///
+/// High level implementation details can be found in the comment of the parent
+/// module. You'll also note that the implementation of the shared and stream
+/// channels are quite similar, and this is no coincidence!
+
+pub use self::Failure::*;
+
+use core::prelude::*;
+
+use core::cmp;
+use core::int;
+
+use sync::{atomic, Mutex, MutexGuard};
+use comm::mpsc_queue as mpsc;
+use comm::blocking::{mod, SignalToken};
+use comm::select::StartResult;
+use comm::select::StartResult::*;
+use thread::Thread;
+
+const DISCONNECTED: int = int::MIN;
+const FUDGE: int = 1024;
+#[cfg(test)]
+const MAX_STEALS: int = 5;
+#[cfg(not(test))]
+const MAX_STEALS: int = 1 << 20;
+
+pub struct Packet<T> {
+    queue: mpsc::Queue<T>,
+    cnt: atomic::AtomicInt, // How many items are on this channel
+    steals: int, // How many times has a port received without blocking?
+    to_wake: atomic::AtomicUint, // SignalToken for wake up
+
+    // The number of channels which are currently using this packet.
+    channels: atomic::AtomicInt,
+
+    // See the discussion in Port::drop and the channel send methods for what
+    // these are used for
+    port_dropped: atomic::AtomicBool,
+    sender_drain: atomic::AtomicInt,
+
+    // this lock protects various portions of this implementation during
+    // select()
+    select_lock: Mutex<()>,
+}
+
+pub enum Failure {
+    Empty,
+    Disconnected,
+}
+
+impl<T: Send> Packet<T> {
+    // Creation of a packet *must* be followed by a call to postinit_lock
+    // and later by inherit_blocker
+    pub fn new() -> Packet<T> {
+        let p = Packet {
+            queue: mpsc::Queue::new(),
+            cnt: atomic::AtomicInt::new(0),
+            steals: 0,
+            to_wake: atomic::AtomicUint::new(0),
+            channels: atomic::AtomicInt::new(2),
+            port_dropped: atomic::AtomicBool::new(false),
+            sender_drain: atomic::AtomicInt::new(0),
+            select_lock: Mutex::new(()),
+        };
+        return p;
+    }
+
+    // This function should be used after newly created Packet
+    // was wrapped with an Arc
+    // In other case mutex data will be duplicated while cloning
+    // and that could cause problems on platforms where it is
+    // represented by opaque data structure
+    pub fn postinit_lock(&self) -> MutexGuard<()> {
+        self.select_lock.lock()
+    }
+
+    // This function is used at the creation of a shared packet to inherit a
+    // previously blocked task. This is done to prevent spurious wakeups of
+    // tasks in select().
+    //
+    // This can only be called at channel-creation time
+    pub fn inherit_blocker(&mut self,
+                           token: Option<SignalToken>,
+                           guard: MutexGuard<()>) {
+        token.map(|token| {
+            assert_eq!(self.cnt.load(atomic::SeqCst), 0);
+            assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
+            self.to_wake.store(unsafe { token.cast_to_uint() }, atomic::SeqCst);
+            self.cnt.store(-1, atomic::SeqCst);
+
+            // This store is a little sketchy. What's happening here is that
+            // we're transferring a blocker from a oneshot or stream channel to
+            // this shared channel. In doing so, we never spuriously wake them
+            // up and rather only wake them up at the appropriate time. This
+            // implementation of shared channels assumes that any blocking
+            // recv() will undo the increment of steals performed in try_recv()
+            // once the recv is complete.  This thread that we're inheriting,
+            // however, is not in the middle of recv. Hence, the first time we
+            // wake them up, they're going to wake up from their old port, move
+            // on to the upgraded port, and then call the block recv() function.
+            //
+            // When calling this function, they'll find there's data immediately
+            // available, counting it as a steal. This in fact wasn't a steal
+            // because we appropriately blocked them waiting for data.
+            //
+            // To offset this bad increment, we initially set the steal count to
+            // -1. You'll find some special code in abort_selection() as well to
+            // ensure that this -1 steal count doesn't escape too far.
+            self.steals = -1;
+        });
+
+        // When the shared packet is constructed, we grabbed this lock. The
+        // purpose of this lock is to ensure that abort_selection() doesn't
+        // interfere with this method. After we unlock this lock, we're
+        // signifying that we're done modifying self.cnt and self.to_wake and
+        // the port is ready for the world to continue using it.
+        drop(guard);
+    }
+
+    pub fn send(&mut self, t: T) -> Result<(), T> {
+        // See Port::drop for what's going on
+        if self.port_dropped.load(atomic::SeqCst) { return Err(t) }
+
+        // Note that the multiple sender case is a little trickier
+        // semantically than the single sender case. The logic for
+        // incrementing is "add and if disconnected store disconnected".
+        // This could end up leading some senders to believe that there
+        // wasn't a disconnect if in fact there was a disconnect. This means
+        // that while one thread is attempting to re-store the disconnected
+        // states, other threads could walk through merrily incrementing
+        // this very-negative disconnected count. To prevent senders from
+        // spuriously attempting to send when the channels is actually
+        // disconnected, the count has a ranged check here.
+        //
+        // This is also done for another reason. Remember that the return
+        // value of this function is:
+        //
+        //  `true` == the data *may* be received, this essentially has no
+        //            meaning
+        //  `false` == the data will *never* be received, this has a lot of
+        //             meaning
+        //
+        // In the SPSC case, we have a check of 'queue.is_empty()' to see
+        // whether the data was actually received, but this same condition
+        // means nothing in a multi-producer context. As a result, this
+        // preflight check serves as the definitive "this will never be
+        // received". Once we get beyond this check, we have permanently
+        // entered the realm of "this may be received"
+        if self.cnt.load(atomic::SeqCst) < DISCONNECTED + FUDGE {
+            return Err(t)
+        }
+
+        self.queue.push(t);
+        match self.cnt.fetch_add(1, atomic::SeqCst) {
+            -1 => {
+                self.take_to_wake().signal();
+            }
+
+            // In this case, we have possibly failed to send our data, and
+            // we need to consider re-popping the data in order to fully
+            // destroy it. We must arbitrate among the multiple senders,
+            // however, because the queues that we're using are
+            // single-consumer queues. In order to do this, all exiting
+            // pushers will use an atomic count in order to count those
+            // flowing through. Pushers who see 0 are required to drain as
+            // much as possible, and then can only exit when they are the
+            // only pusher (otherwise they must try again).
+            n if n < DISCONNECTED + FUDGE => {
+                // see the comment in 'try' for a shared channel for why this
+                // window of "not disconnected" is ok.
+                self.cnt.store(DISCONNECTED, atomic::SeqCst);
+
+                if self.sender_drain.fetch_add(1, atomic::SeqCst) == 0 {
+                    loop {
+                        // drain the queue, for info on the thread yield see the
+                        // discussion in try_recv
+                        loop {
+                            match self.queue.pop() {
+                                mpsc::Data(..) => {}
+                                mpsc::Empty => break,
+                                mpsc::Inconsistent => Thread::yield_now(),
+                            }
+                        }
+                        // maybe we're done, if we're not the last ones
+                        // here, then we need to go try again.
+                        if self.sender_drain.fetch_sub(1, atomic::SeqCst) == 1 {
+                            break
+                        }
+                    }
+
+                    // At this point, there may still be data on the queue,
+                    // but only if the count hasn't been incremented and
+                    // some other sender hasn't finished pushing data just
+                    // yet. That sender in question will drain its own data.
+                }
+            }
+
+            // Can't make any assumptions about this case like in the SPSC case.
+            _ => {}
+        }
+
+        Ok(())
+    }
+
+    pub fn recv(&mut self) -> Result<T, Failure> {
+        // This code is essentially the exact same as that found in the stream
+        // case (see stream.rs)
+        match self.try_recv() {
+            Err(Empty) => {}
+            data => return data,
+        }
+
+        let (wait_token, signal_token) = blocking::tokens();
+        if self.decrement(signal_token) == Installed {
+            wait_token.wait()
+        }
+
+        match self.try_recv() {
+            data @ Ok(..) => { self.steals -= 1; data }
+            data => data,
+        }
+    }
+
+    // Essentially the exact same thing as the stream decrement function.
+    // Returns true if blocking should proceed.
+    fn decrement(&mut self, token: SignalToken) -> StartResult {
+        assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
+        let ptr = unsafe { token.cast_to_uint() };
+        self.to_wake.store(ptr, atomic::SeqCst);
+
+        let steals = self.steals;
+        self.steals = 0;
+
+        match self.cnt.fetch_sub(1 + steals, atomic::SeqCst) {
+            DISCONNECTED => { self.cnt.store(DISCONNECTED, atomic::SeqCst); }
+            // If we factor in our steals and notice that the channel has no
+            // data, we successfully sleep
+            n => {
+                assert!(n >= 0);
+                if n - steals <= 0 { return Installed }
+            }
+        }
+
+        self.to_wake.store(0, atomic::SeqCst);
+        drop(unsafe { SignalToken::cast_from_uint(ptr) });
+        Abort
+    }
+
+    pub fn try_recv(&mut self) -> Result<T, Failure> {
+        let ret = match self.queue.pop() {
+            mpsc::Data(t) => Some(t),
+            mpsc::Empty => None,
+
+            // This is a bit of an interesting case. The channel is reported as
+            // having data available, but our pop() has failed due to the queue
+            // being in an inconsistent state.  This means that there is some
+            // pusher somewhere which has yet to complete, but we are guaranteed
+            // that a pop will eventually succeed. In this case, we spin in a
+            // yield loop because the remote sender should finish their enqueue
+            // operation "very quickly".
+            //
+            // Avoiding this yield loop would require a different queue
+            // abstraction which provides the guarantee that after M pushes have
+            // succeeded, at least M pops will succeed. The current queues
+            // guarantee that if there are N active pushes, you can pop N times
+            // once all N have finished.
+            mpsc::Inconsistent => {
+                let data;
+                loop {
+                    Thread::yield_now();
+                    match self.queue.pop() {
+                        mpsc::Data(t) => { data = t; break }
+                        mpsc::Empty => panic!("inconsistent => empty"),
+                        mpsc::Inconsistent => {}
+                    }
+                }
+                Some(data)
+            }
+        };
+        match ret {
+            // See the discussion in the stream implementation for why we
+            // might decrement steals.
+            Some(data) => {
+                if self.steals > MAX_STEALS {
+                    match self.cnt.swap(0, atomic::SeqCst) {
+                        DISCONNECTED => {
+                            self.cnt.store(DISCONNECTED, atomic::SeqCst);
+                        }
+                        n => {
+                            let m = cmp::min(n, self.steals);
+                            self.steals -= m;
+                            self.bump(n - m);
+                        }
+                    }
+                    assert!(self.steals >= 0);
+                }
+                self.steals += 1;
+                Ok(data)
+            }
+
+            // See the discussion in the stream implementation for why we try
+            // again.
+            None => {
+                match self.cnt.load(atomic::SeqCst) {
+                    n if n != DISCONNECTED => Err(Empty),
+                    _ => {
+                        match self.queue.pop() {
+                            mpsc::Data(t) => Ok(t),
+                            mpsc::Empty => Err(Disconnected),
+                            // with no senders, an inconsistency is impossible.
+                            mpsc::Inconsistent => unreachable!(),
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    // Prepares this shared packet for a channel clone, essentially just bumping
+    // a refcount.
+    pub fn clone_chan(&mut self) {
+        self.channels.fetch_add(1, atomic::SeqCst);
+    }
+
+    // Decrement the reference count on a channel. This is called whenever a
+    // Chan is dropped and may end up waking up a receiver. It's the receiver's
+    // responsibility on the other end to figure out that we've disconnected.
+    pub fn drop_chan(&mut self) {
+        match self.channels.fetch_sub(1, atomic::SeqCst) {
+            1 => {}
+            n if n > 1 => return,
+            n => panic!("bad number of channels left {}", n),
+        }
+
+        match self.cnt.swap(DISCONNECTED, atomic::SeqCst) {
+            -1 => { self.take_to_wake().signal(); }
+            DISCONNECTED => {}
+            n => { assert!(n >= 0); }
+        }
+    }
+
+    // See the long discussion inside of stream.rs for why the queue is drained,
+    // and why it is done in this fashion.
+    pub fn drop_port(&mut self) {
+        self.port_dropped.store(true, atomic::SeqCst);
+        let mut steals = self.steals;
+        while {
+            let cnt = self.cnt.compare_and_swap(steals, DISCONNECTED, atomic::SeqCst);
+            cnt != DISCONNECTED && cnt != steals
+        } {
+            // See the discussion in 'try_recv' for why we yield
+            // control of this thread.
+            loop {
+                match self.queue.pop() {
+                    mpsc::Data(..) => { steals += 1; }
+                    mpsc::Empty | mpsc::Inconsistent => break,
+                }
+            }
+        }
+    }
+
+    // Consumes ownership of the 'to_wake' field.
+    fn take_to_wake(&mut self) -> SignalToken {
+        let ptr = self.to_wake.load(atomic::SeqCst);
+        self.to_wake.store(0, atomic::SeqCst);
+        assert!(ptr != 0);
+        unsafe { SignalToken::cast_from_uint(ptr) }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // select implementation
+    ////////////////////////////////////////////////////////////////////////////
+
+    // Helper function for select, tests whether this port can receive without
+    // blocking (obviously not an atomic decision).
+    //
+    // This is different than the stream version because there's no need to peek
+    // at the queue, we can just look at the local count.
+    pub fn can_recv(&mut self) -> bool {
+        let cnt = self.cnt.load(atomic::SeqCst);
+        cnt == DISCONNECTED || cnt - self.steals > 0
+    }
+
+    // increment the count on the channel (used for selection)
+    fn bump(&mut self, amt: int) -> int {
+        match self.cnt.fetch_add(amt, atomic::SeqCst) {
+            DISCONNECTED => {
+                self.cnt.store(DISCONNECTED, atomic::SeqCst);
+                DISCONNECTED
+            }
+            n => n
+        }
+    }
+
+    // Inserts the signal token for selection on this port, returning true if
+    // blocking should proceed.
+    //
+    // The code here is the same as in stream.rs, except that it doesn't need to
+    // peek at the channel to see if an upgrade is pending.
+    pub fn start_selection(&mut self, token: SignalToken) -> StartResult {
+        match self.decrement(token) {
+            Installed => Installed,
+            Abort => {
+                let prev = self.bump(1);
+                assert!(prev == DISCONNECTED || prev >= 0);
+                Abort
+            }
+        }
+    }
+
+    // Cancels a previous task waiting on this port, returning whether there's
+    // data on the port.
+    //
+    // This is similar to the stream implementation (hence fewer comments), but
+    // uses a different value for the "steals" variable.
+    pub fn abort_selection(&mut self, _was_upgrade: bool) -> bool {
+        // Before we do anything else, we bounce on this lock. The reason for
+        // doing this is to ensure that any upgrade-in-progress is gone and
+        // done with. Without this bounce, we can race with inherit_blocker
+        // about looking at and dealing with to_wake. Once we have acquired the
+        // lock, we are guaranteed that inherit_blocker is done.
+        {
+            let _guard = self.select_lock.lock();
+        }
+
+        // Like the stream implementation, we want to make sure that the count
+        // on the channel goes non-negative. We don't know how negative the
+        // stream currently is, so instead of using a steal value of 1, we load
+        // the channel count and figure out what we should do to make it
+        // positive.
+        let steals = {
+            let cnt = self.cnt.load(atomic::SeqCst);
+            if cnt < 0 && cnt != DISCONNECTED {-cnt} else {0}
+        };
+        let prev = self.bump(steals + 1);
+
+        if prev == DISCONNECTED {
+            assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
+            true
+        } else {
+            let cur = prev + steals + 1;
+            assert!(cur >= 0);
+            if prev < 0 {
+                drop(self.take_to_wake());
+            } else {
+                while self.to_wake.load(atomic::SeqCst) != 0 {
+                    Thread::yield_now();
+                }
+            }
+            // if the number of steals is -1, it was the pre-emptive -1 steal
+            // count from when we inherited a blocker. This is fine because
+            // we're just going to overwrite it with a real value.
+            assert!(self.steals == 0 || self.steals == -1);
+            self.steals = steals;
+            prev >= 0
+        }
+    }
+}
+
+#[unsafe_destructor]
+impl<T: Send> Drop for Packet<T> {
+    fn drop(&mut self) {
+        // Note that this load is not only an assert for correctness about
+        // disconnection, but also a proper fence before the read of
+        // `to_wake`, so this assert cannot be removed with also removing
+        // the `to_wake` assert.
+        assert_eq!(self.cnt.load(atomic::SeqCst), DISCONNECTED);
+        assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
+        assert_eq!(self.channels.load(atomic::SeqCst), 0);
+    }
+}
diff --git a/src/libstd/comm/spsc_queue.rs b/src/libstd/comm/spsc_queue.rs
new file mode 100644
index 00000000000..db8fff772a4
--- /dev/null
+++ b/src/libstd/comm/spsc_queue.rs
@@ -0,0 +1,337 @@
+/* Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *    1. Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *
+ *    2. Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are
+ * those of the authors and should not be interpreted as representing official
+ * policies, either expressed or implied, of Dmitry Vyukov.
+ */
+
+// http://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue
+
+//! A single-producer single-consumer concurrent queue
+//!
+//! This module contains the implementation of an SPSC queue which can be used
+//! concurrently between two tasks. This data structure is safe to use and
+//! enforces the semantics that there is one pusher and one popper.
+
+#![experimental]
+
+use core::prelude::*;
+
+use alloc::boxed::Box;
+use core::mem;
+use core::cell::UnsafeCell;
+
+use sync::atomic::{AtomicPtr, Relaxed, AtomicUint, Acquire, Release};
+
+// Node within the linked list queue of messages to send
+struct Node<T> {
+    // FIXME: this could be an uninitialized T if we're careful enough, and
+    //      that would reduce memory usage (and be a bit faster).
+    //      is it worth it?
+    value: Option<T>,           // nullable for re-use of nodes
+    next: AtomicPtr<Node<T>>,   // next node in the queue
+}
+
+/// The single-producer single-consumer queue. This structure is not cloneable,
+/// but it can be safely shared in an Arc if it is guaranteed that there
+/// is only one popper and one pusher touching the queue at any one point in
+/// time.
+pub struct Queue<T> {
+    // consumer fields
+    tail: UnsafeCell<*mut Node<T>>, // where to pop from
+    tail_prev: AtomicPtr<Node<T>>, // where to pop from
+
+    // producer fields
+    head: UnsafeCell<*mut Node<T>>,      // where to push to
+    first: UnsafeCell<*mut Node<T>>,     // where to get new nodes from
+    tail_copy: UnsafeCell<*mut Node<T>>, // between first/tail
+
+    // Cache maintenance fields. Additions and subtractions are stored
+    // separately in order to allow them to use nonatomic addition/subtraction.
+    cache_bound: uint,
+    cache_additions: AtomicUint,
+    cache_subtractions: AtomicUint,
+}
+
+impl<T: Send> Node<T> {
+    fn new() -> *mut Node<T> {
+        unsafe {
+            mem::transmute(box Node {
+                value: None,
+                next: AtomicPtr::new(0 as *mut Node<T>),
+            })
+        }
+    }
+}
+
+impl<T: Send> Queue<T> {
+    /// Creates a new queue.
+    ///
+    /// This is unsafe as the type system doesn't enforce a single
+    /// consumer-producer relationship. It also allows the consumer to `pop`
+    /// items while there is a `peek` active due to all methods having a
+    /// non-mutable receiver.
+    ///
+    /// # Arguments
+    ///
+    ///   * `bound` - This queue implementation is implemented with a linked
+    ///               list, and this means that a push is always a malloc. In
+    ///               order to amortize this cost, an internal cache of nodes is
+    ///               maintained to prevent a malloc from always being
+    ///               necessary. This bound is the limit on the size of the
+    ///               cache (if desired). If the value is 0, then the cache has
+    ///               no bound. Otherwise, the cache will never grow larger than
+    ///               `bound` (although the queue itself could be much larger.
+    pub unsafe fn new(bound: uint) -> Queue<T> {
+        let n1 = Node::new();
+        let n2 = Node::new();
+        (*n1).next.store(n2, Relaxed);
+        Queue {
+            tail: UnsafeCell::new(n2),
+            tail_prev: AtomicPtr::new(n1),
+            head: UnsafeCell::new(n2),
+            first: UnsafeCell::new(n1),
+            tail_copy: UnsafeCell::new(n1),
+            cache_bound: bound,
+            cache_additions: AtomicUint::new(0),
+            cache_subtractions: AtomicUint::new(0),
+        }
+    }
+
+    /// Pushes a new value onto this queue. Note that to use this function
+    /// safely, it must be externally guaranteed that there is only one pusher.
+    pub fn push(&self, t: T) {
+        unsafe {
+            // Acquire a node (which either uses a cached one or allocates a new
+            // one), and then append this to the 'head' node.
+            let n = self.alloc();
+            assert!((*n).value.is_none());
+            (*n).value = Some(t);
+            (*n).next.store(0 as *mut Node<T>, Relaxed);
+            (**self.head.get()).next.store(n, Release);
+            *self.head.get() = n;
+        }
+    }
+
+    unsafe fn alloc(&self) -> *mut Node<T> {
+        // First try to see if we can consume the 'first' node for our uses.
+        // We try to avoid as many atomic instructions as possible here, so
+        // the addition to cache_subtractions is not atomic (plus we're the
+        // only one subtracting from the cache).
+        if *self.first.get() != *self.tail_copy.get() {
+            if self.cache_bound > 0 {
+                let b = self.cache_subtractions.load(Relaxed);
+                self.cache_subtractions.store(b + 1, Relaxed);
+            }
+            let ret = *self.first.get();
+            *self.first.get() = (*ret).next.load(Relaxed);
+            return ret;
+        }
+        // If the above fails, then update our copy of the tail and try
+        // again.
+        *self.tail_copy.get() = self.tail_prev.load(Acquire);
+        if *self.first.get() != *self.tail_copy.get() {
+            if self.cache_bound > 0 {
+                let b = self.cache_subtractions.load(Relaxed);
+                self.cache_subtractions.store(b + 1, Relaxed);
+            }
+            let ret = *self.first.get();
+            *self.first.get() = (*ret).next.load(Relaxed);
+            return ret;
+        }
+        // If all of that fails, then we have to allocate a new node
+        // (there's nothing in the node cache).
+        Node::new()
+    }
+
+    /// Attempts to pop a value from this queue. Remember that to use this type
+    /// safely you must ensure that there is only one popper at a time.
+    pub fn pop(&self) -> Option<T> {
+        unsafe {
+            // The `tail` node is not actually a used node, but rather a
+            // sentinel from where we should start popping from. Hence, look at
+            // tail's next field and see if we can use it. If we do a pop, then
+            // the current tail node is a candidate for going into the cache.
+            let tail = *self.tail.get();
+            let next = (*tail).next.load(Acquire);
+            if next.is_null() { return None }
+            assert!((*next).value.is_some());
+            let ret = (*next).value.take();
+
+            *self.tail.get() = next;
+            if self.cache_bound == 0 {
+                self.tail_prev.store(tail, Release);
+            } else {
+                // FIXME: this is dubious with overflow.
+                let additions = self.cache_additions.load(Relaxed);
+                let subtractions = self.cache_subtractions.load(Relaxed);
+                let size = additions - subtractions;
+
+                if size < self.cache_bound {
+                    self.tail_prev.store(tail, Release);
+                    self.cache_additions.store(additions + 1, Relaxed);
+                } else {
+                    (*self.tail_prev.load(Relaxed)).next.store(next, Relaxed);
+                    // We have successfully erased all references to 'tail', so
+                    // now we can safely drop it.
+                    let _: Box<Node<T>> = mem::transmute(tail);
+                }
+            }
+            return ret;
+        }
+    }
+
+    /// Attempts to peek at the head of the queue, returning `None` if the queue
+    /// has no data currently
+    ///
+    /// # Warning
+    /// The reference returned is invalid if it is not used before the consumer
+    /// pops the value off the queue. If the producer then pushes another value
+    /// onto the queue, it will overwrite the value pointed to by the reference.
+    pub fn peek<'a>(&'a self) -> Option<&'a mut T> {
+        // This is essentially the same as above with all the popping bits
+        // stripped out.
+        unsafe {
+            let tail = *self.tail.get();
+            let next = (*tail).next.load(Acquire);
+            if next.is_null() { return None }
+            return (*next).value.as_mut();
+        }
+    }
+}
+
+#[unsafe_destructor]
+impl<T: Send> Drop for Queue<T> {
+    fn drop(&mut self) {
+        unsafe {
+            let mut cur = *self.first.get();
+            while !cur.is_null() {
+                let next = (*cur).next.load(Relaxed);
+                let _n: Box<Node<T>> = mem::transmute(cur);
+                cur = next;
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use prelude::*;
+
+    use sync::Arc;
+    use super::Queue;
+
+    #[test]
+    fn smoke() {
+        unsafe {
+            let queue = Queue::new(0);
+            queue.push(1i);
+            queue.push(2);
+            assert_eq!(queue.pop(), Some(1i));
+            assert_eq!(queue.pop(), Some(2));
+            assert_eq!(queue.pop(), None);
+            queue.push(3);
+            queue.push(4);
+            assert_eq!(queue.pop(), Some(3));
+            assert_eq!(queue.pop(), Some(4));
+            assert_eq!(queue.pop(), None);
+        }
+    }
+
+    #[test]
+    fn peek() {
+        unsafe {
+            let queue = Queue::new(0);
+            queue.push(vec![1i]);
+
+            // Ensure the borrowchecker works
+            match queue.peek() {
+                Some(vec) => match vec.as_slice() {
+                    // Note that `pop` is not allowed here due to borrow
+                    [1] => {}
+                    _ => return
+                },
+                None => unreachable!()
+            }
+
+            queue.pop();
+        }
+    }
+
+    #[test]
+    fn drop_full() {
+        unsafe {
+            let q = Queue::new(0);
+            q.push(box 1i);
+            q.push(box 2i);
+        }
+    }
+
+    #[test]
+    fn smoke_bound() {
+        unsafe {
+            let q = Queue::new(0);
+            q.push(1i);
+            q.push(2);
+            assert_eq!(q.pop(), Some(1));
+            assert_eq!(q.pop(), Some(2));
+            assert_eq!(q.pop(), None);
+            q.push(3);
+            q.push(4);
+            assert_eq!(q.pop(), Some(3));
+            assert_eq!(q.pop(), Some(4));
+            assert_eq!(q.pop(), None);
+        }
+    }
+
+    #[test]
+    fn stress() {
+        unsafe {
+            stress_bound(0);
+            stress_bound(1);
+        }
+
+        unsafe fn stress_bound(bound: uint) {
+            let q = Arc::new(Queue::new(bound));
+
+            let (tx, rx) = channel();
+            let q2 = q.clone();
+            spawn(move|| {
+                for _ in range(0u, 100000) {
+                    loop {
+                        match q2.pop() {
+                            Some(1i) => break,
+                            Some(_) => panic!(),
+                            None => {}
+                        }
+                    }
+                }
+                tx.send(());
+            });
+            for _ in range(0i, 100000) {
+                q.push(1);
+            }
+            rx.recv();
+        }
+    }
+}
diff --git a/src/libstd/comm/stream.rs b/src/libstd/comm/stream.rs
new file mode 100644
index 00000000000..b68f626060e
--- /dev/null
+++ b/src/libstd/comm/stream.rs
@@ -0,0 +1,484 @@
+// 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.
+
+/// Stream channels
+///
+/// This is the flavor of channels which are optimized for one sender and one
+/// receiver. The sender will be upgraded to a shared channel if the channel is
+/// cloned.
+///
+/// High level implementation details can be found in the comment of the parent
+/// module.
+
+pub use self::Failure::*;
+pub use self::UpgradeResult::*;
+pub use self::SelectionResult::*;
+use self::Message::*;
+
+use core::prelude::*;
+
+use core::cmp;
+use core::int;
+use thread::Thread;
+
+use sync::atomic;
+use comm::spsc_queue as spsc;
+use comm::Receiver;
+use comm::blocking::{mod, SignalToken};
+
+const DISCONNECTED: int = int::MIN;
+#[cfg(test)]
+const MAX_STEALS: int = 5;
+#[cfg(not(test))]
+const MAX_STEALS: int = 1 << 20;
+
+pub struct Packet<T> {
+    queue: spsc::Queue<Message<T>>, // internal queue for all message
+
+    cnt: atomic::AtomicInt, // How many items are on this channel
+    steals: int, // How many times has a port received without blocking?
+    to_wake: atomic::AtomicUint, // SignalToken for the blocked thread to wake up
+
+    port_dropped: atomic::AtomicBool, // flag if the channel has been destroyed.
+}
+
+pub enum Failure<T> {
+    Empty,
+    Disconnected,
+    Upgraded(Receiver<T>),
+}
+
+pub enum UpgradeResult {
+    UpSuccess,
+    UpDisconnected,
+    UpWoke(SignalToken),
+}
+
+pub enum SelectionResult<T> {
+    SelSuccess,
+    SelCanceled,
+    SelUpgraded(SignalToken, Receiver<T>),
+}
+
+// Any message could contain an "upgrade request" to a new shared port, so the
+// internal queue it's a queue of T, but rather Message<T>
+enum Message<T> {
+    Data(T),
+    GoUp(Receiver<T>),
+}
+
+impl<T: Send> Packet<T> {
+    pub fn new() -> Packet<T> {
+        Packet {
+            queue: unsafe { spsc::Queue::new(128) },
+
+            cnt: atomic::AtomicInt::new(0),
+            steals: 0,
+            to_wake: atomic::AtomicUint::new(0),
+
+            port_dropped: atomic::AtomicBool::new(false),
+        }
+    }
+
+    pub fn send(&mut self, t: T) -> Result<(), T> {
+        // If the other port has deterministically gone away, then definitely
+        // must return the data back up the stack. Otherwise, the data is
+        // considered as being sent.
+        if self.port_dropped.load(atomic::SeqCst) { return Err(t) }
+
+        match self.do_send(Data(t)) {
+            UpSuccess | UpDisconnected => {},
+            UpWoke(token) => { token.signal(); }
+        }
+        Ok(())
+    }
+
+    pub fn upgrade(&mut self, up: Receiver<T>) -> UpgradeResult {
+        // If the port has gone away, then there's no need to proceed any
+        // further.
+        if self.port_dropped.load(atomic::SeqCst) { return UpDisconnected }
+
+        self.do_send(GoUp(up))
+    }
+
+    fn do_send(&mut self, t: Message<T>) -> UpgradeResult {
+        self.queue.push(t);
+        match self.cnt.fetch_add(1, atomic::SeqCst) {
+            // As described in the mod's doc comment, -1 == wakeup
+            -1 => UpWoke(self.take_to_wake()),
+            // As as described before, SPSC queues must be >= -2
+            -2 => UpSuccess,
+
+            // Be sure to preserve the disconnected state, and the return value
+            // in this case is going to be whether our data was received or not.
+            // This manifests itself on whether we have an empty queue or not.
+            //
+            // Primarily, are required to drain the queue here because the port
+            // will never remove this data. We can only have at most one item to
+            // drain (the port drains the rest).
+            DISCONNECTED => {
+                self.cnt.store(DISCONNECTED, atomic::SeqCst);
+                let first = self.queue.pop();
+                let second = self.queue.pop();
+                assert!(second.is_none());
+
+                match first {
+                    Some(..) => UpSuccess,  // we failed to send the data
+                    None => UpDisconnected, // we successfully sent data
+                }
+            }
+
+            // Otherwise we just sent some data on a non-waiting queue, so just
+            // make sure the world is sane and carry on!
+            n => { assert!(n >= 0); UpSuccess }
+        }
+    }
+
+    // Consumes ownership of the 'to_wake' field.
+    fn take_to_wake(&mut self) -> SignalToken {
+        let ptr = self.to_wake.load(atomic::SeqCst);
+        self.to_wake.store(0, atomic::SeqCst);
+        assert!(ptr != 0);
+        unsafe { SignalToken::cast_from_uint(ptr) }
+    }
+
+    // Decrements the count on the channel for a sleeper, returning the sleeper
+    // back if it shouldn't sleep. Note that this is the location where we take
+    // steals into account.
+    fn decrement(&mut self, token: SignalToken) -> Result<(), SignalToken> {
+        assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
+        let ptr = unsafe { token.cast_to_uint() };
+        self.to_wake.store(ptr, atomic::SeqCst);
+
+        let steals = self.steals;
+        self.steals = 0;
+
+        match self.cnt.fetch_sub(1 + steals, atomic::SeqCst) {
+            DISCONNECTED => { self.cnt.store(DISCONNECTED, atomic::SeqCst); }
+            // If we factor in our steals and notice that the channel has no
+            // data, we successfully sleep
+            n => {
+                assert!(n >= 0);
+                if n - steals <= 0 { return Ok(()) }
+            }
+        }
+
+        self.to_wake.store(0, atomic::SeqCst);
+        Err(unsafe { SignalToken::cast_from_uint(ptr) })
+    }
+
+    pub fn recv(&mut self) -> Result<T, Failure<T>> {
+        // Optimistic preflight check (scheduling is expensive).
+        match self.try_recv() {
+            Err(Empty) => {}
+            data => return data,
+        }
+
+        // Welp, our channel has no data. Deschedule the current task and
+        // initiate the blocking protocol.
+        let (wait_token, signal_token) = blocking::tokens();
+        if self.decrement(signal_token).is_ok() {
+            wait_token.wait()
+        }
+
+        match self.try_recv() {
+            // Messages which actually popped from the queue shouldn't count as
+            // a steal, so offset the decrement here (we already have our
+            // "steal" factored into the channel count above).
+            data @ Ok(..) |
+            data @ Err(Upgraded(..)) => {
+                self.steals -= 1;
+                data
+            }
+
+            data => data,
+        }
+    }
+
+    pub fn try_recv(&mut self) -> Result<T, Failure<T>> {
+        match self.queue.pop() {
+            // If we stole some data, record to that effect (this will be
+            // factored into cnt later on).
+            //
+            // Note that we don't allow steals to grow without bound in order to
+            // prevent eventual overflow of either steals or cnt as an overflow
+            // would have catastrophic results. Sometimes, steals > cnt, but
+            // other times cnt > steals, so we don't know the relation between
+            // steals and cnt. This code path is executed only rarely, so we do
+            // a pretty slow operation, of swapping 0 into cnt, taking steals
+            // down as much as possible (without going negative), and then
+            // adding back in whatever we couldn't factor into steals.
+            Some(data) => {
+                if self.steals > MAX_STEALS {
+                    match self.cnt.swap(0, atomic::SeqCst) {
+                        DISCONNECTED => {
+                            self.cnt.store(DISCONNECTED, atomic::SeqCst);
+                        }
+                        n => {
+                            let m = cmp::min(n, self.steals);
+                            self.steals -= m;
+                            self.bump(n - m);
+                        }
+                    }
+                    assert!(self.steals >= 0);
+                }
+                self.steals += 1;
+                match data {
+                    Data(t) => Ok(t),
+                    GoUp(up) => Err(Upgraded(up)),
+                }
+            }
+
+            None => {
+                match self.cnt.load(atomic::SeqCst) {
+                    n if n != DISCONNECTED => Err(Empty),
+
+                    // This is a little bit of a tricky case. We failed to pop
+                    // data above, and then we have viewed that the channel is
+                    // disconnected. In this window more data could have been
+                    // sent on the channel. It doesn't really make sense to
+                    // return that the channel is disconnected when there's
+                    // actually data on it, so be extra sure there's no data by
+                    // popping one more time.
+                    //
+                    // We can ignore steals because the other end is
+                    // disconnected and we'll never need to really factor in our
+                    // steals again.
+                    _ => {
+                        match self.queue.pop() {
+                            Some(Data(t)) => Ok(t),
+                            Some(GoUp(up)) => Err(Upgraded(up)),
+                            None => Err(Disconnected),
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    pub fn drop_chan(&mut self) {
+        // Dropping a channel is pretty simple, we just flag it as disconnected
+        // and then wakeup a blocker if there is one.
+        match self.cnt.swap(DISCONNECTED, atomic::SeqCst) {
+            -1 => { self.take_to_wake().signal(); }
+            DISCONNECTED => {}
+            n => { assert!(n >= 0); }
+        }
+    }
+
+    pub fn drop_port(&mut self) {
+        // Dropping a port seems like a fairly trivial thing. In theory all we
+        // need to do is flag that we're disconnected and then everything else
+        // can take over (we don't have anyone to wake up).
+        //
+        // The catch for Ports is that we want to drop the entire contents of
+        // the queue. There are multiple reasons for having this property, the
+        // largest of which is that if another chan is waiting in this channel
+        // (but not received yet), then waiting on that port will cause a
+        // deadlock.
+        //
+        // So if we accept that we must now destroy the entire contents of the
+        // queue, this code may make a bit more sense. The tricky part is that
+        // we can't let any in-flight sends go un-dropped, we have to make sure
+        // *everything* is dropped and nothing new will come onto the channel.
+
+        // The first thing we do is set a flag saying that we're done for. All
+        // sends are gated on this flag, so we're immediately guaranteed that
+        // there are a bounded number of active sends that we'll have to deal
+        // with.
+        self.port_dropped.store(true, atomic::SeqCst);
+
+        // Now that we're guaranteed to deal with a bounded number of senders,
+        // we need to drain the queue. This draining process happens atomically
+        // with respect to the "count" of the channel. If the count is nonzero
+        // (with steals taken into account), then there must be data on the
+        // channel. In this case we drain everything and then try again. We will
+        // continue to fail while active senders send data while we're dropping
+        // data, but eventually we're guaranteed to break out of this loop
+        // (because there is a bounded number of senders).
+        let mut steals = self.steals;
+        while {
+            let cnt = self.cnt.compare_and_swap(
+                            steals, DISCONNECTED, atomic::SeqCst);
+            cnt != DISCONNECTED && cnt != steals
+        } {
+            loop {
+                match self.queue.pop() {
+                    Some(..) => { steals += 1; }
+                    None => break
+                }
+            }
+        }
+
+        // At this point in time, we have gated all future senders from sending,
+        // and we have flagged the channel as being disconnected. The senders
+        // still have some responsibility, however, because some sends may not
+        // complete until after we flag the disconnection. There are more
+        // details in the sending methods that see DISCONNECTED
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // select implementation
+    ////////////////////////////////////////////////////////////////////////////
+
+    // Tests to see whether this port can receive without blocking. If Ok is
+    // returned, then that's the answer. If Err is returned, then the returned
+    // port needs to be queried instead (an upgrade happened)
+    pub fn can_recv(&mut self) -> Result<bool, Receiver<T>> {
+        // We peek at the queue to see if there's anything on it, and we use
+        // this return value to determine if we should pop from the queue and
+        // upgrade this channel immediately. If it looks like we've got an
+        // upgrade pending, then go through the whole recv rigamarole to update
+        // the internal state.
+        match self.queue.peek() {
+            Some(&GoUp(..)) => {
+                match self.recv() {
+                    Err(Upgraded(port)) => Err(port),
+                    _ => unreachable!(),
+                }
+            }
+            Some(..) => Ok(true),
+            None => Ok(false)
+        }
+    }
+
+    // increment the count on the channel (used for selection)
+    fn bump(&mut self, amt: int) -> int {
+        match self.cnt.fetch_add(amt, atomic::SeqCst) {
+            DISCONNECTED => {
+                self.cnt.store(DISCONNECTED, atomic::SeqCst);
+                DISCONNECTED
+            }
+            n => n
+        }
+    }
+
+    // Attempts to start selecting on this port. Like a oneshot, this can fail
+    // immediately because of an upgrade.
+    pub fn start_selection(&mut self, token: SignalToken) -> SelectionResult<T> {
+        match self.decrement(token) {
+            Ok(()) => SelSuccess,
+            Err(token) => {
+                let ret = match self.queue.peek() {
+                    Some(&GoUp(..)) => {
+                        match self.queue.pop() {
+                            Some(GoUp(port)) => SelUpgraded(token, port),
+                            _ => unreachable!(),
+                        }
+                    }
+                    Some(..) => SelCanceled,
+                    None => SelCanceled,
+                };
+                // Undo our decrement above, and we should be guaranteed that the
+                // previous value is positive because we're not going to sleep
+                let prev = self.bump(1);
+                assert!(prev == DISCONNECTED || prev >= 0);
+                return ret;
+            }
+        }
+    }
+
+    // Removes a previous task from being blocked in this port
+    pub fn abort_selection(&mut self,
+                           was_upgrade: bool) -> Result<bool, Receiver<T>> {
+        // If we're aborting selection after upgrading from a oneshot, then
+        // we're guarantee that no one is waiting. The only way that we could
+        // have seen the upgrade is if data was actually sent on the channel
+        // half again. For us, this means that there is guaranteed to be data on
+        // this channel. Furthermore, we're guaranteed that there was no
+        // start_selection previously, so there's no need to modify `self.cnt`
+        // at all.
+        //
+        // Hence, because of these invariants, we immediately return `Ok(true)`.
+        // Note that the data may not actually be sent on the channel just yet.
+        // The other end could have flagged the upgrade but not sent data to
+        // this end. This is fine because we know it's a small bounded windows
+        // of time until the data is actually sent.
+        if was_upgrade {
+            assert_eq!(self.steals, 0);
+            assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
+            return Ok(true)
+        }
+
+        // We want to make sure that the count on the channel goes non-negative,
+        // and in the stream case we can have at most one steal, so just assume
+        // that we had one steal.
+        let steals = 1;
+        let prev = self.bump(steals + 1);
+
+        // If we were previously disconnected, then we know for sure that there
+        // is no task in to_wake, so just keep going
+        let has_data = if prev == DISCONNECTED {
+            assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
+            true // there is data, that data is that we're disconnected
+        } else {
+            let cur = prev + steals + 1;
+            assert!(cur >= 0);
+
+            // If the previous count was negative, then we just made things go
+            // positive, hence we passed the -1 boundary and we're responsible
+            // for removing the to_wake() field and trashing it.
+            //
+            // If the previous count was positive then we're in a tougher
+            // situation. A possible race is that a sender just incremented
+            // through -1 (meaning it's going to try to wake a task up), but it
+            // hasn't yet read the to_wake. In order to prevent a future recv()
+            // from waking up too early (this sender picking up the plastered
+            // over to_wake), we spin loop here waiting for to_wake to be 0.
+            // Note that this entire select() implementation needs an overhaul,
+            // and this is *not* the worst part of it, so this is not done as a
+            // final solution but rather out of necessity for now to get
+            // something working.
+            if prev < 0 {
+                drop(self.take_to_wake());
+            } else {
+                while self.to_wake.load(atomic::SeqCst) != 0 {
+                    Thread::yield_now();
+                }
+            }
+            assert_eq!(self.steals, 0);
+            self.steals = steals;
+
+            // if we were previously positive, then there's surely data to
+            // receive
+            prev >= 0
+        };
+
+        // Now that we've determined that this queue "has data", we peek at the
+        // queue to see if the data is an upgrade or not. If it's an upgrade,
+        // then we need to destroy this port and abort selection on the
+        // upgraded port.
+        if has_data {
+            match self.queue.peek() {
+                Some(&GoUp(..)) => {
+                    match self.queue.pop() {
+                        Some(GoUp(port)) => Err(port),
+                        _ => unreachable!(),
+                    }
+                }
+                _ => Ok(true),
+            }
+        } else {
+            Ok(false)
+        }
+    }
+}
+
+#[unsafe_destructor]
+impl<T: Send> Drop for Packet<T> {
+    fn drop(&mut self) {
+        // Note that this load is not only an assert for correctness about
+        // disconnection, but also a proper fence before the read of
+        // `to_wake`, so this assert cannot be removed with also removing
+        // the `to_wake` assert.
+        assert_eq!(self.cnt.load(atomic::SeqCst), DISCONNECTED);
+        assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
+    }
+}
diff --git a/src/libstd/comm/sync.rs b/src/libstd/comm/sync.rs
new file mode 100644
index 00000000000..f75186e70e3
--- /dev/null
+++ b/src/libstd/comm/sync.rs
@@ -0,0 +1,475 @@
+// 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.
+
+/// Synchronous channels/ports
+///
+/// This channel implementation differs significantly from the asynchronous
+/// implementations found next to it (oneshot/stream/share). This is an
+/// implementation of a synchronous, bounded buffer channel.
+///
+/// Each channel is created with some amount of backing buffer, and sends will
+/// *block* until buffer space becomes available. A buffer size of 0 is valid,
+/// which means that every successful send is paired with a successful recv.
+///
+/// This flavor of channels defines a new `send_opt` method for channels which
+/// is the method by which a message is sent but the task does not panic if it
+/// cannot be delivered.
+///
+/// Another major difference is that send() will *always* return back the data
+/// if it couldn't be sent. This is because it is deterministically known when
+/// the data is received and when it is not received.
+///
+/// Implementation-wise, it can all be summed up with "use a mutex plus some
+/// logic". The mutex used here is an OS native mutex, meaning that no user code
+/// is run inside of the mutex (to prevent context switching). This
+/// implementation shares almost all code for the buffered and unbuffered cases
+/// of a synchronous channel. There are a few branches for the unbuffered case,
+/// but they're mostly just relevant to blocking senders.
+
+use core::prelude::*;
+
+pub use self::Failure::*;
+use self::Blocker::*;
+
+use vec::Vec;
+use core::mem;
+
+use sync::{atomic, Mutex, MutexGuard};
+use comm::blocking::{mod, WaitToken, SignalToken};
+use comm::select::StartResult::{mod, Installed, Abort};
+
+pub struct Packet<T> {
+    /// Only field outside of the mutex. Just done for kicks, but mainly because
+    /// the other shared channel already had the code implemented
+    channels: atomic::AtomicUint,
+
+    lock: Mutex<State<T>>,
+}
+
+struct State<T> {
+    disconnected: bool, // Is the channel disconnected yet?
+    queue: Queue,       // queue of senders waiting to send data
+    blocker: Blocker,   // currently blocked task on this channel
+    buf: Buffer<T>,     // storage for buffered messages
+    cap: uint,          // capacity of this channel
+
+    /// A curious flag used to indicate whether a sender failed or succeeded in
+    /// blocking. This is used to transmit information back to the task that it
+    /// must dequeue its message from the buffer because it was not received.
+    /// This is only relevant in the 0-buffer case. This obviously cannot be
+    /// safely constructed, but it's guaranteed to always have a valid pointer
+    /// value.
+    canceled: Option<&'static mut bool>,
+}
+
+/// Possible flavors of threads who can be blocked on this channel.
+enum Blocker {
+    BlockedSender(SignalToken),
+    BlockedReceiver(SignalToken),
+    NoneBlocked
+}
+
+/// Simple queue for threading tasks together. Nodes are stack-allocated, so
+/// this structure is not safe at all
+struct Queue {
+    head: *mut Node,
+    tail: *mut Node,
+}
+
+struct Node {
+    token: Option<SignalToken>,
+    next: *mut Node,
+}
+
+/// A simple ring-buffer
+struct Buffer<T> {
+    buf: Vec<Option<T>>,
+    start: uint,
+    size: uint,
+}
+
+#[deriving(Show)]
+pub enum Failure {
+    Empty,
+    Disconnected,
+}
+
+/// Atomically blocks the current thread, placing it into `slot`, unlocking `lock`
+/// in the meantime. This re-locks the mutex upon returning.
+fn wait<'a, 'b, T: Send>(lock: &'a Mutex<State<T>>,
+                         mut guard: MutexGuard<'b, State<T>>,
+                         f: fn(SignalToken) -> Blocker)
+                         -> MutexGuard<'a, State<T>>
+{
+    let (wait_token, signal_token) = blocking::tokens();
+    match mem::replace(&mut guard.blocker, f(signal_token)) {
+        NoneBlocked => {}
+        _ => unreachable!(),
+    }
+    drop(guard);        // unlock
+    wait_token.wait();  // block
+    lock.lock()         // relock
+}
+
+/// Wakes up a thread, dropping the lock at the correct time
+fn wakeup<T>(token: SignalToken, guard: MutexGuard<State<T>>) {
+    // We need to be careful to wake up the waiting task *outside* of the mutex
+    // in case it incurs a context switch.
+    drop(guard);
+    token.signal();
+}
+
+impl<T: Send> Packet<T> {
+    pub fn new(cap: uint) -> Packet<T> {
+        Packet {
+            channels: atomic::AtomicUint::new(1),
+            lock: Mutex::new(State {
+                disconnected: false,
+                blocker: NoneBlocked,
+                cap: cap,
+                canceled: None,
+                queue: Queue {
+                    head: 0 as *mut Node,
+                    tail: 0 as *mut Node,
+                },
+                buf: Buffer {
+                    buf: Vec::from_fn(cap + if cap == 0 {1} else {0}, |_| None),
+                    start: 0,
+                    size: 0,
+                },
+            }),
+        }
+    }
+
+    // wait until a send slot is available, returning locked access to
+    // the channel state.
+    fn acquire_send_slot(&self) -> MutexGuard<State<T>> {
+        let mut node = Node { token: None, next: 0 as *mut Node };
+        loop {
+            let mut guard = self.lock.lock();
+            // are we ready to go?
+            if guard.disconnected || guard.buf.size() < guard.buf.cap() {
+                return guard;
+            }
+            // no room; actually block
+            let wait_token = guard.queue.enqueue(&mut node);
+            drop(guard);
+            wait_token.wait();
+        }
+    }
+
+    pub fn send(&self, t: T) -> Result<(), T> {
+        let mut guard = self.acquire_send_slot();
+        if guard.disconnected { return Err(t) }
+        guard.buf.enqueue(t);
+
+        match mem::replace(&mut guard.blocker, NoneBlocked) {
+            // if our capacity is 0, then we need to wait for a receiver to be
+            // available to take our data. After waiting, we check again to make
+            // sure the port didn't go away in the meantime. If it did, we need
+            // to hand back our data.
+            NoneBlocked if guard.cap == 0 => {
+                let mut canceled = false;
+                assert!(guard.canceled.is_none());
+                guard.canceled = Some(unsafe { mem::transmute(&mut canceled) });
+                let mut guard = wait(&self.lock, guard, BlockedSender);
+                if canceled {Err(guard.buf.dequeue())} else {Ok(())}
+            }
+
+            // success, we buffered some data
+            NoneBlocked => Ok(()),
+
+            // success, someone's about to receive our buffered data.
+            BlockedReceiver(token) => { wakeup(token, guard); Ok(()) }
+
+            BlockedSender(..) => panic!("lolwut"),
+        }
+    }
+
+    pub fn try_send(&self, t: T) -> Result<(), super::TrySendError<T>> {
+        let mut guard = self.lock.lock();
+        if guard.disconnected {
+            Err(super::RecvDisconnected(t))
+        } else if guard.buf.size() == guard.buf.cap() {
+            Err(super::Full(t))
+        } else if guard.cap == 0 {
+            // With capacity 0, even though we have buffer space we can't
+            // transfer the data unless there's a receiver waiting.
+            match mem::replace(&mut guard.blocker, NoneBlocked) {
+                NoneBlocked => Err(super::Full(t)),
+                BlockedSender(..) => unreachable!(),
+                BlockedReceiver(token) => {
+                    guard.buf.enqueue(t);
+                    wakeup(token, guard);
+                    Ok(())
+                }
+            }
+        } else {
+            // If the buffer has some space and the capacity isn't 0, then we
+            // just enqueue the data for later retrieval, ensuring to wake up
+            // any blocked receiver if there is one.
+            assert!(guard.buf.size() < guard.buf.cap());
+            guard.buf.enqueue(t);
+            match mem::replace(&mut guard.blocker, NoneBlocked) {
+                BlockedReceiver(token) => wakeup(token, guard),
+                NoneBlocked => {}
+                BlockedSender(..) => unreachable!(),
+            }
+            Ok(())
+        }
+    }
+
+    // Receives a message from this channel
+    //
+    // When reading this, remember that there can only ever be one receiver at
+    // time.
+    pub fn recv(&self) -> Result<T, ()> {
+        let mut guard = self.lock.lock();
+
+        // Wait for the buffer to have something in it. No need for a while loop
+        // because we're the only receiver.
+        let mut waited = false;
+        if !guard.disconnected && guard.buf.size() == 0 {
+            guard = wait(&self.lock, guard, BlockedReceiver);
+            waited = true;
+        }
+        if guard.disconnected && guard.buf.size() == 0 { return Err(()) }
+
+        // Pick up the data, wake up our neighbors, and carry on
+        assert!(guard.buf.size() > 0);
+        let ret = guard.buf.dequeue();
+        self.wakeup_senders(waited, guard);
+        return Ok(ret);
+    }
+
+    pub fn try_recv(&self) -> Result<T, Failure> {
+        let mut guard = self.lock.lock();
+
+        // Easy cases first
+        if guard.disconnected { return Err(Disconnected) }
+        if guard.buf.size() == 0 { return Err(Empty) }
+
+        // Be sure to wake up neighbors
+        let ret = Ok(guard.buf.dequeue());
+        self.wakeup_senders(false, guard);
+
+        return ret;
+    }
+
+    // Wake up pending senders after some data has been received
+    //
+    // * `waited` - flag if the receiver blocked to receive some data, or if it
+    //              just picked up some data on the way out
+    // * `guard` - the lock guard that is held over this channel's lock
+    fn wakeup_senders(&self, waited: bool, mut guard: MutexGuard<State<T>>) {
+        let pending_sender1: Option<SignalToken> = guard.queue.dequeue();
+
+        // If this is a no-buffer channel (cap == 0), then if we didn't wait we
+        // need to ACK the sender. If we waited, then the sender waking us up
+        // was already the ACK.
+        let pending_sender2 = if guard.cap == 0 && !waited {
+            match mem::replace(&mut guard.blocker, NoneBlocked) {
+                NoneBlocked => None,
+                BlockedReceiver(..) => unreachable!(),
+                BlockedSender(token) => {
+                    guard.canceled.take();
+                    Some(token)
+                }
+            }
+        } else {
+            None
+        };
+        mem::drop(guard);
+
+        // only outside of the lock do we wake up the pending tasks
+        pending_sender1.map(|t| t.signal());
+        pending_sender2.map(|t| t.signal());
+    }
+
+    // Prepares this shared packet for a channel clone, essentially just bumping
+    // a refcount.
+    pub fn clone_chan(&self) {
+        self.channels.fetch_add(1, atomic::SeqCst);
+    }
+
+    pub fn drop_chan(&self) {
+        // Only flag the channel as disconnected if we're the last channel
+        match self.channels.fetch_sub(1, atomic::SeqCst) {
+            1 => {}
+            _ => return
+        }
+
+        // Not much to do other than wake up a receiver if one's there
+        let mut guard = self.lock.lock();
+        if guard.disconnected { return }
+        guard.disconnected = true;
+        match mem::replace(&mut guard.blocker, NoneBlocked) {
+            NoneBlocked => {}
+            BlockedSender(..) => unreachable!(),
+            BlockedReceiver(token) => wakeup(token, guard),
+        }
+    }
+
+    pub fn drop_port(&self) {
+        let mut guard = self.lock.lock();
+
+        if guard.disconnected { return }
+        guard.disconnected = true;
+
+        // If the capacity is 0, then the sender may want its data back after
+        // we're disconnected. Otherwise it's now our responsibility to destroy
+        // the buffered data. As with many other portions of this code, this
+        // needs to be careful to destroy the data *outside* of the lock to
+        // prevent deadlock.
+        let _data = if guard.cap != 0 {
+            mem::replace(&mut guard.buf.buf, Vec::new())
+        } else {
+            Vec::new()
+        };
+        let mut queue = mem::replace(&mut guard.queue, Queue {
+            head: 0 as *mut Node,
+            tail: 0 as *mut Node,
+        });
+
+        let waiter = match mem::replace(&mut guard.blocker, NoneBlocked) {
+            NoneBlocked => None,
+            BlockedSender(token) => {
+                *guard.canceled.take().unwrap() = true;
+                Some(token)
+            }
+            BlockedReceiver(..) => unreachable!(),
+        };
+        mem::drop(guard);
+
+        loop {
+            match queue.dequeue() {
+                Some(token) => { token.signal(); }
+                None => break,
+            }
+        }
+        waiter.map(|t| t.signal());
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // select implementation
+    ////////////////////////////////////////////////////////////////////////////
+
+    // If Ok, the value is whether this port has data, if Err, then the upgraded
+    // port needs to be checked instead of this one.
+    pub fn can_recv(&self) -> bool {
+        let guard = self.lock.lock();
+        guard.disconnected || guard.buf.size() > 0
+    }
+
+    // Attempts to start selection on this port. This can either succeed or fail
+    // because there is data waiting.
+    pub fn start_selection(&self, token: SignalToken) -> StartResult {
+        let mut guard = self.lock.lock();
+        if guard.disconnected || guard.buf.size() > 0 {
+            Abort
+        } else {
+            match mem::replace(&mut guard.blocker, BlockedReceiver(token)) {
+                NoneBlocked => {}
+                BlockedSender(..) => unreachable!(),
+                BlockedReceiver(..) => unreachable!(),
+            }
+            Installed
+        }
+    }
+
+    // Remove a previous selecting task from this port. This ensures that the
+    // blocked task will no longer be visible to any other threads.
+    //
+    // The return value indicates whether there's data on this port.
+    pub fn abort_selection(&self) -> bool {
+        let mut guard = self.lock.lock();
+        match mem::replace(&mut guard.blocker, NoneBlocked) {
+            NoneBlocked => true,
+            BlockedSender(token) => {
+                guard.blocker = BlockedSender(token);
+                true
+            }
+            BlockedReceiver(token) => { drop(token); false }
+        }
+    }
+}
+
+#[unsafe_destructor]
+impl<T: Send> Drop for Packet<T> {
+    fn drop(&mut self) {
+        assert_eq!(self.channels.load(atomic::SeqCst), 0);
+        let mut guard = self.lock.lock();
+        assert!(guard.queue.dequeue().is_none());
+        assert!(guard.canceled.is_none());
+    }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Buffer, a simple ring buffer backed by Vec<T>
+////////////////////////////////////////////////////////////////////////////////
+
+impl<T> Buffer<T> {
+    fn enqueue(&mut self, t: T) {
+        let pos = (self.start + self.size) % self.buf.len();
+        self.size += 1;
+        let prev = mem::replace(&mut self.buf[pos], Some(t));
+        assert!(prev.is_none());
+    }
+
+    fn dequeue(&mut self) -> T {
+        let start = self.start;
+        self.size -= 1;
+        self.start = (self.start + 1) % self.buf.len();
+        self.buf[start].take().unwrap()
+    }
+
+    fn size(&self) -> uint { self.size }
+    fn cap(&self) -> uint { self.buf.len() }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Queue, a simple queue to enqueue tasks with (stack-allocated nodes)
+////////////////////////////////////////////////////////////////////////////////
+
+impl Queue {
+    fn enqueue(&mut self, node: &mut Node) -> WaitToken {
+        let (wait_token, signal_token) = blocking::tokens();
+        node.token = Some(signal_token);
+        node.next = 0 as *mut Node;
+
+        if self.tail.is_null() {
+            self.head = node as *mut Node;
+            self.tail = node as *mut Node;
+        } else {
+            unsafe {
+                (*self.tail).next = node as *mut Node;
+                self.tail = node as *mut Node;
+            }
+        }
+
+        wait_token
+    }
+
+    fn dequeue(&mut self) -> Option<SignalToken> {
+        if self.head.is_null() {
+            return None
+        }
+        let node = self.head;
+        self.head = unsafe { (*node).next };
+        if self.head.is_null() {
+            self.tail = 0 as *mut Node;
+        }
+        unsafe {
+            (*node).next = 0 as *mut Node;
+            Some((*node).token.take().unwrap())
+        }
+    }
+}
diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs
index 0f119d44485..368abe7cb12 100644
--- a/src/libstd/dynamic_lib.rs
+++ b/src/libstd/dynamic_lib.rs
@@ -8,32 +8,22 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/*!
-
-Dynamic library facilities.
-
-A simple wrapper over the platform's dynamic library facilities
-
-*/
+//! Dynamic library facilities.
+//!
+//! A simple wrapper over the platform's dynamic library facilities
 
 #![experimental]
 #![allow(missing_docs)]
 
-use clone::Clone;
-use c_str::ToCStr;
-use iter::Iterator;
+use prelude::*;
 use mem;
-use ops::*;
-use option::*;
 use os;
-use path::{Path,GenericPath};
-use result::*;
-use slice::{AsSlice,SlicePrelude};
 use str;
-use string::String;
-use vec::Vec;
 
-pub struct DynamicLibrary { handle: *mut u8 }
+#[allow(missing_copy_implementations)]
+pub struct DynamicLibrary {
+    handle: *mut u8
+}
 
 impl Drop for DynamicLibrary {
     fn drop(&mut self) {
@@ -210,13 +200,12 @@ mod test {
           target_os = "freebsd",
           target_os = "dragonfly"))]
 pub mod dl {
-    pub use self::Rtld::*;
+    use self::Rtld::*;
 
-    use c_str::{CString, ToCStr};
+    use prelude::*;
+    use c_str::CString;
     use libc;
     use ptr;
-    use result::*;
-    use string::String;
 
     pub unsafe fn open_external<T: ToCStr>(filename: T) -> *mut u8 {
         filename.with_c_str(|raw_name| {
@@ -228,9 +217,11 @@ pub mod dl {
         dlopen(ptr::null(), Lazy as libc::c_int) as *mut u8
     }
 
-    pub fn check_for_errors_in<T>(f: || -> T) -> Result<T, String> {
-        use rustrt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
-        static LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
+    pub fn check_for_errors_in<T, F>(f: F) -> Result<T, String> where
+        F: FnOnce() -> T,
+    {
+        use sync::{StaticMutex, MUTEX_INIT};
+        static LOCK: StaticMutex = MUTEX_INIT;
         unsafe {
             // dlerror isn't thread safe, so we need to lock around this entire
             // sequence
@@ -259,6 +250,7 @@ pub mod dl {
         dlclose(handle as *mut libc::c_void); ()
     }
 
+    #[deriving(Copy)]
     pub enum Rtld {
         Lazy = 1,
         Now = 2,
@@ -280,13 +272,15 @@ pub mod dl {
 #[cfg(target_os = "windows")]
 pub mod dl {
     use c_str::ToCStr;
-    use iter::Iterator;
+    use iter::IteratorExt;
     use libc;
+    use ops::FnOnce;
     use os;
     use ptr;
-    use result::{Ok, Err, Result};
-    use slice::SlicePrelude;
-    use str::StrPrelude;
+    use result::Result;
+    use result::Result::{Ok, Err};
+    use slice::SliceExt;
+    use str::StrExt;
     use str;
     use string::String;
     use vec::Vec;
@@ -306,7 +300,9 @@ pub mod dl {
         handle as *mut u8
     }
 
-    pub fn check_for_errors_in<T>(f: || -> T) -> Result<T, String> {
+    pub fn check_for_errors_in<T, F>(f: F) -> Result<T, String> where
+        F: FnOnce() -> T,
+    {
         unsafe {
             SetLastError(0);
 
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 82ad893f88a..cd7d9aacc90 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -78,9 +78,9 @@
 //! }
 //! ```
 
-use option::{Option, None};
-use kinds::Send;
-use string::String;
+use prelude::*;
+
+use str::Utf8Error;
 
 /// Base functionality for all errors in Rust.
 pub trait Error: Send {
@@ -106,3 +106,14 @@ impl<E> FromError<E> for E {
         err
     }
 }
+
+impl Error for Utf8Error {
+    fn description(&self) -> &str {
+        match *self {
+            Utf8Error::TooShort => "invalid utf-8: not enough bytes",
+            Utf8Error::InvalidByte(..) => "invalid utf-8: corrupt contents",
+        }
+    }
+
+    fn detail(&self) -> Option<String> { Some(self.to_string()) }
+}
diff --git a/src/libstd/failure.rs b/src/libstd/failure.rs
index c23e043c174..7010eae6dba 100644
--- a/src/libstd/failure.rs
+++ b/src/libstd/failure.rs
@@ -10,22 +10,22 @@
 
 #![experimental]
 
-use alloc::boxed::Box;
+use prelude::*;
+
 use any::{Any, AnyRefExt};
+use cell::RefCell;
 use fmt;
-use io::{Writer, IoResult};
-use kinds::Send;
-use option::{Some, None};
-use result::Ok;
-use rt::backtrace;
-use rustrt::{Stderr, Stdio};
-use rustrt::local::Local;
-use rustrt::task::Task;
-use str::Str;
-use string::String;
+use io::IoResult;
+use rt::{backtrace, unwind};
+use rt::util::{Stderr, Stdio};
+use thread::Thread;
 
 // Defined in this module instead of io::stdio so that the unwinding
-local_data_key!(pub local_stderr: Box<Writer + Send>)
+thread_local! {
+    pub static LOCAL_STDERR: RefCell<Option<Box<Writer + Send>>> = {
+        RefCell::new(None)
+    }
+}
 
 impl Writer for Stdio {
     fn write(&mut self, bytes: &[u8]) -> IoResult<()> {
@@ -37,68 +37,44 @@ impl Writer for Stdio {
     }
 }
 
-pub fn on_fail(obj: &Any + Send, file: &'static str, line: uint) {
+pub fn on_fail(obj: &(Any+Send), file: &'static str, line: uint) {
     let msg = match obj.downcast_ref::<&'static str>() {
         Some(s) => *s,
         None => match obj.downcast_ref::<String>() {
-            Some(s) => s.as_slice(),
+            Some(s) => s[],
             None => "Box<Any>",
         }
     };
     let mut err = Stderr;
-
-    // It is assumed that all reasonable rust code will have a local task at
-    // all times. This means that this `exists` will return true almost all of
-    // the time. There are border cases, however, when the runtime has
-    // *almost* set up the local task, but hasn't quite gotten there yet. In
-    // order to get some better diagnostics, we print on panic and
-    // immediately abort the whole process if there is no local task
-    // available.
-    if !Local::exists(None::<Task>) {
-        let _ = writeln!(&mut err, "panicked at '{}', {}:{}", msg, file, line);
-        if backtrace::log_enabled() {
-            let _ = backtrace::write(&mut err);
-        } else {
-            let _ = writeln!(&mut err, "run with `RUST_BACKTRACE=1` to \
-                                        see a backtrace");
-        }
-        return
-    }
-
-    // Peel the name out of local task so we can print it. We've got to be sure
-    // that the local task is in TLS while we're printing as I/O may occur.
-    let (name, unwinding) = {
-        let mut t = Local::borrow(None::<Task>);
-        (t.name.take(), t.unwinder.unwinding())
-    };
-    {
-        let n = name.as_ref().map(|n| n.as_slice()).unwrap_or("<unnamed>");
-
-        match local_stderr.replace(None) {
-            Some(mut stderr) => {
-                // FIXME: what to do when the task printing panics?
-                let _ = writeln!(stderr,
-                                 "task '{}' panicked at '{}', {}:{}\n",
-                                 n, msg, file, line);
-                if backtrace::log_enabled() {
-                    let _ = backtrace::write(&mut *stderr);
-                }
-                local_stderr.replace(Some(stderr));
+    let thread = Thread::current();
+    let name = thread.name().unwrap_or("<unnamed>");
+    let prev = LOCAL_STDERR.with(|s| s.borrow_mut().take());
+    match prev {
+        Some(mut stderr) => {
+            // FIXME: what to do when the thread printing panics?
+            let _ = writeln!(stderr,
+                             "thread '{}' panicked at '{}', {}:{}\n",
+                             name, msg, file, line);
+            if backtrace::log_enabled() {
+                let _ = backtrace::write(&mut *stderr);
             }
-            None => {
-                let _ = writeln!(&mut err, "task '{}' panicked at '{}', {}:{}",
-                                 n, msg, file, line);
-                if backtrace::log_enabled() {
-                    let _ = backtrace::write(&mut err);
-                }
+            let mut s = Some(stderr);
+            LOCAL_STDERR.with(|slot| {
+                *slot.borrow_mut() = s.take();
+            });
+        }
+        None => {
+            let _ = writeln!(&mut err, "thread '{}' panicked at '{}', {}:{}",
+                             name, msg, file, line);
+            if backtrace::log_enabled() {
+                let _ = backtrace::write(&mut err);
             }
         }
+    }
 
-        // If this is a double panic, make sure that we printed a backtrace
-        // for this panic.
-        if unwinding && !backtrace::log_enabled() {
-            let _ = backtrace::write(&mut err);
-        }
+    // If this is a double panic, make sure that we printed a backtrace
+    // for this panic.
+    if unwind::panicking() && !backtrace::log_enabled() {
+        let _ = backtrace::write(&mut err);
     }
-    Local::borrow(None::<Task>).name = name;
 }
diff --git a/src/libstd/fmt.rs b/src/libstd/fmt.rs
index 2482fe63028..d0c9df9d914 100644
--- a/src/libstd/fmt.rs
+++ b/src/libstd/fmt.rs
@@ -10,403 +10,403 @@
 //
 // ignore-lexer-test FIXME #15679
 
-/*!
-
-Utilities for formatting and printing strings
-
-This module contains the runtime support for the `format!` syntax extension.
-This macro is implemented in the compiler to emit calls to this module in order
-to format arguments at runtime into strings and streams.
-
-The functions contained in this module should not normally be used in everyday
-use cases of `format!`. The assumptions made by these functions are unsafe for
-all inputs, and the compiler performs a large amount of validation on the
-arguments to `format!` in order to ensure safety at runtime. While it is
-possible to call these functions directly, it is not recommended to do so in the
-general case.
-
-## Usage
-
-The `format!` macro is intended to be familiar to those coming from C's
-printf/fprintf functions or Python's `str.format` function. In its current
-revision, the `format!` macro returns a `String` type which is the result of
-the formatting. In the future it will also be able to pass in a stream to
-format arguments directly while performing minimal allocations.
-
-Some examples of the `format!` extension are:
-
-```rust
-# fn main() {
-format!("Hello");                  // => "Hello"
-format!("Hello, {}!", "world");    // => "Hello, world!"
-format!("The number is {}", 1i);   // => "The number is 1"
-format!("{}", (3i, 4i));           // => "(3, 4)"
-format!("{value}", value=4i);      // => "4"
-format!("{} {}", 1i, 2u);          // => "1 2"
-# }
-```
-
-From these, you can see that the first argument is a format string. It is
-required by the compiler for this to be a string literal; it cannot be a
-variable passed in (in order to perform validity checking). The compiler will
-then parse the format string and determine if the list of arguments provided is
-suitable to pass to this format string.
-
-### Positional parameters
-
-Each formatting argument is allowed to specify which value argument it's
-referencing, and if omitted it is assumed to be "the next argument". For
-example, the format string `{} {} {}` would take three parameters, and they
-would be formatted in the same order as they're given. The format string
-`{2} {1} {0}`, however, would format arguments in reverse order.
-
-Things can get a little tricky once you start intermingling the two types of
-positional specifiers. The "next argument" specifier can be thought of as an
-iterator over the argument. Each time a "next argument" specifier is seen, the
-iterator advances. This leads to behavior like this:
-
-```rust
-format!("{1} {} {0} {}", 1i, 2i); // => "2 1 1 2"
-```
-
-The internal iterator over the argument has not been advanced by the time the
-first `{}` is seen, so it prints the first argument. Then upon reaching the
-second `{}`, the iterator has advanced forward to the second argument.
-Essentially, parameters which explicitly name their argument do not affect
-parameters which do not name an argument in terms of positional specifiers.
-
-A format string is required to use all of its arguments, otherwise it is a
-compile-time error. You may refer to the same argument more than once in the
-format string, although it must always be referred to with the same type.
-
-### Named parameters
-
-Rust itself does not have a Python-like equivalent of named parameters to a
-function, but the `format!` macro is a syntax extension which allows it to
-leverage named parameters. Named parameters are listed at the end of the
-argument list and have the syntax:
-
-```text
-identifier '=' expression
-```
-
-For example, the following `format!` expressions all use named argument:
-
-```rust
-# fn main() {
-format!("{argument}", argument = "test");   // => "test"
-format!("{name} {}", 1i, name = 2i);        // => "2 1"
-format!("{a} {c} {b}", a="a", b=(), c=3i);  // => "a 3 ()"
-# }
-```
-
-It is illegal to put positional parameters (those without names) after arguments
-which have names. Like with positional parameters, it is illegal to provide
-named parameters that are unused by the format string.
-
-### Argument types
-
-Each argument's type is dictated by the format string. It is a requirement that
-every argument is only ever referred to by one type. For example, this is an
-invalid format string:
-
-```text
-{0:d} {0:s}
-```
-
-This is invalid because the first argument is both referred to as an integer as
-well as a string.
-
-Because formatting is done via traits, there is no requirement that the
-`d` format actually takes an `int`, but rather it simply requires a type which
-ascribes to the `Signed` formatting trait. There are various parameters which do
-require a particular type, however. Namely if the syntax `{:.*s}` is used, then
-the number of characters to print from the string precedes the actual string and
-must have the type `uint`. Although a `uint` can be printed with `{:u}`, it is
-illegal to reference an argument as such. For example, this is another invalid
-format string:
-
-```text
-{:.*s} {0:u}
-```
-
-### Formatting traits
-
-When requesting that an argument be formatted with a particular type, you are
-actually requesting that an argument ascribes to a particular trait. This allows
-multiple actual types to be formatted via `{:d}` (like `i8` as well as `int`).
-The current mapping of types to traits is:
-
-* *nothing* ⇒ `Show`
-* `o` ⇒ `Octal`
-* `x` ⇒ `LowerHex`
-* `X` ⇒ `UpperHex`
-* `p` ⇒ `Pointer`
-* `b` ⇒ `Binary`
-* `e` ⇒ `LowerExp`
-* `E` ⇒ `UpperExp`
-
-What this means is that any type of argument which implements the
-`std::fmt::Binary` trait can then be formatted with `{:b}`. Implementations are
-provided for these traits for a number of primitive types by the standard
-library as well. If no format is specified (as in `{}` or `{:6}`), then the
-format trait used is the `Show` trait. This is one of the more commonly
-implemented traits when formatting a custom type.
-
-When implementing a format trait for your own type, you will have to implement a
-method of the signature:
-
-```rust
-# use std;
-# mod fmt { pub type Result = (); }
-# struct T;
-# trait SomeName<T> {
-fn fmt(&self, f: &mut std::fmt::Formatter) -> fmt::Result;
-# }
-```
-
-Your type will be passed as `self` by-reference, and then the function should
-emit output into the `f.buf` stream. It is up to each format trait
-implementation to correctly adhere to the requested formatting parameters. The
-values of these parameters will be listed in the fields of the `Formatter`
-struct. In order to help with this, the `Formatter` struct also provides some
-helper methods.
-
-Additionally, the return value of this function is `fmt::Result` which is a
-typedef to `Result<(), IoError>` (also known as `IoResult<()>`). Formatting
-implementations should ensure that they return errors from `write!` correctly
-(propagating errors upward).
-
-An example of implementing the formatting traits would look
-like:
-
-```rust
-use std::fmt;
-use std::f64;
-use std::num::Float;
-
-struct Vector2D {
-    x: int,
-    y: int,
-}
-
-impl fmt::Show for Vector2D {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        // The `f` value implements the `Writer` trait, which is what the
-        // write! macro is expecting. Note that this formatting ignores the
-        // various flags provided to format strings.
-        write!(f, "({}, {})", self.x, self.y)
-    }
-}
-
-// Different traits allow different forms of output of a type. The meaning of
-// this format is to print the magnitude of a vector.
-impl fmt::Binary for Vector2D {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let magnitude = (self.x * self.x + self.y * self.y) as f64;
-        let magnitude = magnitude.sqrt();
-
-        // Respect the formatting flags by using the helper method
-        // `pad_integral` on the Formatter object. See the method documentation
-        // for details, and the function `pad` can be used to pad strings.
-        let decimals = f.precision().unwrap_or(3);
-        let string = f64::to_str_exact(magnitude, decimals);
-        f.pad_integral(true, "", string.as_bytes())
-    }
-}
-
-fn main() {
-    let myvector = Vector2D { x: 3, y: 4 };
-
-    println!("{}", myvector);       // => "(3, 4)"
-    println!("{:10.3b}", myvector); // => "     5.000"
-}
-```
-
-### Related macros
-
-There are a number of related macros in the `format!` family. The ones that are
-currently implemented are:
-
-```ignore
-format!      // described above
-write!       // first argument is a &mut io::Writer, the destination
-writeln!     // same as write but appends a newline
-print!       // the format string is printed to the standard output
-println!     // same as print but appends a newline
-format_args! // described below.
-```
-
-
-#### `write!`
-
-This and `writeln` are two macros which are used to emit the format string to a
-specified stream. This is used to prevent intermediate allocations of format
-strings and instead directly write the output. Under the hood, this function is
-actually invoking the `write` function defined in this module. Example usage is:
-
-```rust
-# #![allow(unused_must_use)]
-use std::io;
-
-let mut w = Vec::new();
-write!(&mut w as &mut io::Writer, "Hello {}!", "world");
-```
-
-#### `print!`
-
-This and `println` emit their output to stdout. Similarly to the `write!` macro,
-the goal of these macros is to avoid intermediate allocations when printing
-output. Example usage is:
-
-```rust
-print!("Hello {}!", "world");
-println!("I have a newline {}", "character at the end");
-```
-
-#### `format_args!`
-This is a curious macro which is used to safely pass around
-an opaque object describing the format string. This object
-does not require any heap allocations to create, and it only
-references information on the stack. Under the hood, all of
-the related macros are implemented in terms of this. First
-off, some example usage is:
-
-```
-use std::fmt;
-use std::io;
-
-# #[allow(unused_must_use)]
-# fn main() {
-format_args!(fmt::format, "this returns {}", "String");
-
-let some_writer: &mut io::Writer = &mut io::stdout();
-format_args!(|args| { write!(some_writer, "{}", args) }, "print with a {}", "closure");
-
-fn my_fmt_fn(args: &fmt::Arguments) {
-    write!(&mut io::stdout(), "{}", args);
-}
-format_args!(my_fmt_fn, "or a {} too", "function");
-# }
-```
-
-The first argument of the `format_args!` macro is a function (or closure) which
-takes one argument of type `&fmt::Arguments`. This structure can then be
-passed to the `write` and `format` functions inside this module in order to
-process the format string. The goal of this macro is to even further prevent
-intermediate allocations when dealing formatting strings.
-
-For example, a logging library could use the standard formatting syntax, but it
-would internally pass around this structure until it has been determined where
-output should go to.
-
-It is unsafe to programmatically create an instance of `fmt::Arguments` because
-the operations performed when executing a format string require the compile-time
-checks provided by the compiler. The `format_args!` macro is the only method of
-safely creating these structures, but they can be unsafely created with the
-constructor provided.
-
-## Syntax
-
-The syntax for the formatting language used is drawn from other languages, so it
-should not be too alien. Arguments are formatted with python-like syntax,
-meaning that arguments are surrounded by `{}` instead of the C-like `%`. The
-actual grammar for the formatting syntax is:
-
-```text
-format_string := <text> [ format <text> ] *
-format := '{' [ argument ] [ ':' format_spec ] '}'
-argument := integer | identifier
-
-format_spec := [[fill]align][sign]['#'][0][width]['.' precision][type]
-fill := character
-align := '<' | '^' | '>'
-sign := '+' | '-'
-width := count
-precision := count | '*'
-type := identifier | ''
-count := parameter | integer
-parameter := integer '$'
-```
-
-## Formatting Parameters
-
-Each argument being formatted can be transformed by a number of formatting
-parameters (corresponding to `format_spec` in the syntax above). These
-parameters affect the string representation of what's being formatted. This
-syntax draws heavily from Python's, so it may seem a bit familiar.
-
-### Fill/Alignment
-
-The fill character is provided normally in conjunction with the `width`
-parameter. This indicates that if the value being formatted is smaller than
-`width` some extra characters will be printed around it. The extra characters
-are specified by `fill`, and the alignment can be one of two options:
-
-* `<` - the argument is left-aligned in `width` columns
-* `^` - the argument is center-aligned in `width` columns
-* `>` - the argument is right-aligned in `width` columns
-
-### Sign/#/0
-
-These can all be interpreted as flags for a particular formatter.
-
-* '+' - This is intended for numeric types and indicates that the sign should
-        always be printed. Positive signs are never printed by default, and the
-        negative sign is only printed by default for the `Signed` trait. This
-        flag indicates that the correct sign (+ or -) should always be printed.
-* '-' - Currently not used
-* '#' - This flag is indicates that the "alternate" form of printing should be
-        used. By default, this only applies to the integer formatting traits and
-        performs like:
-    * `x` - precedes the argument with a "0x"
-    * `X` - precedes the argument with a "0x"
-    * `t` - precedes the argument with a "0b"
-    * `o` - precedes the argument with a "0o"
-* '0' - This is used to indicate for integer formats that the padding should
-        both be done with a `0` character as well as be sign-aware. A format
-        like `{:08d}` would yield `00000001` for the integer `1`, while the same
-        format would yield `-0000001` for the integer `-1`. Notice that the
-        negative version has one fewer zero than the positive version.
-
-### Width
-
-This is a parameter for the "minimum width" that the format should take up. If
-the value's string does not fill up this many characters, then the padding
-specified by fill/alignment will be used to take up the required space.
-
-The default fill/alignment for non-numerics is a space and left-aligned. The
-defaults for numeric formatters is also a space but with right-alignment. If the
-'0' flag is specified for numerics, then the implicit fill character is '0'.
-
-The value for the width can also be provided as a `uint` in the list of
-parameters by using the `2$` syntax indicating that the second argument is a
-`uint` specifying the width.
-
-### Precision
-
-For non-numeric types, this can be considered a "maximum width". If the
-resulting string is longer than this width, then it is truncated down to this
-many characters and only those are emitted.
-
-For integral types, this has no meaning currently.
-
-For floating-point types, this indicates how many digits after the decimal point
-should be printed.
-
-## Escaping
-
-The literal characters `{` and `}` may be included in a string by preceding them
-with the same character. For example, the `{` character is escaped with `{{` and
-the `}` character is escaped with `}}`.
-
-*/
+//! Utilities for formatting and printing strings
+//!
+//! This module contains the runtime support for the `format!` syntax extension.
+//! This macro is implemented in the compiler to emit calls to this module in
+//! order to format arguments at runtime into strings and streams.
+//!
+//! The functions contained in this module should not normally be used in
+//! everyday use cases of `format!`. The assumptions made by these functions are
+//! unsafe for all inputs, and the compiler performs a large amount of
+//! validation on the arguments to `format!` in order to ensure safety at
+//! runtime. While it is possible to call these functions directly, it is not
+//! recommended to do so in the general case.
+//!
+//! ## Usage
+//!
+//! The `format!` macro is intended to be familiar to those coming from C's
+//! printf/fprintf functions or Python's `str.format` function. In its current
+//! revision, the `format!` macro returns a `String` type which is the result of
+//! the formatting. In the future it will also be able to pass in a stream to
+//! format arguments directly while performing minimal allocations.
+//!
+//! Some examples of the `format!` extension are:
+//!
+//! ```rust
+//! # fn main() {
+//! format!("Hello");                  // => "Hello"
+//! format!("Hello, {}!", "world");    // => "Hello, world!"
+//! format!("The number is {}", 1i);   // => "The number is 1"
+//! format!("{}", (3i, 4i));           // => "(3, 4)"
+//! format!("{value}", value=4i);      // => "4"
+//! format!("{} {}", 1i, 2u);          // => "1 2"
+//! # }
+//! ```
+//!
+//! From these, you can see that the first argument is a format string. It is
+//! required by the compiler for this to be a string literal; it cannot be a
+//! variable passed in (in order to perform validity checking). The compiler
+//! will then parse the format string and determine if the list of arguments
+//! provided is suitable to pass to this format string.
+//!
+//! ### Positional parameters
+//!
+//! Each formatting argument is allowed to specify which value argument it's
+//! referencing, and if omitted it is assumed to be "the next argument". For
+//! example, the format string `{} {} {}` would take three parameters, and they
+//! would be formatted in the same order as they're given. The format string
+//! `{2} {1} {0}`, however, would format arguments in reverse order.
+//!
+//! Things can get a little tricky once you start intermingling the two types of
+//! positional specifiers. The "next argument" specifier can be thought of as an
+//! iterator over the argument. Each time a "next argument" specifier is seen,
+//! the iterator advances. This leads to behavior like this:
+//!
+//! ```rust
+//! format!("{1} {} {0} {}", 1i, 2i); // => "2 1 1 2"
+//! ```
+//!
+//! The internal iterator over the argument has not been advanced by the time
+//! the first `{}` is seen, so it prints the first argument. Then upon reaching
+//! the second `{}`, the iterator has advanced forward to the second argument.
+//! Essentially, parameters which explicitly name their argument do not affect
+//! parameters which do not name an argument in terms of positional specifiers.
+//!
+//! A format string is required to use all of its arguments, otherwise it is a
+//! compile-time error. You may refer to the same argument more than once in the
+//! format string, although it must always be referred to with the same type.
+//!
+//! ### Named parameters
+//!
+//! Rust itself does not have a Python-like equivalent of named parameters to a
+//! function, but the `format!` macro is a syntax extension which allows it to
+//! leverage named parameters. Named parameters are listed at the end of the
+//! argument list and have the syntax:
+//!
+//! ```text
+//! identifier '=' expression
+//! ```
+//!
+//! For example, the following `format!` expressions all use named argument:
+//!
+//! ```rust
+//! # fn main() {
+//! format!("{argument}", argument = "test");   // => "test"
+//! format!("{name} {}", 1i, name = 2i);        // => "2 1"
+//! format!("{a} {c} {b}", a="a", b=(), c=3i);  // => "a 3 ()"
+//! # }
+//! ```
+//!
+//! It is illegal to put positional parameters (those without names) after
+//! arguments which have names. Like with positional parameters, it is illegal
+//! to provide named parameters that are unused by the format string.
+//!
+//! ### Argument types
+//!
+//! Each argument's type is dictated by the format string. It is a requirement
+//! that every argument is only ever referred to by one type. For example, this
+//! is an invalid format string:
+//!
+//! ```text
+//! {0:x} {0:o}
+//! ```
+//!
+//! This is invalid because the first argument is both referred to as a
+//! hexidecimal as well as an
+//! octal.
+//!
+//! There are various parameters which do require a particular type, however.
+//! Namely if the syntax `{:.*}` is used, then the number of characters to print
+//! precedes the actual object being formatted, and the number of characters
+//! must have the type `uint`. Although a `uint` can be printed with `{}`, it is
+//! illegal to reference an argument as such. For example this is another
+//! invalid format string:
+//!
+//! ```text
+//! {:.*} {0}
+//! ```
+//!
+//! ### Formatting traits
+//!
+//! When requesting that an argument be formatted with a particular type, you
+//! are actually requesting that an argument ascribes to a particular trait.
+//! This allows multiple actual types to be formatted via `{:x}` (like `i8` as
+//! well as `int`).  The current mapping of types to traits is:
+//!
+//! * *nothing* ⇒ `Show`
+//! * `o` ⇒ `Octal`
+//! * `x` ⇒ `LowerHex`
+//! * `X` ⇒ `UpperHex`
+//! * `p` ⇒ `Pointer`
+//! * `b` ⇒ `Binary`
+//! * `e` ⇒ `LowerExp`
+//! * `E` ⇒ `UpperExp`
+//!
+//! What this means is that any type of argument which implements the
+//! `std::fmt::Binary` trait can then be formatted with `{:b}`. Implementations
+//! are provided for these traits for a number of primitive types by the
+//! standard library as well. If no format is specified (as in `{}` or `{:6}`),
+//! then the format trait used is the `Show` trait. This is one of the more
+//! commonly implemented traits when formatting a custom type.
+//!
+//! When implementing a format trait for your own type, you will have to
+//! implement a method of the signature:
+//!
+//! ```rust
+//! # use std::fmt;
+//! # struct Foo; // our custom type
+//! # impl fmt::Show for Foo {
+//! fn fmt(&self, f: &mut std::fmt::Formatter) -> fmt::Result {
+//! # write!(f, "testing, testing")
+//! # } }
+//! ```
+//!
+//! Your type will be passed as `self` by-reference, and then the function
+//! should emit output into the `f.buf` stream. It is up to each format trait
+//! implementation to correctly adhere to the requested formatting parameters.
+//! The values of these parameters will be listed in the fields of the
+//! `Formatter` struct. In order to help with this, the `Formatter` struct also
+//! provides some helper methods.
+//!
+//! Additionally, the return value of this function is `fmt::Result` which is a
+//! typedef to `Result<(), IoError>` (also known as `IoResult<()>`). Formatting
+//! implementations should ensure that they return errors from `write!`
+//! correctly (propagating errors upward).
+//!
+//! An example of implementing the formatting traits would look
+//! like:
+//!
+//! ```rust
+//! use std::fmt;
+//! use std::f64;
+//! use std::num::Float;
+//!
+//! struct Vector2D {
+//!     x: int,
+//!     y: int,
+//! }
+//!
+//! impl fmt::Show for Vector2D {
+//!     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+//!         // The `f` value implements the `Writer` trait, which is what the
+//!         // write! macro is expecting. Note that this formatting ignores the
+//!         // various flags provided to format strings.
+//!         write!(f, "({}, {})", self.x, self.y)
+//!     }
+//! }
+//!
+//! // Different traits allow different forms of output of a type. The meaning
+//! // of this format is to print the magnitude of a vector.
+//! impl fmt::Binary for Vector2D {
+//!     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+//!         let magnitude = (self.x * self.x + self.y * self.y) as f64;
+//!         let magnitude = magnitude.sqrt();
+//!
+//!         // Respect the formatting flags by using the helper method
+//!         // `pad_integral` on the Formatter object. See the method documentation
+//!         // for details, and the function `pad` can be used to pad strings.
+//!         let decimals = f.precision().unwrap_or(3);
+//!         let string = f64::to_str_exact(magnitude, decimals);
+//!         f.pad_integral(true, "", string.as_bytes())
+//!     }
+//! }
+//!
+//! fn main() {
+//!     let myvector = Vector2D { x: 3, y: 4 };
+//!
+//!     println!("{}", myvector);       // => "(3, 4)"
+//!     println!("{:10.3b}", myvector); // => "     5.000"
+//! }
+//! ```
+//!
+//! ### Related macros
+//!
+//! There are a number of related macros in the `format!` family. The ones that
+//! are currently implemented are:
+//!
+//! ```ignore
+//! format!      // described above
+//! write!       // first argument is a &mut io::Writer, the destination
+//! writeln!     // same as write but appends a newline
+//! print!       // the format string is printed to the standard output
+//! println!     // same as print but appends a newline
+//! format_args! // described below.
+//! ```
+//!
+//! #### `write!`
+//!
+//! This and `writeln` are two macros which are used to emit the format string
+//! to a specified stream. This is used to prevent intermediate allocations of
+//! format strings and instead directly write the output. Under the hood, this
+//! function is actually invoking the `write` function defined in this module.
+//! Example usage is:
+//!
+//! ```rust
+//! # #![allow(unused_must_use)]
+//! use std::io;
+//!
+//! let mut w = Vec::new();
+//! write!(&mut w as &mut io::Writer, "Hello {}!", "world");
+//! ```
+//!
+//! #### `print!`
+//!
+//! This and `println` emit their output to stdout. Similarly to the `write!`
+//! macro, the goal of these macros is to avoid intermediate allocations when
+//! printing output. Example usage is:
+//!
+//! ```rust
+//! print!("Hello {}!", "world");
+//! println!("I have a newline {}", "character at the end");
+//! ```
+//!
+//! #### `format_args!`
+//! This is a curious macro which is used to safely pass around
+//! an opaque object describing the format string. This object
+//! does not require any heap allocations to create, and it only
+//! references information on the stack. Under the hood, all of
+//! the related macros are implemented in terms of this. First
+//! off, some example usage is:
+//!
+//! ```
+//! use std::fmt;
+//! use std::io;
+//!
+//! # #[allow(unused_must_use)]
+//! # fn main() {
+//! format_args!(fmt::format, "this returns {}", "String");
+//!
+//! let some_writer: &mut io::Writer = &mut io::stdout();
+//! format_args!(|args| { write!(some_writer, "{}", args) },
+//!              "print with a {}", "closure");
+//!
+//! fn my_fmt_fn(args: &fmt::Arguments) {
+//!     write!(&mut io::stdout(), "{}", args);
+//! }
+//! format_args!(my_fmt_fn, "or a {} too", "function");
+//! # }
+//! ```
+//!
+//! The first argument of the `format_args!` macro is a function (or closure)
+//! which takes one argument of type `&fmt::Arguments`. This structure can then
+//! be passed to the `write` and `format` functions inside this module in order
+//! to process the format string. The goal of this macro is to even further
+//! prevent intermediate allocations when dealing formatting strings.
+//!
+//! For example, a logging library could use the standard formatting syntax, but
+//! it would internally pass around this structure until it has been determined
+//! where output should go to.
+//!
+//! It is unsafe to programmatically create an instance of `fmt::Arguments`
+//! because the operations performed when executing a format string require the
+//! compile-time checks provided by the compiler. The `format_args!` macro is
+//! the only method of safely creating these structures, but they can be
+//! unsafely created with the constructor provided.
+//!
+//! ## Syntax
+//!
+//! The syntax for the formatting language used is drawn from other languages,
+//! so it should not be too alien. Arguments are formatted with python-like
+//! syntax, meaning that arguments are surrounded by `{}` instead of the C-like
+//! `%`. The actual grammar for the formatting syntax is:
+//!
+//! ```text
+//! format_string := <text> [ format <text> ] *
+//! format := '{' [ argument ] [ ':' format_spec ] '}'
+//! argument := integer | identifier
+//!
+//! format_spec := [[fill]align][sign]['#'][0][width]['.' precision][type]
+//! fill := character
+//! align := '<' | '^' | '>'
+//! sign := '+' | '-'
+//! width := count
+//! precision := count | '*'
+//! type := identifier | ''
+//! count := parameter | integer
+//! parameter := integer '$'
+//! ```
+//!
+//! ## Formatting Parameters
+//!
+//! Each argument being formatted can be transformed by a number of formatting
+//! parameters (corresponding to `format_spec` in the syntax above). These
+//! parameters affect the string representation of what's being formatted. This
+//! syntax draws heavily from Python's, so it may seem a bit familiar.
+//!
+//! ### Fill/Alignment
+//!
+//! The fill character is provided normally in conjunction with the `width`
+//! parameter. This indicates that if the value being formatted is smaller than
+//! `width` some extra characters will be printed around it. The extra
+//! characters are specified by `fill`, and the alignment can be one of two
+//! options:
+//!
+//! * `<` - the argument is left-aligned in `width` columns
+//! * `^` - the argument is center-aligned in `width` columns
+//! * `>` - the argument is right-aligned in `width` columns
+//!
+//! ### Sign/#/0
+//!
+//! These can all be interpreted as flags for a particular formatter.
+//!
+//! * '+' - This is intended for numeric types and indicates that the sign
+//!         should always be printed. Positive signs are never printed by
+//!         default, and the negative sign is only printed by default for the
+//!         `Signed` trait. This flag indicates that the correct sign (+ or -)
+//!         should always be printed.
+//! * '-' - Currently not used
+//! * '#' - This flag is indicates that the "alternate" form of printing should
+//!         be used. By default, this only applies to the integer formatting
+//!         traits and performs like:
+//!     * `x` - precedes the argument with a "0x"
+//!     * `X` - precedes the argument with a "0x"
+//!     * `t` - precedes the argument with a "0b"
+//!     * `o` - precedes the argument with a "0o"
+//! * '0' - This is used to indicate for integer formats that the padding should
+//!         both be done with a `0` character as well as be sign-aware. A format
+//!         like `{:08d}` would yield `00000001` for the integer `1`, while the
+//!         same format would yield `-0000001` for the integer `-1`. Notice that
+//!         the negative version has one fewer zero than the positive version.
+//!
+//! ### Width
+//!
+//! This is a parameter for the "minimum width" that the format should take up.
+//! If the value's string does not fill up this many characters, then the
+//! padding specified by fill/alignment will be used to take up the required
+//! space.
+//!
+//! The default fill/alignment for non-numerics is a space and left-aligned. The
+//! defaults for numeric formatters is also a space but with right-alignment. If
+//! the '0' flag is specified for numerics, then the implicit fill character is
+//! '0'.
+//!
+//! The value for the width can also be provided as a `uint` in the list of
+//! parameters by using the `2$` syntax indicating that the second argument is a
+//! `uint` specifying the width.
+//!
+//! ### Precision
+//!
+//! For non-numeric types, this can be considered a "maximum width". If the
+//! resulting string is longer than this width, then it is truncated down to
+//! this many characters and only those are emitted.
+//!
+//! For integral types, this has no meaning currently.
+//!
+//! For floating-point types, this indicates how many digits after the decimal
+//! point should be printed.
+//!
+//! ## Escaping
+//!
+//! The literal characters `{` and `}` may be included in a string by preceding
+//! them with the same character. For example, the `{` character is escaped with
+//! `{{` and the `}` character is escaped with `}}`.
 
 #![experimental]
 
 use io::Writer;
 use io;
-use result::{Ok, Err};
+use result::Result::{Ok, Err};
 use string;
 use vec::Vec;
 
@@ -418,7 +418,7 @@ pub use core::fmt::Error;
 pub use core::fmt::{Argument, Arguments, write, radix, Radix, RadixFmt};
 
 #[doc(hidden)]
-pub use core::fmt::{argument, argumentstr, argumentuint};
+pub use core::fmt::{argument, argumentuint};
 
 /// The format function takes a precompiled format string and a list of
 /// arguments, to return the resulting formatted string.
diff --git a/src/libstd/hash.rs b/src/libstd/hash.rs
index e4017ea5a47..52e3c718b2d 100644
--- a/src/libstd/hash.rs
+++ b/src/libstd/hash.rs
@@ -8,62 +8,60 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/*!
- * Generic hashing support.
- *
- * This module provides a generic way to compute the hash of a value. The
- * simplest way to make a type hashable is to use `#[deriving(Hash)]`:
- *
- * # Example
- *
- * ```rust
- * use std::hash;
- * use std::hash::Hash;
- *
- * #[deriving(Hash)]
- * struct Person {
- *     id: uint,
- *     name: String,
- *     phone: u64,
- * }
- *
- * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
- * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
- *
- * assert!(hash::hash(&person1) != hash::hash(&person2));
- * ```
- *
- * If you need more control over how a value is hashed, you need to implement
- * the trait `Hash`:
- *
- * ```rust
- * use std::hash;
- * use std::hash::Hash;
- * use std::hash::sip::SipState;
- *
- * struct Person {
- *     id: uint,
- *     name: String,
- *     phone: u64,
- * }
- *
- * impl Hash for Person {
- *     fn hash(&self, state: &mut SipState) {
- *         self.id.hash(state);
- *         self.phone.hash(state);
- *     }
- * }
- *
- * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
- * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
- *
- * assert!(hash::hash(&person1) == hash::hash(&person2));
- * ```
- */
+//! Generic hashing support.
+//!
+//! This module provides a generic way to compute the hash of a value. The
+//! simplest way to make a type hashable is to use `#[deriving(Hash)]`:
+//!
+//! # Example
+//!
+//! ```rust
+//! use std::hash;
+//! use std::hash::Hash;
+//!
+//! #[deriving(Hash)]
+//! struct Person {
+//!     id: uint,
+//!     name: String,
+//!     phone: u64,
+//! }
+//!
+//! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
+//! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
+//!
+//! assert!(hash::hash(&person1) != hash::hash(&person2));
+//! ```
+//!
+//! If you need more control over how a value is hashed, you need to implement
+//! the trait `Hash`:
+//!
+//! ```rust
+//! use std::hash;
+//! use std::hash::Hash;
+//! use std::hash::sip::SipState;
+//!
+//! struct Person {
+//!     id: uint,
+//!     name: String,
+//!     phone: u64,
+//! }
+//!
+//! impl Hash for Person {
+//!     fn hash(&self, state: &mut SipState) {
+//!         self.id.hash(state);
+//!         self.phone.hash(state);
+//!     }
+//! }
+//!
+//! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
+//! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
+//!
+//! assert!(hash::hash(&person1) == hash::hash(&person2));
+//! ```
 
 #![experimental]
 
-pub use core_collections::hash::{Hash, Hasher, Writer, hash, sip};
+pub use core::hash::{Hash, Hasher, Writer, hash, sip};
 
 use core::kinds::Sized;
 use default::Default;
@@ -97,7 +95,9 @@ impl Hasher<sip::SipState> for RandomSipHasher {
     }
 }
 
+#[stable]
 impl Default for RandomSipHasher {
+    #[stable]
     #[inline]
     fn default() -> RandomSipHasher {
         RandomSipHasher::new()
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index 25e85f33aa5..9d9e8827571 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -14,11 +14,12 @@
 
 use cmp;
 use io::{Reader, Writer, Stream, Buffer, DEFAULT_BUF_SIZE, IoResult};
-use iter::ExactSize;
+use iter::ExactSizeIterator;
 use ops::Drop;
-use option::{Some, None, Option};
-use result::{Ok, Err};
-use slice::{SlicePrelude};
+use option::Option;
+use option::Option::{Some, None};
+use result::Result::{Ok, Err};
+use slice::{SliceExt};
 use slice;
 use vec::Vec;
 
@@ -75,15 +76,23 @@ impl<R: Reader> BufferedReader<R> {
     }
 
     /// Gets a reference to the underlying reader.
+    pub fn get_ref<'a>(&self) -> &R { &self.inner }
+
+    /// Gets a mutable reference to the underlying reader.
     ///
-    /// This type does not expose the ability to get a mutable reference to the
-    /// underlying reader because that could possibly corrupt the buffer.
-    pub fn get_ref<'a>(&'a self) -> &'a R { &self.inner }
+    /// # Warning
+    ///
+    /// It is inadvisable to directly read from the underlying reader.
+    pub fn get_mut(&mut self) -> &mut R { &mut self.inner }
 
     /// Unwraps this `BufferedReader`, returning the underlying reader.
     ///
     /// Note that any leftover data in the internal buffer is lost.
-    pub fn unwrap(self) -> R { self.inner }
+    pub fn into_inner(self) -> R { self.inner }
+
+    /// Deprecated, use into_inner() instead
+    #[deprecated = "renamed to into_inner()"]
+    pub fn unwrap(self) -> R { self.into_inner() }
 }
 
 impl<R: Reader> Buffer for BufferedReader<R> {
@@ -172,19 +181,27 @@ impl<W: Writer> BufferedWriter<W> {
     }
 
     /// Gets a reference to the underlying writer.
+    pub fn get_ref(&self) -> &W { self.inner.as_ref().unwrap() }
+
+    /// Gets a mutable reference to the underlying write.
     ///
-    /// This type does not expose the ability to get a mutable reference to the
-    /// underlying reader because that could possibly corrupt the buffer.
-    pub fn get_ref<'a>(&'a self) -> &'a W { self.inner.as_ref().unwrap() }
+    /// # Warning
+    ///
+    /// It is inadvisable to directly read from the underlying writer.
+    pub fn get_mut(&mut self) -> &mut W { self.inner.as_mut().unwrap() }
 
     /// Unwraps this `BufferedWriter`, returning the underlying writer.
     ///
     /// The buffer is flushed before returning the writer.
-    pub fn unwrap(mut self) -> W {
+    pub fn into_inner(mut self) -> W {
         // FIXME(#12628): is panicking the right thing to do if flushing panicks?
         self.flush_buf().unwrap();
         self.inner.take().unwrap()
     }
+
+    /// Deprecated, use into_inner() instead
+    #[deprecated = "renamed to into_inner()"]
+    pub fn unwrap(self) -> W { self.into_inner() }
 }
 
 impl<W: Writer> Writer for BufferedWriter<W> {
@@ -244,7 +261,11 @@ impl<W: Writer> LineBufferedWriter<W> {
     /// Unwraps this `LineBufferedWriter`, returning the underlying writer.
     ///
     /// The internal buffer is flushed before returning the writer.
-    pub fn unwrap(self) -> W { self.inner.unwrap() }
+    pub fn into_inner(self) -> W { self.inner.into_inner() }
+
+    /// Deprecated, use into_inner() instead
+    #[deprecated = "renamed to into_inner()"]
+    pub fn unwrap(self) -> W { self.into_inner() }
 }
 
 impl<W: Writer> Writer for LineBufferedWriter<W> {
@@ -329,22 +350,34 @@ impl<S: Stream> BufferedStream<S> {
     }
 
     /// Gets a reference to the underlying stream.
-    ///
-    /// This type does not expose the ability to get a mutable reference to the
-    /// underlying reader because that could possibly corrupt the buffer.
-    pub fn get_ref<'a>(&'a self) -> &'a S {
+    pub fn get_ref(&self) -> &S {
         let InternalBufferedWriter(ref w) = self.inner.inner;
         w.get_ref()
     }
 
+    /// Gets a mutable reference to the underlying stream.
+    ///
+    /// # Warning
+    ///
+    /// It is inadvisable to read directly from or write directly to the
+    /// underlying stream.
+    pub fn get_mut(&mut self) -> &mut S {
+        let InternalBufferedWriter(ref mut w) = self.inner.inner;
+        w.get_mut()
+    }
+
     /// Unwraps this `BufferedStream`, returning the underlying stream.
     ///
     /// The internal buffer is flushed before returning the stream. Any leftover
     /// data in the read buffer is lost.
-    pub fn unwrap(self) -> S {
+    pub fn into_inner(self) -> S {
         let InternalBufferedWriter(w) = self.inner.inner;
-        w.unwrap()
+        w.into_inner()
     }
+
+    /// Deprecated, use into_inner() instead
+    #[deprecated = "renamed to into_inner()"]
+    pub fn unwrap(self) -> S { self.into_inner() }
 }
 
 impl<S: Stream> Buffer for BufferedStream<S> {
@@ -374,9 +407,8 @@ mod test {
     use prelude::*;
     use super::*;
     use super::super::{IoResult, EndOfFile};
-    use super::super::mem::{MemReader, BufReader};
+    use super::super::mem::MemReader;
     use self::test::Bencher;
-    use str::StrPrelude;
 
     /// A type, free to create, primarily intended for benchmarking creation of
     /// wrappers that, just for construction, don't need a Reader/Writer that
@@ -417,30 +449,30 @@ mod test {
         let nread = reader.read(&mut buf);
         assert_eq!(Ok(3), nread);
         let b: &[_] = &[5, 6, 7];
-        assert_eq!(buf.as_slice(), b);
+        assert_eq!(buf, b);
 
         let mut buf = [0, 0];
         let nread = reader.read(&mut buf);
         assert_eq!(Ok(2), nread);
         let b: &[_] = &[0, 1];
-        assert_eq!(buf.as_slice(), b);
+        assert_eq!(buf, b);
 
         let mut buf = [0];
         let nread = reader.read(&mut buf);
         assert_eq!(Ok(1), nread);
         let b: &[_] = &[2];
-        assert_eq!(buf.as_slice(), b);
+        assert_eq!(buf, b);
 
         let mut buf = [0, 0, 0];
         let nread = reader.read(&mut buf);
         assert_eq!(Ok(1), nread);
         let b: &[_] = &[3, 0, 0];
-        assert_eq!(buf.as_slice(), b);
+        assert_eq!(buf, b);
 
         let nread = reader.read(&mut buf);
         assert_eq!(Ok(1), nread);
         let b: &[_] = &[4, 0, 0];
-        assert_eq!(buf.as_slice(), b);
+        assert_eq!(buf, b);
 
         assert!(reader.read(&mut buf).is_err());
     }
@@ -594,14 +626,14 @@ mod test {
     #[test]
     fn read_char_buffered() {
         let buf = [195u8, 159u8];
-        let mut reader = BufferedReader::with_capacity(1, BufReader::new(&buf));
+        let mut reader = BufferedReader::with_capacity(1, buf[]);
         assert_eq!(reader.read_char(), Ok('ß'));
     }
 
     #[test]
     fn test_chars() {
         let buf = [195u8, 159u8, b'a'];
-        let mut reader = BufferedReader::with_capacity(1, BufReader::new(&buf));
+        let mut reader = BufferedReader::with_capacity(1, buf[]);
         let mut it = reader.chars();
         assert_eq!(it.next(), Some(Ok('ß')));
         assert_eq!(it.next(), Some(Ok('a')));
diff --git a/src/libstd/io/comm_adapters.rs b/src/libstd/io/comm_adapters.rs
index a90b6bbbb8e..3a18b0dc1b5 100644
--- a/src/libstd/io/comm_adapters.rs
+++ b/src/libstd/io/comm_adapters.rs
@@ -12,9 +12,9 @@ use clone::Clone;
 use cmp;
 use comm::{Sender, Receiver};
 use io;
-use option::{None, Some};
-use result::{Ok, Err};
-use slice::{bytes, CloneSliceAllocPrelude, SlicePrelude};
+use option::Option::{None, Some};
+use result::Result::{Ok, Err};
+use slice::{bytes, CloneSliceExt, SliceExt};
 use super::{Buffer, Reader, Writer, IoResult};
 use vec::Vec;
 
@@ -132,6 +132,7 @@ impl ChanWriter {
     }
 }
 
+#[stable]
 impl Clone for ChanWriter {
     fn clone(&self) -> ChanWriter {
         ChanWriter { tx: self.tx.clone() }
@@ -156,18 +157,18 @@ mod test {
     use prelude::*;
     use super::*;
     use io;
-    use task;
+    use thread::Thread;
 
     #[test]
     fn test_rx_reader() {
         let (tx, rx) = channel();
-        task::spawn(proc() {
+        Thread::spawn(move|| {
           tx.send(vec![1u8, 2u8]);
           tx.send(vec![]);
           tx.send(vec![3u8, 4u8]);
           tx.send(vec![5u8, 6u8]);
           tx.send(vec![7u8, 8u8]);
-        });
+        }).detach();
 
         let mut reader = ChanReader::new(rx);
         let mut buf = [0u8, ..3];
@@ -176,41 +177,41 @@ mod test {
 
         assert_eq!(Ok(3), reader.read(&mut buf));
         let a: &[u8] = &[1,2,3];
-        assert_eq!(a, buf.as_slice());
+        assert_eq!(a, buf);
 
         assert_eq!(Ok(3), reader.read(&mut buf));
         let a: &[u8] = &[4,5,6];
-        assert_eq!(a, buf.as_slice());
+        assert_eq!(a, buf);
 
         assert_eq!(Ok(2), reader.read(&mut buf));
         let a: &[u8] = &[7,8,6];
-        assert_eq!(a, buf.as_slice());
+        assert_eq!(a, buf);
 
         match reader.read(buf.as_mut_slice()) {
             Ok(..) => panic!(),
             Err(e) => assert_eq!(e.kind, io::EndOfFile),
         }
-        assert_eq!(a, buf.as_slice());
+        assert_eq!(a, buf);
 
         // Ensure it continues to panic in the same way.
         match reader.read(buf.as_mut_slice()) {
             Ok(..) => panic!(),
             Err(e) => assert_eq!(e.kind, io::EndOfFile),
         }
-        assert_eq!(a, buf.as_slice());
+        assert_eq!(a, buf);
     }
 
     #[test]
     fn test_rx_buffer() {
         let (tx, rx) = channel();
-        task::spawn(proc() {
+        Thread::spawn(move|| {
           tx.send(b"he".to_vec());
           tx.send(b"llo wo".to_vec());
           tx.send(b"".to_vec());
           tx.send(b"rld\nhow ".to_vec());
           tx.send(b"are you?".to_vec());
           tx.send(b"".to_vec());
-        });
+        }).detach();
 
         let mut reader = ChanReader::new(rx);
 
@@ -229,7 +230,7 @@ mod test {
         writer.write_be_u32(42).unwrap();
 
         let wanted = vec![0u8, 0u8, 0u8, 42u8];
-        let got = match task::try(proc() { rx.recv() }) {
+        let got = match Thread::spawn(move|| { rx.recv() }).join() {
             Ok(got) => got,
             Err(_) => panic!(),
         };
diff --git a/src/libstd/io/extensions.rs b/src/libstd/io/extensions.rs
index 4b2ffb4d559..c1f1a5b7869 100644
--- a/src/libstd/io/extensions.rs
+++ b/src/libstd/io/extensions.rs
@@ -19,10 +19,12 @@ use io::{IoError, IoResult, Reader};
 use io;
 use iter::Iterator;
 use num::Int;
-use option::{Option, Some, None};
+use ops::FnOnce;
+use option::Option;
+use option::Option::{Some, None};
 use ptr::RawPtr;
-use result::{Ok, Err};
-use slice::{SlicePrelude, AsSlice};
+use result::Result::{Ok, Err};
+use slice::{SliceExt, AsSlice};
 
 /// An iterator that reads a single byte on each iteration,
 /// until `.read_byte()` returns `EndOfFile`.
@@ -75,7 +77,9 @@ impl<'r, R: Reader> Iterator<IoResult<u8>> for Bytes<'r, R> {
 /// * `f`: A callback that receives the value.
 ///
 /// This function returns the value returned by the callback, for convenience.
-pub fn u64_to_le_bytes<T>(n: u64, size: uint, f: |v: &[u8]| -> T) -> T {
+pub fn u64_to_le_bytes<T, F>(n: u64, size: uint, f: F) -> T where
+    F: FnOnce(&[u8]) -> T,
+{
     use mem::transmute;
 
     // LLVM fails to properly optimize this when using shifts instead of the to_le* intrinsics
@@ -114,7 +118,9 @@ pub fn u64_to_le_bytes<T>(n: u64, size: uint, f: |v: &[u8]| -> T) -> T {
 /// * `f`: A callback that receives the value.
 ///
 /// This function returns the value returned by the callback, for convenience.
-pub fn u64_to_be_bytes<T>(n: u64, size: uint, f: |v: &[u8]| -> T) -> T {
+pub fn u64_to_be_bytes<T, F>(n: u64, size: uint, f: F) -> T where
+    F: FnOnce(&[u8]) -> T,
+{
     use mem::transmute;
 
     // LLVM fails to properly optimize this when using shifts instead of the to_be* intrinsics
@@ -150,7 +156,7 @@ pub fn u64_to_be_bytes<T>(n: u64, size: uint, f: |v: &[u8]| -> T) -> T {
 ///           32-bit value is parsed.
 pub fn u64_from_be_bytes(data: &[u8], start: uint, size: uint) -> u64 {
     use ptr::{copy_nonoverlapping_memory};
-    use slice::SlicePrelude;
+    use slice::SliceExt;
 
     assert!(size <= 8u);
 
@@ -505,7 +511,7 @@ mod bench {
     use self::test::Bencher;
 
     // why is this a macro? wouldn't an inlined function work just as well?
-    macro_rules! u64_from_be_bytes_bench_impl(
+    macro_rules! u64_from_be_bytes_bench_impl {
         ($b:expr, $size:expr, $stride:expr, $start_index:expr) =>
         ({
             use super::u64_from_be_bytes;
@@ -520,7 +526,7 @@ mod bench {
                 }
             });
         })
-    )
+    }
 
     #[bench]
     fn u64_from_be_bytes_4_aligned(b: &mut Bencher) {
diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs
index cd4141e045c..4e736908c37 100644
--- a/src/libstd/io/fs.rs
+++ b/src/libstd/io/fs.rs
@@ -10,61 +10,61 @@
 //
 // ignore-lexer-test FIXME #15679
 
-/*! Synchronous File I/O
-
-This module provides a set of functions and traits for working
-with regular files & directories on a filesystem.
-
-At the top-level of the module are a set of freestanding functions, associated
-with various filesystem operations. They all operate on `Path` objects.
-
-All operations in this module, including those as part of `File` et al
-block the task during execution. In the event of failure, all functions/methods
-will return an `IoResult` type with an `Err` value.
-
-Also included in this module is an implementation block on the `Path` object
-defined in `std::path::Path`. The impl adds useful methods about inspecting the
-metadata of a file. This includes getting the `stat` information, reading off
-particular bits of it, etc.
-
-# Example
-
-```rust
-# #![allow(unused_must_use)]
-use std::io::fs::PathExtensions;
-use std::io::{File, fs};
-
-let path = Path::new("foo.txt");
-
-// create the file, whether it exists or not
-let mut file = File::create(&path);
-file.write(b"foobar");
-# drop(file);
-
-// open the file in read-only mode
-let mut file = File::open(&path);
-file.read_to_end();
-
-println!("{}", path.stat().unwrap().size);
-# drop(file);
-fs::unlink(&path);
-```
-
-*/
+//! Synchronous File I/O
+//!
+//! This module provides a set of functions and traits for working
+//! with regular files & directories on a filesystem.
+//!
+//! At the top-level of the module are a set of freestanding functions, associated
+//! with various filesystem operations. They all operate on `Path` objects.
+//!
+//! All operations in this module, including those as part of `File` et al
+//! block the task during execution. In the event of failure, all functions/methods
+//! will return an `IoResult` type with an `Err` value.
+//!
+//! Also included in this module is an implementation block on the `Path` object
+//! defined in `std::path::Path`. The impl adds useful methods about inspecting the
+//! metadata of a file. This includes getting the `stat` information, reading off
+//! particular bits of it, etc.
+//!
+//! # Example
+//!
+//! ```rust
+//! # #![allow(unused_must_use)]
+//! use std::io::fs::PathExtensions;
+//! use std::io::{File, fs};
+//!
+//! let path = Path::new("foo.txt");
+//!
+//! // create the file, whether it exists or not
+//! let mut file = File::create(&path);
+//! file.write(b"foobar");
+//! # drop(file);
+//!
+//! // open the file in read-only mode
+//! let mut file = File::open(&path);
+//! file.read_to_end();
+//!
+//! println!("{}", path.stat().unwrap().size);
+//! # drop(file);
+//! fs::unlink(&path);
+//! ```
 
 use clone::Clone;
 use io::standard_error;
-use io::{FilePermission, Write, Open, FileAccess, FileMode};
-use io::{IoResult, IoError, FileStat, SeekStyle, Seek, Writer, Reader};
+use io::{FilePermission, Write, Open, FileAccess, FileMode, FileType};
+use io::{IoResult, IoError, InvalidInput};
+use io::{FileStat, SeekStyle, Seek, Writer, Reader};
 use io::{Read, Truncate, ReadWrite, Append};
 use io::UpdateIoError;
 use io;
 use iter::{Iterator, Extend};
-use option::{Some, None, Option};
+use option::Option;
+use option::Option::{Some, None};
 use path::{Path, GenericPath};
 use path;
-use result::{Err, Ok};
-use slice::SlicePrelude;
+use result::Result::{Err, Ok};
+use slice::SliceExt;
 use string::String;
 use vec::Vec;
 
@@ -88,8 +88,8 @@ pub struct File {
     last_nread: int,
 }
 
-impl sys_common::AsFileDesc for File {
-    fn as_fd(&self) -> &fs_imp::FileDesc {
+impl sys_common::AsInner<fs_imp::FileDesc> for File {
+    fn as_inner(&self) -> &fs_imp::FileDesc {
         &self.fd
     }
 }
@@ -136,13 +136,26 @@ impl File {
     pub fn open_mode(path: &Path,
                      mode: FileMode,
                      access: FileAccess) -> IoResult<File> {
-        fs_imp::open(path, mode, access).map(|fd| {
-            File {
-                path: path.clone(),
-                fd: fd,
-                last_nread: -1
+        fs_imp::open(path, mode, access).and_then(|fd| {
+            // On *BSD systems, we can open a directory as a file and read from it:
+            // fd=open("/tmp", O_RDONLY); read(fd, buf, N);
+            // due to an old tradition before the introduction of opendir(3).
+            // We explicitly reject it because there are few use cases.
+            if cfg!(not(any(windows, target_os = "linux", target_os = "android"))) &&
+               try!(fd.fstat()).kind == FileType::Directory {
+                Err(IoError {
+                    kind: InvalidInput,
+                    desc: "is a directory",
+                    detail: None
+                })
+            } else {
+                Ok(File {
+                    path: path.clone(),
+                    fd: fd,
+                    last_nread: -1
+                })
             }
-        }).update_err("couldn't open file", |e| {
+        }).update_err("couldn't open path as file", |e| {
             format!("{}; path={}; mode={}; access={}", e, path.display(),
                 mode_string(mode), access_string(access))
         })
@@ -187,7 +200,7 @@ impl File {
              .update_desc("couldn't create file")
     }
 
-    /// Returns the original path which was used to open this file.
+    /// Returns the original path that was used to open this file.
     pub fn path<'a>(&'a self) -> &'a Path {
         &self.path
     }
@@ -202,7 +215,7 @@ impl File {
     }
 
     /// This function is similar to `fsync`, except that it may not synchronize
-    /// file metadata to the filesystem. This is intended for use case which
+    /// file metadata to the filesystem. This is intended for use cases that
     /// must synchronize content, but don't need the metadata on disk. The goal
     /// of this method is to reduce disk operations.
     pub fn datasync(&mut self) -> IoResult<()> {
@@ -239,7 +252,7 @@ impl File {
     }
 
     /// Queries information about the underlying file.
-    pub fn stat(&mut self) -> IoResult<FileStat> {
+    pub fn stat(&self) -> IoResult<FileStat> {
         self.fd.fstat()
             .update_err("couldn't fstat file", |e|
                 format!("{}; path={}", e, self.path.display()))
@@ -443,7 +456,7 @@ pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> {
 /// # Error
 ///
 /// This function will return an error on failure. Failure conditions include
-/// reading a file that does not exist or reading a file which is not a symlink.
+/// reading a file that does not exist or reading a file that is not a symlink.
 pub fn readlink(path: &Path) -> IoResult<Path> {
     fs_imp::readlink(path)
            .update_err("couldn't resolve symlink for path", |e|
@@ -533,7 +546,7 @@ pub fn readdir(path: &Path) -> IoResult<Vec<Path>> {
                        |e| format!("{}; path={}", e, path.display()))
 }
 
-/// Returns an iterator which will recursively walk the directory structure
+/// Returns an iterator that will recursively walk the directory structure
 /// rooted at `path`. The path given will not be iterated over, and this will
 /// perform iteration in some top-down order.  The contents of unreadable
 /// subdirectories are ignored.
@@ -544,7 +557,7 @@ pub fn walk_dir(path: &Path) -> IoResult<Directories> {
     })
 }
 
-/// An iterator which walks over a directory
+/// An iterator that walks over a directory
 pub struct Directories {
     stack: Vec<Path>,
 }
@@ -592,7 +605,7 @@ pub fn mkdir_recursive(path: &Path, mode: FilePermission) -> IoResult<()> {
         match result {
             Err(mkdir_err) => {
                 // already exists ?
-                if try!(stat(&curpath)).kind != io::TypeDirectory {
+                if try!(stat(&curpath)).kind != FileType::Directory {
                     return Err(mkdir_err);
                 }
             }
@@ -638,7 +651,7 @@ pub fn rmdir_recursive(path: &Path) -> IoResult<()> {
                 false => try!(update_err(lstat(&child), path))
             };
 
-            if child_type.kind == io::TypeDirectory {
+            if child_type.kind == FileType::Directory {
                 rm_stack.push(child);
                 has_child_dir = true;
             } else {
@@ -772,13 +785,13 @@ impl PathExtensions for path::Path {
     }
     fn is_file(&self) -> bool {
         match self.stat() {
-            Ok(s) => s.kind == io::TypeFile,
+            Ok(s) => s.kind == FileType::RegularFile,
             Err(..) => false
         }
     }
     fn is_dir(&self) -> bool {
         match self.stat() {
-            Ok(s) => s.kind == io::TypeDirectory,
+            Ok(s) => s.kind == FileType::Directory,
             Err(..) => false
         }
     }
@@ -806,29 +819,25 @@ fn access_string(access: FileAccess) -> &'static str {
 #[allow(unused_mut)]
 mod test {
     use prelude::*;
-    use io::{SeekSet, SeekCur, SeekEnd, Read, Open, ReadWrite};
+    use io::{SeekSet, SeekCur, SeekEnd, Read, Open, ReadWrite, FileType};
     use io;
     use str;
     use io::fs::*;
-    use path::Path;
-    use io;
-    use ops::Drop;
-    use str::StrPrelude;
 
-    macro_rules! check( ($e:expr) => (
+    macro_rules! check { ($e:expr) => (
         match $e {
             Ok(t) => t,
             Err(e) => panic!("{} failed with: {}", stringify!($e), e),
         }
-    ) )
+    ) }
 
-    macro_rules! error( ($e:expr, $s:expr) => (
+    macro_rules! error { ($e:expr, $s:expr) => (
         match $e {
             Ok(_) => panic!("Unexpected success. Should've been: {}", $s),
-            Err(ref err) => assert!(err.to_string().as_slice().contains($s.as_slice()),
+            Err(ref err) => assert!(err.to_string().contains($s.as_slice()),
                                     format!("`{}` did not contain `{}`", err, $s))
         }
-    ) )
+    ) }
 
     pub struct TempDir(Path);
 
@@ -888,7 +897,7 @@ mod test {
         let filename = &tmpdir.join("file_that_does_not_exist.txt");
         let result = File::open_mode(filename, Open, Read);
 
-        error!(result, "couldn't open file");
+        error!(result, "couldn't open path as file");
         if cfg!(unix) {
             error!(result, "no such file or directory");
         }
@@ -983,7 +992,7 @@ mod test {
         }
         check!(unlink(filename));
         let read_str = str::from_utf8(&read_mem).unwrap();
-        assert!(read_str.as_slice() == final_msg.as_slice());
+        assert!(read_str == final_msg);
     }
 
     #[test]
@@ -1028,12 +1037,12 @@ mod test {
             fs.write(msg.as_bytes()).unwrap();
 
             let fstat_res = check!(fs.stat());
-            assert_eq!(fstat_res.kind, io::TypeFile);
+            assert_eq!(fstat_res.kind, FileType::RegularFile);
         }
         let stat_res_fn = check!(stat(filename));
-        assert_eq!(stat_res_fn.kind, io::TypeFile);
+        assert_eq!(stat_res_fn.kind, FileType::RegularFile);
         let stat_res_meth = check!(filename.stat());
-        assert_eq!(stat_res_meth.kind, io::TypeFile);
+        assert_eq!(stat_res_meth.kind, FileType::RegularFile);
         check!(unlink(filename));
     }
 
@@ -1043,9 +1052,9 @@ mod test {
         let filename = &tmpdir.join("file_stat_correct_on_is_dir");
         check!(mkdir(filename, io::USER_RWX));
         let stat_res_fn = check!(stat(filename));
-        assert!(stat_res_fn.kind == io::TypeDirectory);
+        assert!(stat_res_fn.kind == FileType::Directory);
         let stat_res_meth = check!(filename.stat());
-        assert!(stat_res_meth.kind == io::TypeDirectory);
+        assert!(stat_res_meth.kind == FileType::Directory);
         check!(rmdir(filename));
     }
 
@@ -1091,7 +1100,7 @@ mod test {
             let f = dir.join(format!("{}.txt", n));
             let mut w = check!(File::create(&f));
             let msg_str = format!("{}{}", prefix, n.to_string());
-            let msg = msg_str.as_slice().as_bytes();
+            let msg = msg_str.as_bytes();
             check!(w.write(msg));
         }
         let files = check!(readdir(dir));
@@ -1202,7 +1211,7 @@ mod test {
         assert!(dirpath.is_dir());
 
         let mut filepath = dirpath;
-        filepath.push("unicode-file-\uac00\u4e00\u30fc\u4f60\u597d.rs");
+        filepath.push("unicode-file-\u{ac00}\u{4e00}\u{30fc}\u{4f60}\u{597d}.rs");
         check!(File::create(&filepath)); // ignore return; touch only
         assert!(!filepath.is_dir());
         assert!(filepath.exists());
@@ -1315,8 +1324,8 @@ mod test {
         check!(File::create(&input).write("foobar".as_bytes()));
         check!(symlink(&input, &out));
         if cfg!(not(windows)) {
-            assert_eq!(check!(lstat(&out)).kind, io::TypeSymlink);
-            assert_eq!(check!(out.lstat()).kind, io::TypeSymlink);
+            assert_eq!(check!(lstat(&out)).kind, FileType::Symlink);
+            assert_eq!(check!(out.lstat()).kind, FileType::Symlink);
         }
         assert_eq!(check!(stat(&out)).size, check!(stat(&input)).size);
         assert_eq!(check!(File::open(&out).read_to_end()),
@@ -1350,8 +1359,8 @@ mod test {
         check!(File::create(&input).write("foobar".as_bytes()));
         check!(link(&input, &out));
         if cfg!(not(windows)) {
-            assert_eq!(check!(lstat(&out)).kind, io::TypeFile);
-            assert_eq!(check!(out.lstat()).kind, io::TypeFile);
+            assert_eq!(check!(lstat(&out)).kind, FileType::RegularFile);
+            assert_eq!(check!(out.lstat()).kind, FileType::RegularFile);
             assert_eq!(check!(stat(&out)).unstable.nlink, 2);
             assert_eq!(check!(out.stat()).unstable.nlink, 2);
         }
@@ -1530,7 +1539,7 @@ mod test {
 
         check!(File::create(&tmpdir.join("test")).write(&bytes));
         let actual = check!(File::open(&tmpdir.join("test")).read_to_end());
-        assert!(actual.as_slice() == &bytes);
+        assert!(actual == bytes.as_slice());
     }
 
     #[test]
diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs
index 21de6c2013d..431e11cf9ca 100644
--- a/src/libstd/io/mem.rs
+++ b/src/libstd/io/mem.rs
@@ -15,11 +15,11 @@
 #![allow(deprecated)]
 
 use cmp::min;
-use option::None;
-use result::{Err, Ok};
+use option::Option::None;
+use result::Result::{Err, Ok};
 use io;
 use io::{Reader, Writer, Seek, Buffer, IoError, SeekStyle, IoResult};
-use slice::{mod, AsSlice, SlicePrelude};
+use slice::{mod, AsSlice, SliceExt};
 use vec::Vec;
 
 const BUF_CAPACITY: uint = 128;
@@ -62,7 +62,7 @@ impl Writer for Vec<u8> {
 /// let mut w = MemWriter::new();
 /// w.write(&[0, 1, 2]);
 ///
-/// assert_eq!(w.unwrap(), vec!(0, 1, 2));
+/// assert_eq!(w.into_inner(), vec!(0, 1, 2));
 /// ```
 #[deprecated = "use the Vec<u8> Writer implementation directly"]
 #[deriving(Clone)]
@@ -95,7 +95,11 @@ impl MemWriter {
 
     /// Unwraps this `MemWriter`, returning the underlying buffer
     #[inline]
-    pub fn unwrap(self) -> Vec<u8> { self.buf }
+    pub fn into_inner(self) -> Vec<u8> { self.buf }
+
+    /// Deprecated, use into_inner() instead
+    #[deprecated = "renamed to into_inner()"]
+    pub fn unwrap(self) -> Vec<u8> { self.into_inner() }
 }
 
 impl Writer for MemWriter {
@@ -150,7 +154,11 @@ impl MemReader {
 
     /// Unwraps this `MemReader`, returning the underlying buffer
     #[inline]
-    pub fn unwrap(self) -> Vec<u8> { self.buf }
+    pub fn into_inner(self) -> Vec<u8> { self.buf }
+
+    /// Deprecated, use into_inner() instead
+    #[deprecated = "renamed to into_inner()"]
+    pub fn unwrap(self) -> Vec<u8> { self.into_inner() }
 }
 
 impl Reader for MemReader {
@@ -198,6 +206,41 @@ impl Buffer for MemReader {
     fn consume(&mut self, amt: uint) { self.pos += amt; }
 }
 
+impl<'a> Reader for &'a [u8] {
+    #[inline]
+    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
+        if self.is_empty() { return Err(io::standard_error(io::EndOfFile)); }
+
+        let write_len = min(buf.len(), self.len());
+        {
+            let input = self[..write_len];
+            let output = buf[mut ..write_len];
+            slice::bytes::copy_memory(output, input);
+        }
+
+        *self = self.slice_from(write_len);
+
+        Ok(write_len)
+    }
+}
+
+impl<'a> Buffer for &'a [u8] {
+    #[inline]
+    fn fill_buf(&mut self) -> IoResult<&[u8]> {
+        if self.is_empty() {
+            Err(io::standard_error(io::EndOfFile))
+        } else {
+            Ok(*self)
+        }
+    }
+
+    #[inline]
+    fn consume(&mut self, amt: uint) {
+        *self = self[amt..];
+    }
+}
+
+
 /// Writes to a fixed-size byte slice
 ///
 /// If a write will not fit in the buffer, it returns an error and does not
@@ -225,7 +268,7 @@ impl<'a> BufWriter<'a> {
     /// Creates a new `BufWriter` which will wrap the specified buffer. The
     /// writer initially starts at position 0.
     #[inline]
-    pub fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> {
+    pub fn new(buf: &'a mut [u8]) -> BufWriter<'a> {
         BufWriter {
             buf: buf,
             pos: 0
@@ -235,20 +278,29 @@ impl<'a> BufWriter<'a> {
 
 impl<'a> Writer for BufWriter<'a> {
     #[inline]
-    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
-        // return an error if the entire write does not fit in the buffer
-        let cap = if self.pos >= self.buf.len() { 0 } else { self.buf.len() - self.pos };
-        if buf.len() > cap {
-            return Err(IoError {
-                kind: io::OtherIoError,
-                desc: "Trying to write past end of buffer",
-                detail: None
-            })
+    fn write(&mut self, src: &[u8]) -> IoResult<()> {
+        let dst = self.buf[mut self.pos..];
+        let dst_len = dst.len();
+
+        if dst_len == 0 {
+            return Err(io::standard_error(io::EndOfFile));
         }
 
-        slice::bytes::copy_memory(self.buf[mut self.pos..], buf);
-        self.pos += buf.len();
-        Ok(())
+        let src_len = src.len();
+
+        if dst_len >= src_len {
+            slice::bytes::copy_memory(dst, src);
+
+            self.pos += src_len;
+
+            Ok(())
+        } else {
+            slice::bytes::copy_memory(dst, src[..dst_len]);
+
+            self.pos += dst_len;
+
+            Err(io::standard_error(io::ShortWrite(dst_len)))
+        }
     }
 }
 
@@ -259,7 +311,7 @@ impl<'a> Seek for BufWriter<'a> {
     #[inline]
     fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
         let new = try!(combine(style, self.pos, self.buf.len(), pos));
-        self.pos = new as uint;
+        self.pos = min(new as uint, self.buf.len());
         Ok(())
     }
 }
@@ -272,10 +324,10 @@ impl<'a> Seek for BufWriter<'a> {
 /// # #![allow(unused_must_use)]
 /// use std::io::BufReader;
 ///
-/// let mut buf = [0, 1, 2, 3];
-/// let mut r = BufReader::new(&mut buf);
+/// let buf = [0, 1, 2, 3];
+/// let mut r = BufReader::new(&buf);
 ///
-/// assert_eq!(r.read_to_end().unwrap(), vec!(0, 1, 2, 3));
+/// assert_eq!(r.read_to_end().unwrap(), vec![0, 1, 2, 3]);
 /// ```
 pub struct BufReader<'a> {
     buf: &'a [u8],
@@ -285,7 +337,7 @@ pub struct BufReader<'a> {
 impl<'a> BufReader<'a> {
     /// Creates a new buffered reader which will read the specified buffer
     #[inline]
-    pub fn new<'a>(buf: &'a [u8]) -> BufReader<'a> {
+    pub fn new(buf: &'a [u8]) -> BufReader<'a> {
         BufReader {
             buf: buf,
             pos: 0
@@ -332,7 +384,7 @@ impl<'a> Seek for BufReader<'a> {
 
 impl<'a> Buffer for BufReader<'a> {
     #[inline]
-    fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> {
+    fn fill_buf(&mut self) -> IoResult<&[u8]> {
         if self.pos < self.buf.len() {
             Ok(self.buf[self.pos..])
         } else {
@@ -346,13 +398,22 @@ impl<'a> Buffer for BufReader<'a> {
 
 #[cfg(test)]
 mod test {
-    extern crate test;
+    extern crate "test" as test_crate;
     use prelude::*;
     use super::*;
     use io::*;
     use io;
-    use self::test::Bencher;
-    use str::StrPrelude;
+    use self::test_crate::Bencher;
+
+    #[test]
+    fn test_vec_writer() {
+        let mut writer = Vec::new();
+        writer.write(&[0]).unwrap();
+        writer.write(&[1, 2, 3]).unwrap();
+        writer.write(&[4, 5, 6, 7]).unwrap();
+        let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
+        assert_eq!(writer.as_slice(), b);
+    }
 
     #[test]
     fn test_mem_writer() {
@@ -366,7 +427,7 @@ mod test {
 
     #[test]
     fn test_buf_writer() {
-        let mut buf = [0 as u8, ..8];
+        let mut buf = [0 as u8, ..9];
         {
             let mut writer = BufWriter::new(&mut buf);
             assert_eq!(writer.tell(), Ok(0));
@@ -377,9 +438,12 @@ mod test {
             assert_eq!(writer.tell(), Ok(8));
             writer.write(&[]).unwrap();
             assert_eq!(writer.tell(), Ok(8));
+
+            assert_eq!(writer.write(&[8, 9]).unwrap_err().kind, io::ShortWrite(1));
+            assert_eq!(writer.write(&[10]).unwrap_err().kind, io::EndOfFile);
         }
-        let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
-        assert_eq!(buf.as_slice(), b);
+        let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8];
+        assert_eq!(buf, b);
     }
 
     #[test]
@@ -408,7 +472,7 @@ mod test {
 
         }
         let b: &[_] = &[1, 3, 2, 0, 0, 0, 0, 4];
-        assert_eq!(buf.as_slice(), b);
+        assert_eq!(buf, b);
     }
 
     #[test]
@@ -419,7 +483,7 @@ mod test {
 
         match writer.write(&[0, 0]) {
             Ok(..) => panic!(),
-            Err(e) => assert_eq!(e.kind, io::OtherIoError),
+            Err(e) => assert_eq!(e.kind, io::ShortWrite(1)),
         }
     }
 
@@ -433,12 +497,12 @@ mod test {
         assert_eq!(reader.read(&mut buf), Ok(1));
         assert_eq!(reader.tell(), Ok(1));
         let b: &[_] = &[0];
-        assert_eq!(buf.as_slice(), b);
+        assert_eq!(buf, b);
         let mut buf = [0, ..4];
         assert_eq!(reader.read(&mut buf), Ok(4));
         assert_eq!(reader.tell(), Ok(5));
         let b: &[_] = &[1, 2, 3, 4];
-        assert_eq!(buf.as_slice(), b);
+        assert_eq!(buf, b);
         assert_eq!(reader.read(&mut buf), Ok(3));
         let b: &[_] = &[5, 6, 7];
         assert_eq!(buf[0..3], b);
@@ -450,6 +514,32 @@ mod test {
     }
 
     #[test]
+    fn test_slice_reader() {
+        let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
+        let mut reader = &mut in_buf.as_slice();
+        let mut buf = [];
+        assert_eq!(reader.read(&mut buf), Ok(0));
+        let mut buf = [0];
+        assert_eq!(reader.read(&mut buf), Ok(1));
+        assert_eq!(reader.len(), 7);
+        let b: &[_] = &[0];
+        assert_eq!(buf.as_slice(), b);
+        let mut buf = [0, ..4];
+        assert_eq!(reader.read(&mut buf), Ok(4));
+        assert_eq!(reader.len(), 3);
+        let b: &[_] = &[1, 2, 3, 4];
+        assert_eq!(buf.as_slice(), b);
+        assert_eq!(reader.read(&mut buf), Ok(3));
+        let b: &[_] = &[5, 6, 7];
+        assert_eq!(buf[0..3], b);
+        assert!(reader.read(&mut buf).is_err());
+        let mut reader = &mut in_buf.as_slice();
+        assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3));
+        assert_eq!(reader.read_until(3).unwrap(), vec!(4, 5, 6, 7));
+        assert!(reader.read(&mut buf).is_err());
+    }
+
+    #[test]
     fn test_buf_reader() {
         let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
         let mut reader = BufReader::new(in_buf.as_slice());
@@ -460,12 +550,12 @@ mod test {
         assert_eq!(reader.read(&mut buf), Ok(1));
         assert_eq!(reader.tell(), Ok(1));
         let b: &[_] = &[0];
-        assert_eq!(buf.as_slice(), b);
+        assert_eq!(buf, b);
         let mut buf = [0, ..4];
         assert_eq!(reader.read(&mut buf), Ok(4));
         assert_eq!(reader.tell(), Ok(5));
         let b: &[_] = &[1, 2, 3, 4];
-        assert_eq!(buf.as_slice(), b);
+        assert_eq!(buf, b);
         assert_eq!(reader.read(&mut buf), Ok(3));
         let b: &[_] = &[5, 6, 7];
         assert_eq!(buf[0..3], b);
@@ -501,7 +591,7 @@ mod test {
         writer.write_line("testing").unwrap();
         writer.write_str("testing").unwrap();
         let mut r = BufReader::new(writer.get_ref());
-        assert_eq!(r.read_to_string().unwrap(), "testingtesting\ntesting".to_string());
+        assert_eq!(r.read_to_string().unwrap(), "testingtesting\ntesting");
     }
 
     #[test]
@@ -511,7 +601,7 @@ mod test {
         writer.write_char('\n').unwrap();
         writer.write_char('ệ').unwrap();
         let mut r = BufReader::new(writer.get_ref());
-        assert_eq!(r.read_to_string().unwrap(), "a\nệ".to_string());
+        assert_eq!(r.read_to_string().unwrap(), "a\nệ");
     }
 
     #[test]
@@ -561,15 +651,15 @@ mod test {
         let mut buf = [0, ..3];
         assert!(r.read_at_least(buf.len(), &mut buf).is_ok());
         let b: &[_] = &[1, 2, 3];
-        assert_eq!(buf.as_slice(), b);
+        assert_eq!(buf, b);
         assert!(r.read_at_least(0, buf[mut ..0]).is_ok());
-        assert_eq!(buf.as_slice(), b);
+        assert_eq!(buf, b);
         assert!(r.read_at_least(buf.len(), &mut buf).is_ok());
         let b: &[_] = &[4, 5, 6];
-        assert_eq!(buf.as_slice(), b);
+        assert_eq!(buf, b);
         assert!(r.read_at_least(buf.len(), &mut buf).is_err());
         let b: &[_] = &[7, 8, 6];
-        assert_eq!(buf.as_slice(), b);
+        assert_eq!(buf, b);
     }
 
     fn do_bench_mem_writer(b: &mut Bencher, times: uint, len: uint) {
@@ -666,7 +756,7 @@ mod test {
                 for _i in range(0u, 10) {
                     let mut buf = [0 as u8, .. 10];
                     rdr.read(&mut buf).unwrap();
-                    assert_eq!(buf.as_slice(), [5, .. 10].as_slice());
+                    assert_eq!(buf, [5, .. 10]);
                 }
             }
         });
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 681400e9db5..233ad781093 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -16,207 +16,206 @@
 //        error handling
 
 
-/*! I/O, including files, networking, timers, and processes
-
-`std::io` provides Rust's basic I/O types,
-for reading and writing to files, TCP, UDP,
-and other types of sockets and pipes,
-manipulating the file system, spawning processes.
-
-# Examples
-
-Some examples of obvious things you might want to do
-
-* Read lines from stdin
-
-    ```rust
-    use std::io;
-
-    for line in io::stdin().lines() {
-        print!("{}", line.unwrap());
-    }
-    ```
-
-* Read a complete file
-
-    ```rust
-    use std::io::File;
-
-    let contents = File::open(&Path::new("message.txt")).read_to_end();
-    ```
-
-* Write a line to a file
-
-    ```rust
-    # #![allow(unused_must_use)]
-    use std::io::File;
-
-    let mut file = File::create(&Path::new("message.txt"));
-    file.write(b"hello, file!\n");
-    # drop(file);
-    # ::std::io::fs::unlink(&Path::new("message.txt"));
-    ```
-
-* Iterate over the lines of a file
-
-    ```rust,no_run
-    use std::io::BufferedReader;
-    use std::io::File;
-
-    let path = Path::new("message.txt");
-    let mut file = BufferedReader::new(File::open(&path));
-    for line in file.lines() {
-        print!("{}", line.unwrap());
-    }
-    ```
-
-* Pull the lines of a file into a vector of strings
-
-    ```rust,no_run
-    use std::io::BufferedReader;
-    use std::io::File;
-
-    let path = Path::new("message.txt");
-    let mut file = BufferedReader::new(File::open(&path));
-    let lines: Vec<String> = file.lines().map(|x| x.unwrap()).collect();
-    ```
-
-* Make a simple TCP client connection and request
-
-    ```rust
-    # #![allow(unused_must_use)]
-    use std::io::TcpStream;
-
-    # // connection doesn't fail if a server is running on 8080
-    # // locally, we still want to be type checking this code, so lets
-    # // just stop it running (#11576)
-    # if false {
-    let mut socket = TcpStream::connect("127.0.0.1:8080").unwrap();
-    socket.write(b"GET / HTTP/1.0\n\n");
-    let response = socket.read_to_end();
-    # }
-    ```
-
-* Make a simple TCP server
-
-    ```rust
-    # fn main() { }
-    # fn foo() {
-    # #![allow(dead_code)]
-    use std::io::{TcpListener, TcpStream};
-    use std::io::{Acceptor, Listener};
-
-    let listener = TcpListener::bind("127.0.0.1:80");
-
-    // bind the listener to the specified address
-    let mut acceptor = listener.listen();
-
-    fn handle_client(mut stream: TcpStream) {
-        // ...
-    # &mut stream; // silence unused mutability/variable warning
-    }
-    // accept connections and process them, spawning a new tasks for each one
-    for stream in acceptor.incoming() {
-        match stream {
-            Err(e) => { /* connection failed */ }
-            Ok(stream) => spawn(proc() {
-                // connection succeeded
-                handle_client(stream)
-            })
-        }
-    }
-
-    // close the socket server
-    drop(acceptor);
-    # }
-    ```
-
-
-# Error Handling
-
-I/O is an area where nearly every operation can result in unexpected
-errors. Errors should be painfully visible when they happen, and handling them
-should be easy to work with. It should be convenient to handle specific I/O
-errors, and it should also be convenient to not deal with I/O errors.
-
-Rust's I/O employs a combination of techniques to reduce boilerplate
-while still providing feedback about errors. The basic strategy:
-
-* All I/O operations return `IoResult<T>` which is equivalent to
-  `Result<T, IoError>`. The `Result` type is defined in the `std::result`
-  module.
-* If the `Result` type goes unused, then the compiler will by default emit a
-  warning about the unused result. This is because `Result` has the
-  `#[must_use]` attribute.
-* Common traits are implemented for `IoResult`, e.g.
-  `impl<R: Reader> Reader for IoResult<R>`, so that error values do not have
-  to be 'unwrapped' before use.
-
-These features combine in the API to allow for expressions like
-`File::create(&Path::new("diary.txt")).write(b"Met a girl.\n")`
-without having to worry about whether "diary.txt" exists or whether
-the write succeeds. As written, if either `new` or `write_line`
-encounters an error then the result of the entire expression will
-be an error.
-
-If you wanted to handle the error though you might write:
-
-```rust
-# #![allow(unused_must_use)]
-use std::io::File;
-
-match File::create(&Path::new("diary.txt")).write(b"Met a girl.\n") {
-    Ok(()) => (), // succeeded
-    Err(e) => println!("failed to write to my diary: {}", e),
-}
-
-# ::std::io::fs::unlink(&Path::new("diary.txt"));
-```
-
-So what actually happens if `create` encounters an error?
-It's important to know that what `new` returns is not a `File`
-but an `IoResult<File>`.  If the file does not open, then `new` will simply
-return `Err(..)`. Because there is an implementation of `Writer` (the trait
-required ultimately required for types to implement `write_line`) there is no
-need to inspect or unwrap the `IoResult<File>` and we simply call `write_line`
-on it. If `new` returned an `Err(..)` then the followup call to `write_line`
-will also return an error.
-
-## `try!`
-
-Explicit pattern matching on `IoResult`s can get quite verbose, especially
-when performing many I/O operations. Some examples (like those above) are
-alleviated with extra methods implemented on `IoResult`, but others have more
-complex interdependencies among each I/O operation.
-
-The `try!` macro from `std::macros` is provided as a method of early-return
-inside `Result`-returning functions. It expands to an early-return on `Err`
-and otherwise unwraps the contained `Ok` value.
-
-If you wanted to read several `u32`s from a file and return their product:
-
-```rust
-use std::io::{File, IoResult};
-
-fn file_product(p: &Path) -> IoResult<u32> {
-    let mut f = File::open(p);
-    let x1 = try!(f.read_le_u32());
-    let x2 = try!(f.read_le_u32());
-
-    Ok(x1 * x2)
-}
-
-match file_product(&Path::new("numbers.bin")) {
-    Ok(x) => println!("{}", x),
-    Err(e) => println!("Failed to read numbers!")
-}
-```
-
-With `try!` in `file_product`, each `read_le_u32` need not be directly
-concerned with error handling; instead its caller is responsible for
-responding to errors that may occur while attempting to read the numbers.
-
-*/
+//! I/O, including files, networking, timers, and processes
+//!
+//! `std::io` provides Rust's basic I/O types,
+//! for reading and writing to files, TCP, UDP,
+//! and other types of sockets and pipes,
+//! manipulating the file system, spawning processes.
+//!
+//! # Examples
+//!
+//! Some examples of obvious things you might want to do
+//!
+//! * Read lines from stdin
+//!
+//!     ```rust
+//!     use std::io;
+//!
+//!     for line in io::stdin().lock().lines() {
+//!         print!("{}", line.unwrap());
+//!     }
+//!     ```
+//!
+//! * Read a complete file
+//!
+//!     ```rust
+//!     use std::io::File;
+//!
+//!     let contents = File::open(&Path::new("message.txt")).read_to_end();
+//!     ```
+//!
+//! * Write a line to a file
+//!
+//!     ```rust
+//!     # #![allow(unused_must_use)]
+//!     use std::io::File;
+//!
+//!     let mut file = File::create(&Path::new("message.txt"));
+//!     file.write(b"hello, file!\n");
+//!     # drop(file);
+//!     # ::std::io::fs::unlink(&Path::new("message.txt"));
+//!     ```
+//!
+//! * Iterate over the lines of a file
+//!
+//!     ```rust,no_run
+//!     use std::io::BufferedReader;
+//!     use std::io::File;
+//!
+//!     let path = Path::new("message.txt");
+//!     let mut file = BufferedReader::new(File::open(&path));
+//!     for line in file.lines() {
+//!         print!("{}", line.unwrap());
+//!     }
+//!     ```
+//!
+//! * Pull the lines of a file into a vector of strings
+//!
+//!     ```rust,no_run
+//!     use std::io::BufferedReader;
+//!     use std::io::File;
+//!
+//!     let path = Path::new("message.txt");
+//!     let mut file = BufferedReader::new(File::open(&path));
+//!     let lines: Vec<String> = file.lines().map(|x| x.unwrap()).collect();
+//!     ```
+//!
+//! * Make a simple TCP client connection and request
+//!
+//!     ```rust
+//!     # #![allow(unused_must_use)]
+//!     use std::io::TcpStream;
+//!
+//!     # // connection doesn't fail if a server is running on 8080
+//!     # // locally, we still want to be type checking this code, so lets
+//!     # // just stop it running (#11576)
+//!     # if false {
+//!     let mut socket = TcpStream::connect("127.0.0.1:8080").unwrap();
+//!     socket.write(b"GET / HTTP/1.0\n\n");
+//!     let response = socket.read_to_end();
+//!     # }
+//!     ```
+//!
+//! * Make a simple TCP server
+//!
+//!     ```rust
+//!     # fn main() { }
+//!     # fn foo() {
+//!     # #![allow(dead_code)]
+//!     use std::io::{TcpListener, TcpStream};
+//!     use std::io::{Acceptor, Listener};
+//!     use std::thread::Thread;
+//!
+//!     let listener = TcpListener::bind("127.0.0.1:80");
+//!
+//!     // bind the listener to the specified address
+//!     let mut acceptor = listener.listen();
+//!
+//!     fn handle_client(mut stream: TcpStream) {
+//!         // ...
+//!     # &mut stream; // silence unused mutability/variable warning
+//!     }
+//!     // accept connections and process them, spawning a new tasks for each one
+//!     for stream in acceptor.incoming() {
+//!         match stream {
+//!             Err(e) => { /* connection failed */ }
+//!             Ok(stream) => Thread::spawn(move|| {
+//!                 // connection succeeded
+//!                 handle_client(stream)
+//!             }).detach()
+//!         }
+//!     }
+//!
+//!     // close the socket server
+//!     drop(acceptor);
+//!     # }
+//!     ```
+//!
+//!
+//! # Error Handling
+//!
+//! I/O is an area where nearly every operation can result in unexpected
+//! errors. Errors should be painfully visible when they happen, and handling them
+//! should be easy to work with. It should be convenient to handle specific I/O
+//! errors, and it should also be convenient to not deal with I/O errors.
+//!
+//! Rust's I/O employs a combination of techniques to reduce boilerplate
+//! while still providing feedback about errors. The basic strategy:
+//!
+//! * All I/O operations return `IoResult<T>` which is equivalent to
+//!   `Result<T, IoError>`. The `Result` type is defined in the `std::result`
+//!   module.
+//! * If the `Result` type goes unused, then the compiler will by default emit a
+//!   warning about the unused result. This is because `Result` has the
+//!   `#[must_use]` attribute.
+//! * Common traits are implemented for `IoResult`, e.g.
+//!   `impl<R: Reader> Reader for IoResult<R>`, so that error values do not have
+//!   to be 'unwrapped' before use.
+//!
+//! These features combine in the API to allow for expressions like
+//! `File::create(&Path::new("diary.txt")).write(b"Met a girl.\n")`
+//! without having to worry about whether "diary.txt" exists or whether
+//! the write succeeds. As written, if either `new` or `write_line`
+//! encounters an error then the result of the entire expression will
+//! be an error.
+//!
+//! If you wanted to handle the error though you might write:
+//!
+//! ```rust
+//! # #![allow(unused_must_use)]
+//! use std::io::File;
+//!
+//! match File::create(&Path::new("diary.txt")).write(b"Met a girl.\n") {
+//!     Ok(()) => (), // succeeded
+//!     Err(e) => println!("failed to write to my diary: {}", e),
+//! }
+//!
+//! # ::std::io::fs::unlink(&Path::new("diary.txt"));
+//! ```
+//!
+//! So what actually happens if `create` encounters an error?
+//! It's important to know that what `new` returns is not a `File`
+//! but an `IoResult<File>`.  If the file does not open, then `new` will simply
+//! return `Err(..)`. Because there is an implementation of `Writer` (the trait
+//! required ultimately required for types to implement `write_line`) there is no
+//! need to inspect or unwrap the `IoResult<File>` and we simply call `write_line`
+//! on it. If `new` returned an `Err(..)` then the followup call to `write_line`
+//! will also return an error.
+//!
+//! ## `try!`
+//!
+//! Explicit pattern matching on `IoResult`s can get quite verbose, especially
+//! when performing many I/O operations. Some examples (like those above) are
+//! alleviated with extra methods implemented on `IoResult`, but others have more
+//! complex interdependencies among each I/O operation.
+//!
+//! The `try!` macro from `std::macros` is provided as a method of early-return
+//! inside `Result`-returning functions. It expands to an early-return on `Err`
+//! and otherwise unwraps the contained `Ok` value.
+//!
+//! If you wanted to read several `u32`s from a file and return their product:
+//!
+//! ```rust
+//! use std::io::{File, IoResult};
+//!
+//! fn file_product(p: &Path) -> IoResult<u32> {
+//!     let mut f = File::open(p);
+//!     let x1 = try!(f.read_le_u32());
+//!     let x2 = try!(f.read_le_u32());
+//!
+//!     Ok(x1 * x2)
+//! }
+//!
+//! match file_product(&Path::new("numbers.bin")) {
+//!     Ok(x) => println!("{}", x),
+//!     Err(e) => println!("Failed to read numbers!")
+//! }
+//! ```
+//!
+//! With `try!` in `file_product`, each `read_le_u32` need not be directly
+//! concerned with error handling; instead its caller is responsible for
+//! responding to errors that may occur while attempting to read the numbers.
 
 #![experimental]
 #![deny(unused_must_use)]
@@ -224,7 +223,6 @@ responding to errors that may occur while attempting to read the numbers.
 pub use self::SeekStyle::*;
 pub use self::FileMode::*;
 pub use self::FileAccess::*;
-pub use self::FileType::*;
 pub use self::IoErrorKind::*;
 
 use char::Char;
@@ -233,19 +231,22 @@ use default::Default;
 use error::{FromError, Error};
 use fmt;
 use int;
-use iter::Iterator;
+use iter::{Iterator, IteratorExt};
 use mem::transmute;
-use ops::{BitOr, BitXor, BitAnd, Sub, Not};
-use option::{Option, Some, None};
+use ops::{BitOr, BitXor, BitAnd, Sub, Not, FnOnce};
+use option::Option;
+use option::Option::{Some, None};
 use os;
 use boxed::Box;
-use result::{Ok, Err, Result};
+use result::Result;
+use result::Result::{Ok, Err};
 use sys;
-use slice::{AsSlice, SlicePrelude};
-use str::{Str, StrPrelude};
+use slice::SliceExt;
+use str::StrExt;
 use str;
 use string::String;
 use uint;
+use unicode;
 use unicode::char::UnicodeChar;
 use vec::Vec;
 
@@ -319,7 +320,7 @@ impl IoError {
     pub fn from_errno(errno: uint, detail: bool) -> IoError {
         let mut err = sys::decode_error(errno as i32);
         if detail && err.kind == OtherIoError {
-            err.detail = Some(os::error_string(errno).as_slice().chars()
+            err.detail = Some(os::error_string(errno).chars()
                                  .map(|c| c.to_lowercase()).collect())
         }
         err
@@ -366,7 +367,7 @@ impl FromError<IoError> for Box<Error> {
 }
 
 /// A list specifying general categories of I/O error.
-#[deriving(PartialEq, Eq, Clone, Show)]
+#[deriving(Copy, PartialEq, Eq, Clone, Show)]
 pub enum IoErrorKind {
     /// Any I/O error not part of this list.
     OtherIoError,
@@ -424,18 +425,22 @@ pub enum IoErrorKind {
 /// A trait that lets you add a `detail` to an IoError easily
 trait UpdateIoError<T> {
     /// Returns an IoError with updated description and detail
-    fn update_err(self, desc: &'static str, detail: |&IoError| -> String) -> Self;
+    fn update_err<D>(self, desc: &'static str, detail: D) -> Self where
+        D: FnOnce(&IoError) -> String;
 
     /// Returns an IoError with updated detail
-    fn update_detail(self, detail: |&IoError| -> String) -> Self;
+    fn update_detail<D>(self, detail: D) -> Self where
+        D: FnOnce(&IoError) -> String;
 
     /// Returns an IoError with update description
     fn update_desc(self, desc: &'static str) -> Self;
 }
 
 impl<T> UpdateIoError<T> for IoResult<T> {
-    fn update_err(self, desc: &'static str, detail: |&IoError| -> String) -> IoResult<T> {
-        self.map_err(|mut e| {
+    fn update_err<D>(self, desc: &'static str, detail: D) -> IoResult<T> where
+        D: FnOnce(&IoError) -> String,
+    {
+        self.map_err(move |mut e| {
             let detail = detail(&e);
             e.desc = desc;
             e.detail = Some(detail);
@@ -443,8 +448,10 @@ impl<T> UpdateIoError<T> for IoResult<T> {
         })
     }
 
-    fn update_detail(self, detail: |&IoError| -> String) -> IoResult<T> {
-        self.map_err(|mut e| { e.detail = Some(detail(&e)); e })
+    fn update_detail<D>(self, detail: D) -> IoResult<T> where
+        D: FnOnce(&IoError) -> String,
+    {
+        self.map_err(move |mut e| { e.detail = Some(detail(&e)); e })
     }
 
     fn update_desc(self, desc: &'static str) -> IoResult<T> {
@@ -911,7 +918,7 @@ impl<'a> Reader for Box<Reader+'a> {
     }
 }
 
-impl<'a> Reader for &'a mut Reader+'a {
+impl<'a> Reader for &'a mut (Reader+'a) {
     fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { (*self).read(buf) }
 }
 
@@ -973,7 +980,7 @@ impl<'a, R: Reader> Reader for RefReader<'a, R> {
 }
 
 impl<'a, R: Buffer> Buffer for RefReader<'a, R> {
-    fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> { self.inner.fill_buf() }
+    fn fill_buf(&mut self) -> IoResult<&[u8]> { self.inner.fill_buf() }
     fn consume(&mut self, amt: uint) { self.inner.consume(amt) }
 }
 
@@ -1279,7 +1286,7 @@ impl<'a> Writer for Box<Writer+'a> {
     }
 }
 
-impl<'a> Writer for &'a mut Writer+'a {
+impl<'a> Writer for &'a mut (Writer+'a) {
     #[inline]
     fn write(&mut self, buf: &[u8]) -> IoResult<()> { (**self).write(buf) }
 
@@ -1416,10 +1423,10 @@ pub trait Buffer: Reader {
     /// # Example
     ///
     /// ```rust
-    /// use std::io;
+    /// use std::io::BufReader;
     ///
-    /// let mut reader = io::stdin();
-    /// let input = reader.read_line().ok().unwrap_or("nothing".to_string());
+    /// let mut reader = BufReader::new(b"hello\nworld");
+    /// assert_eq!("hello\n", &*reader.read_line().unwrap());
     /// ```
     ///
     /// # Error
@@ -1499,7 +1506,7 @@ pub trait Buffer: Reader {
     /// valid utf-8 encoded codepoint as the next few bytes in the stream.
     fn read_char(&mut self) -> IoResult<char> {
         let first_byte = try!(self.read_byte());
-        let width = str::utf8_char_width(first_byte);
+        let width = unicode::str::utf8_char_width(first_byte);
         if width == 1 { return Ok(first_byte as char) }
         if width == 0 { return Err(standard_error(InvalidInput)) } // not utf8
         let mut buf = [first_byte, 0, 0, 0];
@@ -1513,7 +1520,7 @@ pub trait Buffer: Reader {
                 }
             }
         }
-        match str::from_utf8(buf[..width]) {
+        match str::from_utf8(buf[..width]).ok() {
             Some(s) => Ok(s.char_at(0)),
             None => Err(standard_error(InvalidInput))
         }
@@ -1552,6 +1559,7 @@ impl<T: Buffer> BufferPrelude for T {
 
 /// When seeking, the resulting cursor is offset from a base by the offset given
 /// to the `seek` function. The base used is specified by this enumeration.
+#[deriving(Copy)]
 pub enum SeekStyle {
     /// Seek from the beginning of the stream
     SeekSet,
@@ -1674,6 +1682,7 @@ pub fn standard_error(kind: IoErrorKind) -> IoError {
 /// A mode specifies how a file should be opened or created. These modes are
 /// passed to `File::open_mode` and are used to control where the file is
 /// positioned when it is initially opened.
+#[deriving(Copy)]
 pub enum FileMode {
     /// Opens a file positioned at the beginning.
     Open,
@@ -1685,6 +1694,7 @@ pub enum FileMode {
 
 /// Access permissions with which the file should be opened. `File`s
 /// opened with `Read` will return an error if written to.
+#[deriving(Copy)]
 pub enum FileAccess {
     /// Read-only access, requests to write will result in an error
     Read,
@@ -1695,25 +1705,25 @@ pub enum FileAccess {
 }
 
 /// Different kinds of files which can be identified by a call to stat
-#[deriving(PartialEq, Show, Hash, Clone)]
+#[deriving(Copy, PartialEq, Show, Hash, Clone)]
 pub enum FileType {
     /// This is a normal file, corresponding to `S_IFREG`
-    TypeFile,
+    RegularFile,
 
     /// This file is a directory, corresponding to `S_IFDIR`
-    TypeDirectory,
+    Directory,
 
     /// This file is a named pipe, corresponding to `S_IFIFO`
-    TypeNamedPipe,
+    NamedPipe,
 
     /// This file is a block device, corresponding to `S_IFBLK`
-    TypeBlockSpecial,
+    BlockSpecial,
 
     /// This file is a symbolic link to another file, corresponding to `S_IFLNK`
-    TypeSymlink,
+    Symlink,
 
     /// The type of this file is not recognized as one of the other categories
-    TypeUnknown,
+    Unknown,
 }
 
 /// A structure used to describe metadata information about a file. This
@@ -1733,7 +1743,7 @@ pub enum FileType {
 /// println!("byte size: {}", info.size);
 /// # }
 /// ```
-#[deriving(Hash)]
+#[deriving(Copy, Hash)]
 pub struct FileStat {
     /// The size of the file, in bytes
     pub size: u64,
@@ -1772,7 +1782,7 @@ pub struct FileStat {
 /// structure. This information is not necessarily platform independent, and may
 /// have different meanings or no meaning at all on some platforms.
 #[unstable]
-#[deriving(Hash)]
+#[deriving(Copy, Hash)]
 pub struct UnstableFileStat {
     /// The ID of the device containing the file.
     pub device: u64,
@@ -1890,7 +1900,10 @@ bitflags! {
     }
 }
 
+
+#[stable]
 impl Default for FilePermission {
+    #[stable]
     #[inline]
     fn default() -> FilePermission { FilePermission::empty() }
 }
@@ -2008,14 +2021,14 @@ mod tests {
     fn test_show() {
         use super::*;
 
-        assert_eq!(format!("{}", USER_READ), "0400".to_string());
-        assert_eq!(format!("{}", USER_FILE), "0644".to_string());
-        assert_eq!(format!("{}", USER_EXEC), "0755".to_string());
-        assert_eq!(format!("{}", USER_RWX),  "0700".to_string());
-        assert_eq!(format!("{}", GROUP_RWX), "0070".to_string());
-        assert_eq!(format!("{}", OTHER_RWX), "0007".to_string());
-        assert_eq!(format!("{}", ALL_PERMISSIONS), "0777".to_string());
-        assert_eq!(format!("{}", USER_READ | USER_WRITE | OTHER_WRITE), "0602".to_string());
+        assert_eq!(format!("{}", USER_READ), "0400");
+        assert_eq!(format!("{}", USER_FILE), "0644");
+        assert_eq!(format!("{}", USER_EXEC), "0755");
+        assert_eq!(format!("{}", USER_RWX),  "0700");
+        assert_eq!(format!("{}", GROUP_RWX), "0070");
+        assert_eq!(format!("{}", OTHER_RWX), "0007");
+        assert_eq!(format!("{}", ALL_PERMISSIONS), "0777");
+        assert_eq!(format!("{}", USER_READ | USER_WRITE | OTHER_WRITE), "0602");
     }
 
     fn _ensure_buffer_is_object_safe<T: Buffer>(x: &T) -> &Buffer {
diff --git a/src/libstd/io/net/addrinfo.rs b/src/libstd/io/net/addrinfo.rs
index 13f602de03a..69ba64d856e 100644
--- a/src/libstd/io/net/addrinfo.rs
+++ b/src/libstd/io/net/addrinfo.rs
@@ -8,14 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/*!
-
-Synchronous DNS Resolution
-
-Contains the functionality to perform DNS resolution in a style related to
-getaddrinfo()
-
-*/
+//! Synchronous DNS Resolution
+//!
+//! Contains the functionality to perform DNS resolution in a style related to
+//! `getaddrinfo()`
 
 #![allow(missing_docs)]
 
@@ -23,14 +19,16 @@ pub use self::SocketType::*;
 pub use self::Flag::*;
 pub use self::Protocol::*;
 
-use iter::Iterator;
+use iter::IteratorExt;
 use io::{IoResult};
 use io::net::ip::{SocketAddr, IpAddr};
-use option::{Option, Some, None};
+use option::Option;
+use option::Option::{Some, None};
 use sys;
 use vec::Vec;
 
 /// Hints to the types of sockets that are desired when looking up hosts
+#[deriving(Copy)]
 pub enum SocketType {
     Stream, Datagram, Raw
 }
@@ -39,6 +37,7 @@ pub enum SocketType {
 /// to manipulate how a query is performed.
 ///
 /// The meaning of each of these flags can be found with `man -s 3 getaddrinfo`
+#[deriving(Copy)]
 pub enum Flag {
     AddrConfig,
     All,
@@ -51,6 +50,7 @@ pub enum Flag {
 
 /// A transport protocol associated with either a hint or a return value of
 /// `lookup`
+#[deriving(Copy)]
 pub enum Protocol {
     TCP, UDP
 }
@@ -60,6 +60,7 @@ pub enum Protocol {
 ///
 /// For details on these fields, see their corresponding definitions via
 /// `man -s 3 getaddrinfo`
+#[deriving(Copy)]
 pub struct Hint {
     pub family: uint,
     pub socktype: Option<SocketType>,
@@ -67,6 +68,7 @@ pub struct Hint {
     pub flags: uint,
 }
 
+#[deriving(Copy)]
 pub struct Info {
     pub address: SocketAddr,
     pub family: uint,
diff --git a/src/libstd/io/net/ip.rs b/src/libstd/io/net/ip.rs
index d87768a0860..add986387da 100644
--- a/src/libstd/io/net/ip.rs
+++ b/src/libstd/io/net/ip.rs
@@ -20,16 +20,18 @@ pub use self::IpAddr::*;
 use fmt;
 use io::{mod, IoResult, IoError};
 use io::net;
-use iter::Iterator;
-use option::{Option, None, Some};
-use result::{Ok, Err};
-use str::{FromStr, StrPrelude};
-use slice::{CloneSlicePrelude, SlicePrelude};
+use iter::{Iterator, IteratorExt};
+use ops::FnOnce;
+use option::Option;
+use option::Option::{None, Some};
+use result::Result::{Ok, Err};
+use slice::{CloneSliceExt, SliceExt};
+use str::{FromStr, StrExt};
 use vec::Vec;
 
 pub type Port = u16;
 
-#[deriving(PartialEq, Eq, Clone, Hash)]
+#[deriving(Copy, PartialEq, Eq, Clone, Hash)]
 pub enum IpAddr {
     Ipv4Addr(u8, u8, u8, u8),
     Ipv6Addr(u16, u16, u16, u16, u16, u16, u16, u16)
@@ -60,7 +62,7 @@ impl fmt::Show for IpAddr {
     }
 }
 
-#[deriving(PartialEq, Eq, Clone, Hash)]
+#[deriving(Copy, PartialEq, Eq, Clone, Hash)]
 pub struct SocketAddr {
     pub ip: IpAddr,
     pub port: Port,
@@ -94,8 +96,9 @@ impl<'a> Parser<'a> {
     }
 
     // Commit only if parser returns Some
-    fn read_atomically<T>(&mut self, cb: |&mut Parser| -> Option<T>)
-                       -> Option<T> {
+    fn read_atomically<T, F>(&mut self, cb: F) -> Option<T> where
+        F: FnOnce(&mut Parser) -> Option<T>,
+    {
         let pos = self.pos;
         let r = cb(self);
         if r.is_none() {
@@ -105,9 +108,10 @@ impl<'a> Parser<'a> {
     }
 
     // Commit only if parser read till EOF
-    fn read_till_eof<T>(&mut self, cb: |&mut Parser| -> Option<T>)
-                     -> Option<T> {
-        self.read_atomically(|p| {
+    fn read_till_eof<T, F>(&mut self, cb: F) -> Option<T> where
+        F: FnOnce(&mut Parser) -> Option<T>,
+    {
+        self.read_atomically(move |p| {
             match cb(p) {
                 Some(x) => if p.is_eof() {Some(x)} else {None},
                 None => None,
@@ -128,15 +132,16 @@ impl<'a> Parser<'a> {
     }
 
     // Apply 3 parsers sequentially
-    fn read_seq_3<A,
-                  B,
-                  C>(
-                  &mut self,
-                  pa: |&mut Parser| -> Option<A>,
-                  pb: |&mut Parser| -> Option<B>,
-                  pc: |&mut Parser| -> Option<C>)
-                  -> Option<(A, B, C)> {
-        self.read_atomically(|p| {
+    fn read_seq_3<A, B, C, PA, PB, PC>(&mut self,
+                                       pa: PA,
+                                       pb: PB,
+                                       pc: PC)
+                                       -> Option<(A, B, C)> where
+        PA: FnOnce(&mut Parser) -> Option<A>,
+        PB: FnOnce(&mut Parser) -> Option<B>,
+        PC: FnOnce(&mut Parser) -> Option<C>,
+    {
+        self.read_atomically(move |p| {
             let a = pa(p);
             let b = if a.is_some() { pb(p) } else { None };
             let c = if b.is_some() { pc(p) } else { None };
@@ -321,22 +326,22 @@ impl<'a> Parser<'a> {
     }
 
     fn read_socket_addr(&mut self) -> Option<SocketAddr> {
-        let ip_addr = |p: &mut Parser| {
+        let ip_addr = |&: p: &mut Parser| {
             let ipv4_p = |p: &mut Parser| p.read_ip_addr();
             let ipv6_p = |p: &mut Parser| {
-                let open_br = |p: &mut Parser| p.read_given_char('[');
-                let ip_addr = |p: &mut Parser| p.read_ipv6_addr();
-                let clos_br = |p: &mut Parser| p.read_given_char(']');
-                p.read_seq_3::<char, IpAddr, char>(open_br, ip_addr, clos_br)
+                let open_br = |&: p: &mut Parser| p.read_given_char('[');
+                let ip_addr = |&: p: &mut Parser| p.read_ipv6_addr();
+                let clos_br = |&: p: &mut Parser| p.read_given_char(']');
+                p.read_seq_3::<char, IpAddr, char, _, _, _>(open_br, ip_addr, clos_br)
                         .map(|t| match t { (_, ip, _) => ip })
             };
             p.read_or(&mut [ipv4_p, ipv6_p])
         };
-        let colon = |p: &mut Parser| p.read_given_char(':');
-        let port  = |p: &mut Parser| p.read_number(10, 5, 0x10000).map(|n| n as u16);
+        let colon = |&: p: &mut Parser| p.read_given_char(':');
+        let port  = |&: p: &mut Parser| p.read_number(10, 5, 0x10000).map(|n| n as u16);
 
         // host, colon, port
-        self.read_seq_3::<IpAddr, char, u16>(ip_addr, colon, port)
+        self.read_seq_3::<IpAddr, char, u16, _, _, _>(ip_addr, colon, port)
                 .map(|t| match t { (ip, _, port) => SocketAddr { ip: ip, port: port } })
     }
 }
@@ -378,8 +383,8 @@ impl FromStr for SocketAddr {
 ///    expected by its `FromStr` implementation or a string like `<host_name>:<port>` pair
 ///    where `<port>` is a `u16` value.
 ///
-///    For the former, `to_socker_addr_all` returns a vector with a single element corresponding
-///    to that socker address.
+///    For the former, `to_socket_addr_all` returns a vector with a single element corresponding
+///    to that socket address.
 ///
 ///    For the latter, it tries to resolve the host name and returns a vector of all IP addresses
 ///    for the host name, each joined with the port.
@@ -438,7 +443,7 @@ pub trait ToSocketAddr {
 
     /// Converts this object to all available socket address values.
     ///
-    /// Some values like host name string naturally corrrespond to multiple IP addresses.
+    /// Some values like host name string naturally correspond to multiple IP addresses.
     /// This method tries to return all available addresses corresponding to this object.
     ///
     /// By default this method delegates to `to_socket_addr` method, creating a singleton
@@ -468,7 +473,7 @@ fn resolve_socket_addr(s: &str, p: u16) -> IoResult<Vec<SocketAddr>> {
 }
 
 fn parse_and_resolve_socket_addr(s: &str) -> IoResult<Vec<SocketAddr>> {
-    macro_rules! try_opt(
+    macro_rules! try_opt {
         ($e:expr, $msg:expr) => (
             match $e {
                 Some(r) => r,
@@ -479,7 +484,7 @@ fn parse_and_resolve_socket_addr(s: &str) -> IoResult<Vec<SocketAddr>> {
                 })
             }
         )
-    )
+    }
 
     // split the string by ':' and convert the second part to u16
     let mut parts_iter = s.rsplitn(2, ':');
@@ -640,10 +645,10 @@ mod test {
     #[test]
     fn ipv6_addr_to_string() {
         let a1 = Ipv6Addr(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
-        assert!(a1.to_string() == "::ffff:192.0.2.128".to_string() ||
-                a1.to_string() == "::FFFF:192.0.2.128".to_string());
+        assert!(a1.to_string() == "::ffff:192.0.2.128" ||
+                a1.to_string() == "::FFFF:192.0.2.128");
         assert_eq!(Ipv6Addr(8, 9, 10, 11, 12, 13, 14, 15).to_string(),
-                   "8:9:a:b:c:d:e:f".to_string());
+                   "8:9:a:b:c:d:e:f");
     }
 
     #[test]
diff --git a/src/libstd/io/net/mod.rs b/src/libstd/io/net/mod.rs
index 5b1747876d7..2056933e6df 100644
--- a/src/libstd/io/net/mod.rs
+++ b/src/libstd/io/net/mod.rs
@@ -11,8 +11,9 @@
 //! Networking I/O
 
 use io::{IoError, IoResult, InvalidInput};
-use option::None;
-use result::{Ok, Err};
+use ops::FnMut;
+use option::Option::None;
+use result::Result::{Ok, Err};
 use self::ip::{SocketAddr, ToSocketAddr};
 
 pub use self::addrinfo::get_host_addresses;
@@ -23,8 +24,10 @@ pub mod udp;
 pub mod ip;
 pub mod pipe;
 
-fn with_addresses<A: ToSocketAddr, T>(addr: A, action: |SocketAddr| -> IoResult<T>)
-    -> IoResult<T> {
+fn with_addresses<A, T, F>(addr: A, mut action: F) -> IoResult<T> where
+    A: ToSocketAddr,
+    F: FnMut(SocketAddr) -> IoResult<T>,
+{
     const DEFAULT_ERROR: IoError = IoError {
         kind: InvalidInput,
         desc: "no addresses found for hostname",
diff --git a/src/libstd/io/net/pipe.rs b/src/libstd/io/net/pipe.rs
index 8e934d221d2..01eb33b44f9 100644
--- a/src/libstd/io/net/pipe.rs
+++ b/src/libstd/io/net/pipe.rs
@@ -8,19 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/*!
-
-Named pipes
-
-This module contains the ability to communicate over named pipes with
-synchronous I/O. On windows, this corresponds to talking over a Named Pipe,
-while on Unix it corresponds to UNIX domain sockets.
-
-These pipes are similar to TCP in the sense that you can have both a stream to a
-server and a server itself. The server provided accepts other `UnixStream`
-instances as clients.
-
-*/
+//! Named pipes
+//!
+//! This module contains the ability to communicate over named pipes with
+//! synchronous I/O. On windows, this corresponds to talking over a Named Pipe,
+//! while on Unix it corresponds to UNIX domain sockets.
+//!
+//! These pipes are similar to TCP in the sense that you can have both a stream to a
+//! server and a server itself. The server provided accepts other `UnixStream`
+//! instances as clients.
 
 #![allow(missing_docs)]
 
@@ -33,6 +29,8 @@ use sys::pipe::UnixStream as UnixStreamImp;
 use sys::pipe::UnixListener as UnixListenerImp;
 use sys::pipe::UnixAcceptor as UnixAcceptorImp;
 
+use sys_common;
+
 /// A stream which communicates over a named pipe.
 pub struct UnixStream {
     inner: UnixStreamImp,
@@ -145,6 +143,12 @@ impl Writer for UnixStream {
     }
 }
 
+impl sys_common::AsInner<UnixStreamImp> for UnixStream {
+    fn as_inner(&self) -> &UnixStreamImp {
+        &self.inner
+    }
+}
+
 /// A value that can listen for incoming named pipe connection requests.
 pub struct UnixListener {
     /// The internal, opaque runtime Unix listener.
@@ -186,6 +190,12 @@ impl Listener<UnixStream, UnixAcceptor> for UnixListener {
     }
 }
 
+impl sys_common::AsInner<UnixListenerImp> for UnixListener {
+    fn as_inner(&self) -> &UnixListenerImp {
+        &self.inner
+    }
+}
+
 /// A value that can accept named pipe connections, returned from `listen()`.
 pub struct UnixAcceptor {
     /// The internal, opaque runtime Unix acceptor.
@@ -247,6 +257,12 @@ impl Clone for UnixAcceptor {
     }
 }
 
+impl sys_common::AsInner<UnixAcceptorImp> for UnixAcceptor {
+    fn as_inner(&self) -> &UnixAcceptorImp {
+        &self.inner
+    }
+}
+
 #[cfg(test)]
 #[allow(experimental)]
 mod tests {
@@ -257,13 +273,16 @@ mod tests {
     use io::fs::PathExtensions;
     use time::Duration;
 
-    pub fn smalltest(server: proc(UnixStream):Send, client: proc(UnixStream):Send) {
+    pub fn smalltest<F,G>(server: F, client: G)
+        where F : FnOnce(UnixStream), F : Send,
+              G : FnOnce(UnixStream), G : Send
+    {
         let path1 = next_test_unix();
         let path2 = path1.clone();
 
         let mut acceptor = UnixListener::bind(&path1).listen();
 
-        spawn(proc() {
+        spawn(move|| {
             match UnixStream::connect(&path2) {
                 Ok(c) => client(c),
                 Err(e) => panic!("failed connect: {}", e),
@@ -305,11 +324,11 @@ mod tests {
 
     #[test]
     fn smoke() {
-        smalltest(proc(mut server) {
+        smalltest(move |mut server| {
             let mut buf = [0];
             server.read(&mut buf).unwrap();
             assert!(buf[0] == 99);
-        }, proc(mut client) {
+        }, move|mut client| {
             client.write(&[99]).unwrap();
         })
     }
@@ -317,18 +336,18 @@ mod tests {
     #[cfg_attr(windows, ignore)] // FIXME(#12516)
     #[test]
     fn read_eof() {
-        smalltest(proc(mut server) {
+        smalltest(move|mut server| {
             let mut buf = [0];
             assert!(server.read(&mut buf).is_err());
             assert!(server.read(&mut buf).is_err());
-        }, proc(_client) {
+        }, move|_client| {
             // drop the client
         })
     }
 
     #[test]
     fn write_begone() {
-        smalltest(proc(mut server) {
+        smalltest(move|mut server| {
             let buf = [0];
             loop {
                 match server.write(&buf) {
@@ -342,7 +361,7 @@ mod tests {
                     }
                 }
             }
-        }, proc(_client) {
+        }, move|_client| {
             // drop the client
         })
     }
@@ -358,7 +377,7 @@ mod tests {
             Err(e) => panic!("failed listen: {}", e),
         };
 
-        spawn(proc() {
+        spawn(move|| {
             for _ in range(0u, times) {
                 let mut stream = UnixStream::connect(&path2);
                 match stream.write(&[100]) {
@@ -392,7 +411,7 @@ mod tests {
         let addr = next_test_unix();
         let mut acceptor = UnixListener::bind(&addr).listen();
 
-        spawn(proc() {
+        spawn(move|| {
             let mut s = UnixStream::connect(&addr);
             let mut buf = [0, 0];
             debug!("client reading");
@@ -408,7 +427,7 @@ mod tests {
 
         let (tx1, rx1) = channel();
         let (tx2, rx2) = channel();
-        spawn(proc() {
+        spawn(move|| {
             let mut s2 = s2;
             rx1.recv();
             debug!("writer writing");
@@ -431,7 +450,7 @@ mod tests {
         let (tx1, rx) = channel();
         let tx2 = tx1.clone();
 
-        spawn(proc() {
+        spawn(move|| {
             let mut s = UnixStream::connect(&addr);
             s.write(&[1]).unwrap();
             rx.recv();
@@ -443,7 +462,7 @@ mod tests {
         let s2 = s1.clone();
 
         let (done, rx) = channel();
-        spawn(proc() {
+        spawn(move|| {
             let mut s2 = s2;
             let mut buf = [0, 0];
             s2.read(&mut buf).unwrap();
@@ -462,7 +481,7 @@ mod tests {
         let addr = next_test_unix();
         let mut acceptor = UnixListener::bind(&addr).listen();
 
-        spawn(proc() {
+        spawn(move|| {
             let mut s = UnixStream::connect(&addr);
             let buf = &mut [0, 1];
             s.read(buf).unwrap();
@@ -473,7 +492,7 @@ mod tests {
         let s2 = s1.clone();
 
         let (tx, rx) = channel();
-        spawn(proc() {
+        spawn(move|| {
             let mut s2 = s2;
             s2.write(&[1]).unwrap();
             tx.send(());
@@ -520,7 +539,7 @@ mod tests {
         // continue to receive any pending connections.
         let (tx, rx) = channel();
         let addr2 = addr.clone();
-        spawn(proc() {
+        spawn(move|| {
             tx.send(UnixStream::connect(&addr2).unwrap());
         });
         let l = rx.recv();
@@ -530,7 +549,7 @@ mod tests {
                 Err(ref e) if e.kind == TimedOut => {}
                 Err(e) => panic!("error: {}", e),
             }
-            ::task::deschedule();
+            ::thread::Thread::yield_now();
             if i == 1000 { panic!("should have a pending connection") }
         }
         drop(l);
@@ -538,7 +557,7 @@ mod tests {
         // Unset the timeout and make sure that this always blocks.
         a.set_timeout(None);
         let addr2 = addr.clone();
-        spawn(proc() {
+        spawn(move|| {
             drop(UnixStream::connect(&addr2).unwrap());
         });
         a.accept().unwrap();
@@ -576,7 +595,7 @@ mod tests {
         let addr = next_test_unix();
         let a = UnixListener::bind(&addr).listen().unwrap();
         let (_tx, rx) = channel::<()>();
-        spawn(proc() {
+        spawn(move|| {
             let mut a = a;
             let _s = a.accept().unwrap();
             let _ = rx.recv_opt();
@@ -613,7 +632,7 @@ mod tests {
         let addr = next_test_unix();
         let a = UnixListener::bind(&addr).listen().unwrap();
         let (_tx, rx) = channel::<()>();
-        spawn(proc() {
+        spawn(move|| {
             let mut a = a;
             let _s = a.accept().unwrap();
             let _ = rx.recv_opt();
@@ -622,7 +641,7 @@ mod tests {
         let mut s = UnixStream::connect(&addr).unwrap();
         let s2 = s.clone();
         let (tx, rx) = channel();
-        spawn(proc() {
+        spawn(move|| {
             let mut s2 = s2;
             assert!(s2.read(&mut [0]).is_err());
             tx.send(());
@@ -639,7 +658,7 @@ mod tests {
         let addr = next_test_unix();
         let mut a = UnixListener::bind(&addr).listen().unwrap();
         let (tx, rx) = channel::<()>();
-        spawn(proc() {
+        spawn(move|| {
             let mut s = UnixStream::connect(&addr).unwrap();
             rx.recv();
             assert!(s.write(&[0]).is_ok());
@@ -677,7 +696,7 @@ mod tests {
         let addr = next_test_unix();
         let mut a = UnixListener::bind(&addr).listen().unwrap();
         let (tx, rx) = channel::<()>();
-        spawn(proc() {
+        spawn(move|| {
             let mut s = UnixStream::connect(&addr).unwrap();
             rx.recv();
             let mut amt = 0;
@@ -706,7 +725,7 @@ mod tests {
         let addr = next_test_unix();
         let mut a = UnixListener::bind(&addr).listen().unwrap();
         let (tx, rx) = channel::<()>();
-        spawn(proc() {
+        spawn(move|| {
             let mut s = UnixStream::connect(&addr).unwrap();
             rx.recv();
             assert!(s.write(&[0]).is_ok());
@@ -733,7 +752,7 @@ mod tests {
         let addr = next_test_unix();
         let mut a = UnixListener::bind(&addr).listen().unwrap();
         let (tx, rx) = channel::<()>();
-        spawn(proc() {
+        spawn(move|| {
             let mut s = UnixStream::connect(&addr).unwrap();
             rx.recv();
             assert!(s.write(&[0]).is_ok());
@@ -743,7 +762,7 @@ mod tests {
         let mut s = a.accept().unwrap();
         let s2 = s.clone();
         let (tx2, rx2) = channel();
-        spawn(proc() {
+        spawn(move|| {
             let mut s2 = s2;
             assert!(s2.read(&mut [0]).is_ok());
             tx2.send(());
@@ -765,10 +784,10 @@ mod tests {
         let mut a2 = a.clone();
 
         let addr2 = addr.clone();
-        spawn(proc() {
+        spawn(move|| {
             let _ = UnixStream::connect(&addr2);
         });
-        spawn(proc() {
+        spawn(move|| {
             let _ = UnixStream::connect(&addr);
         });
 
@@ -788,14 +807,14 @@ mod tests {
         let (tx, rx) = channel();
         let tx2 = tx.clone();
 
-        spawn(proc() { let mut a = a; tx.send(a.accept()) });
-        spawn(proc() { let mut a = a2; tx2.send(a.accept()) });
+        spawn(move|| { let mut a = a; tx.send(a.accept()) });
+        spawn(move|| { let mut a = a2; tx2.send(a.accept()) });
 
         let addr2 = addr.clone();
-        spawn(proc() {
+        spawn(move|| {
             let _ = UnixStream::connect(&addr2);
         });
-        spawn(proc() {
+        spawn(move|| {
             let _ = UnixStream::connect(&addr);
         });
 
@@ -821,7 +840,7 @@ mod tests {
         let mut a2 = a.clone();
 
         let (tx, rx) = channel();
-        spawn(proc() {
+        spawn(move|| {
             let mut a = a;
             tx.send(a.accept());
         });
diff --git a/src/libstd/io/net/tcp.rs b/src/libstd/io/net/tcp.rs
index cab54d82e1c..6adb5387f2e 100644
--- a/src/libstd/io/net/tcp.rs
+++ b/src/libstd/io/net/tcp.rs
@@ -19,33 +19,39 @@
 
 use clone::Clone;
 use io::IoResult;
-use iter::Iterator;
-use result::Err;
+use result::Result::Err;
 use io::net::ip::{SocketAddr, ToSocketAddr};
 use io::{Reader, Writer, Listener, Acceptor};
 use io::{standard_error, TimedOut};
-use option::{None, Some, Option};
+use option::Option;
+use option::Option::{None, Some};
 use time::Duration;
 
 use sys::tcp::TcpStream as TcpStreamImp;
 use sys::tcp::TcpListener as TcpListenerImp;
 use sys::tcp::TcpAcceptor as TcpAcceptorImp;
 
+use sys_common;
+
 /// A structure which represents a TCP stream between a local socket and a
 /// remote socket.
 ///
+/// The socket will be closed when the value is dropped.
+///
 /// # Example
 ///
 /// ```no_run
-/// # #![allow(unused_must_use)]
 /// use std::io::TcpStream;
 ///
-/// let mut stream = TcpStream::connect("127.0.0.1:34254");
+/// {
+///     let mut stream = TcpStream::connect("127.0.0.1:34254");
+///
+///     // ignore the Result
+///     let _ = stream.write(&[1]);
 ///
-/// stream.write(&[1]);
-/// let mut buf = [0];
-/// stream.read(&mut buf);
-/// drop(stream); // close the connection
+///     let mut buf = [0];
+///     let _ = stream.read(&mut buf); // ignore here too
+/// } // the stream is closed here
 /// ```
 pub struct TcpStream {
     inner: TcpStreamImp,
@@ -130,16 +136,17 @@ impl TcpStream {
     /// use std::io::timer;
     /// use std::io::TcpStream;
     /// use std::time::Duration;
+    /// use std::thread::Thread;
     ///
     /// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();
     /// let stream2 = stream.clone();
     ///
-    /// spawn(proc() {
+    /// Thread::spawn(move|| {
     ///     // close this stream after one second
     ///     timer::sleep(Duration::seconds(1));
     ///     let mut stream = stream2;
     ///     stream.close_read();
-    /// });
+    /// }).detach();
     ///
     /// // wait for some data, will get canceled after one second
     /// let mut buf = [0];
@@ -256,6 +263,12 @@ impl Writer for TcpStream {
     }
 }
 
+impl sys_common::AsInner<TcpStreamImp> for TcpStream {
+    fn as_inner(&self) -> &TcpStreamImp {
+        &self.inner
+    }
+}
+
 /// A structure representing a socket server. This listener is used to create a
 /// `TcpAcceptor` which can be used to accept sockets on a local port.
 ///
@@ -267,6 +280,7 @@ impl Writer for TcpStream {
 /// # #![allow(dead_code)]
 /// use std::io::{TcpListener, TcpStream};
 /// use std::io::{Acceptor, Listener};
+/// use std::thread::Thread;
 ///
 /// let listener = TcpListener::bind("127.0.0.1:80");
 ///
@@ -281,10 +295,10 @@ impl Writer for TcpStream {
 /// for stream in acceptor.incoming() {
 ///     match stream {
 ///         Err(e) => { /* connection failed */ }
-///         Ok(stream) => spawn(proc() {
+///         Ok(stream) => Thread::spawn(move|| {
 ///             // connection succeeded
 ///             handle_client(stream)
-///         })
+///         }).detach()
 ///     }
 /// }
 ///
@@ -305,7 +319,7 @@ impl TcpListener {
     /// to this listener. The port allocated can be queried via the
     /// `socket_name` function.
     ///
-    /// The address type can be any implementor of `ToSocketAddr` trait. See its
+    /// The address type can be any implementer of `ToSocketAddr` trait. See its
     /// documentation for concrete examples.
     pub fn bind<A: ToSocketAddr>(addr: A) -> IoResult<TcpListener> {
         super::with_addresses(addr, |addr| {
@@ -325,6 +339,12 @@ impl Listener<TcpStream, TcpAcceptor> for TcpListener {
     }
 }
 
+impl sys_common::AsInner<TcpListenerImp> for TcpListener {
+    fn as_inner(&self) -> &TcpListenerImp {
+        &self.inner
+    }
+}
+
 /// The accepting half of a TCP socket server. This structure is created through
 /// a `TcpListener`'s `listen` method, and this object can be used to accept new
 /// `TcpStream` instances.
@@ -398,11 +418,12 @@ impl TcpAcceptor {
     /// ```
     /// # #![allow(experimental)]
     /// use std::io::{TcpListener, Listener, Acceptor, EndOfFile};
+    /// use std::thread::Thread;
     ///
     /// let mut a = TcpListener::bind("127.0.0.1:8482").listen().unwrap();
     /// let a2 = a.clone();
     ///
-    /// spawn(proc() {
+    /// Thread::spawn(move|| {
     ///     let mut a2 = a2;
     ///     for socket in a2.incoming() {
     ///         match socket {
@@ -411,7 +432,7 @@ impl TcpAcceptor {
     ///             Err(e) => panic!("unexpected error: {}", e),
     ///         }
     ///     }
-    /// });
+    /// }).detach();
     ///
     /// # fn wait_for_sigint() {}
     /// // Now that our accept loop is running, wait for the program to be
@@ -452,6 +473,12 @@ impl Clone for TcpAcceptor {
     }
 }
 
+impl sys_common::AsInner<TcpAcceptorImp> for TcpAcceptor {
+    fn as_inner(&self) -> &TcpAcceptorImp {
+        &self.inner
+    }
+}
+
 #[cfg(test)]
 #[allow(experimental)]
 mod test {
@@ -485,7 +512,7 @@ mod test {
         let listener = TcpListener::bind(socket_addr);
         let mut acceptor = listener.listen();
 
-        spawn(proc() {
+        spawn(move|| {
             let mut stream = TcpStream::connect(("localhost", socket_addr.port));
             stream.write(&[144]).unwrap();
         });
@@ -501,7 +528,7 @@ mod test {
         let addr = next_test_ip4();
         let mut acceptor = TcpListener::bind(addr).listen();
 
-        spawn(proc() {
+        spawn(move|| {
             let mut stream = TcpStream::connect(("localhost", addr.port));
             stream.write(&[64]).unwrap();
         });
@@ -517,7 +544,7 @@ mod test {
         let addr = next_test_ip4();
         let mut acceptor = TcpListener::bind(addr).listen();
 
-        spawn(proc() {
+        spawn(move|| {
             let mut stream = TcpStream::connect(("127.0.0.1", addr.port));
             stream.write(&[44]).unwrap();
         });
@@ -533,7 +560,7 @@ mod test {
         let addr = next_test_ip6();
         let mut acceptor = TcpListener::bind(addr).listen();
 
-        spawn(proc() {
+        spawn(move|| {
             let mut stream = TcpStream::connect(("::1", addr.port));
             stream.write(&[66]).unwrap();
         });
@@ -549,7 +576,7 @@ mod test {
         let addr = next_test_ip4();
         let mut acceptor = TcpListener::bind(addr).listen();
 
-        spawn(proc() {
+        spawn(move|| {
             let mut stream = TcpStream::connect(addr);
             stream.write(&[99]).unwrap();
         });
@@ -565,7 +592,7 @@ mod test {
         let addr = next_test_ip6();
         let mut acceptor = TcpListener::bind(addr).listen();
 
-        spawn(proc() {
+        spawn(move|| {
             let mut stream = TcpStream::connect(addr);
             stream.write(&[99]).unwrap();
         });
@@ -581,7 +608,7 @@ mod test {
         let addr = next_test_ip4();
         let mut acceptor = TcpListener::bind(addr).listen();
 
-        spawn(proc() {
+        spawn(move|| {
             let _stream = TcpStream::connect(addr);
             // Close
         });
@@ -597,7 +624,7 @@ mod test {
         let addr = next_test_ip6();
         let mut acceptor = TcpListener::bind(addr).listen();
 
-        spawn(proc() {
+        spawn(move|| {
             let _stream = TcpStream::connect(addr);
             // Close
         });
@@ -613,7 +640,7 @@ mod test {
         let addr = next_test_ip4();
         let mut acceptor = TcpListener::bind(addr).listen();
 
-        spawn(proc() {
+        spawn(move|| {
             let _stream = TcpStream::connect(addr);
             // Close
         });
@@ -637,7 +664,7 @@ mod test {
         let addr = next_test_ip6();
         let mut acceptor = TcpListener::bind(addr).listen();
 
-        spawn(proc() {
+        spawn(move|| {
             let _stream = TcpStream::connect(addr);
             // Close
         });
@@ -662,7 +689,7 @@ mod test {
         let mut acceptor = TcpListener::bind(addr).listen();
 
         let (tx, rx) = channel();
-        spawn(proc() {
+        spawn(move|| {
             drop(TcpStream::connect(addr));
             tx.send(());
         });
@@ -687,7 +714,7 @@ mod test {
         let mut acceptor = TcpListener::bind(addr).listen();
 
         let (tx, rx) = channel();
-        spawn(proc() {
+        spawn(move|| {
             drop(TcpStream::connect(addr));
             tx.send(());
         });
@@ -712,7 +739,7 @@ mod test {
         let max = 10u;
         let mut acceptor = TcpListener::bind(addr).listen();
 
-        spawn(proc() {
+        spawn(move|| {
             for _ in range(0, max) {
                 let mut stream = TcpStream::connect(addr);
                 stream.write(&[99]).unwrap();
@@ -732,7 +759,7 @@ mod test {
         let max = 10u;
         let mut acceptor = TcpListener::bind(addr).listen();
 
-        spawn(proc() {
+        spawn(move|| {
             for _ in range(0, max) {
                 let mut stream = TcpStream::connect(addr);
                 stream.write(&[99]).unwrap();
@@ -752,11 +779,11 @@ mod test {
         static MAX: int = 10;
         let acceptor = TcpListener::bind(addr).listen();
 
-        spawn(proc() {
+        spawn(move|| {
             let mut acceptor = acceptor;
             for (i, stream) in acceptor.incoming().enumerate().take(MAX as uint) {
                 // Start another task to handle the connection
-                spawn(proc() {
+                spawn(move|| {
                     let mut stream = stream;
                     let mut buf = [0];
                     stream.read(&mut buf).unwrap();
@@ -771,7 +798,7 @@ mod test {
         fn connect(i: int, addr: SocketAddr) {
             if i == MAX { return }
 
-            spawn(proc() {
+            spawn(move|| {
                 debug!("connecting");
                 let mut stream = TcpStream::connect(addr);
                 // Connect again before writing
@@ -788,11 +815,11 @@ mod test {
         static MAX: int = 10;
         let acceptor = TcpListener::bind(addr).listen();
 
-        spawn(proc() {
+        spawn(move|| {
             let mut acceptor = acceptor;
             for (i, stream) in acceptor.incoming().enumerate().take(MAX as uint) {
                 // Start another task to handle the connection
-                spawn(proc() {
+                spawn(move|| {
                     let mut stream = stream;
                     let mut buf = [0];
                     stream.read(&mut buf).unwrap();
@@ -807,7 +834,7 @@ mod test {
         fn connect(i: int, addr: SocketAddr) {
             if i == MAX { return }
 
-            spawn(proc() {
+            spawn(move|| {
                 debug!("connecting");
                 let mut stream = TcpStream::connect(addr);
                 // Connect again before writing
@@ -824,11 +851,11 @@ mod test {
         let addr = next_test_ip4();
         let acceptor = TcpListener::bind(addr).listen();
 
-        spawn(proc() {
+        spawn(move|| {
             let mut acceptor = acceptor;
             for stream in acceptor.incoming().take(MAX as uint) {
                 // Start another task to handle the connection
-                spawn(proc() {
+                spawn(move|| {
                     let mut stream = stream;
                     let mut buf = [0];
                     stream.read(&mut buf).unwrap();
@@ -843,7 +870,7 @@ mod test {
         fn connect(i: int, addr: SocketAddr) {
             if i == MAX { return }
 
-            spawn(proc() {
+            spawn(move|| {
                 debug!("connecting");
                 let mut stream = TcpStream::connect(addr);
                 // Connect again before writing
@@ -860,11 +887,11 @@ mod test {
         let addr = next_test_ip6();
         let acceptor = TcpListener::bind(addr).listen();
 
-        spawn(proc() {
+        spawn(move|| {
             let mut acceptor = acceptor;
             for stream in acceptor.incoming().take(MAX as uint) {
                 // Start another task to handle the connection
-                spawn(proc() {
+                spawn(move|| {
                     let mut stream = stream;
                     let mut buf = [0];
                     stream.read(&mut buf).unwrap();
@@ -879,7 +906,7 @@ mod test {
         fn connect(i: int, addr: SocketAddr) {
             if i == MAX { return }
 
-            spawn(proc() {
+            spawn(move|| {
                 debug!("connecting");
                 let mut stream = TcpStream::connect(addr);
                 // Connect again before writing
@@ -902,7 +929,7 @@ mod test {
 
     pub fn peer_name(addr: SocketAddr) {
         let acceptor = TcpListener::bind(addr).listen();
-        spawn(proc() {
+        spawn(move|| {
             let mut acceptor = acceptor;
             acceptor.accept().unwrap();
         });
@@ -937,7 +964,7 @@ mod test {
     fn partial_read() {
         let addr = next_test_ip4();
         let (tx, rx) = channel();
-        spawn(proc() {
+        spawn(move|| {
             let mut srv = TcpListener::bind(addr).listen().unwrap();
             tx.send(());
             let mut cl = srv.accept().unwrap();
@@ -974,7 +1001,7 @@ mod test {
         let addr = next_test_ip4();
         let (tx, rx) = channel();
 
-        spawn(proc() {
+        spawn(move|| {
             rx.recv();
             let _stream = TcpStream::connect(addr).unwrap();
             // Close
@@ -999,7 +1026,7 @@ mod test {
         let addr = next_test_ip4();
         let mut acceptor = TcpListener::bind(addr).listen();
 
-        spawn(proc() {
+        spawn(move|| {
             let mut s = TcpStream::connect(addr);
             let mut buf = [0, 0];
             assert_eq!(s.read(&mut buf), Ok(1));
@@ -1012,7 +1039,7 @@ mod test {
 
         let (tx1, rx1) = channel();
         let (tx2, rx2) = channel();
-        spawn(proc() {
+        spawn(move|| {
             let mut s2 = s2;
             rx1.recv();
             s2.write(&[1]).unwrap();
@@ -1031,7 +1058,7 @@ mod test {
         let (tx1, rx) = channel();
         let tx2 = tx1.clone();
 
-        spawn(proc() {
+        spawn(move|| {
             let mut s = TcpStream::connect(addr);
             s.write(&[1]).unwrap();
             rx.recv();
@@ -1043,7 +1070,7 @@ mod test {
         let s2 = s1.clone();
 
         let (done, rx) = channel();
-        spawn(proc() {
+        spawn(move|| {
             let mut s2 = s2;
             let mut buf = [0, 0];
             s2.read(&mut buf).unwrap();
@@ -1062,7 +1089,7 @@ mod test {
         let addr = next_test_ip4();
         let mut acceptor = TcpListener::bind(addr).listen();
 
-        spawn(proc() {
+        spawn(move|| {
             let mut s = TcpStream::connect(addr);
             let mut buf = [0, 1];
             s.read(&mut buf).unwrap();
@@ -1073,7 +1100,7 @@ mod test {
         let s2 = s1.clone();
 
         let (done, rx) = channel();
-        spawn(proc() {
+        spawn(move|| {
             let mut s2 = s2;
             s2.write(&[1]).unwrap();
             done.send(());
@@ -1087,7 +1114,7 @@ mod test {
     fn shutdown_smoke() {
         let addr = next_test_ip4();
         let a = TcpListener::bind(addr).unwrap().listen();
-        spawn(proc() {
+        spawn(move|| {
             let mut a = a;
             let mut c = a.accept().unwrap();
             assert_eq!(c.read_to_end(), Ok(vec!()));
@@ -1121,7 +1148,7 @@ mod test {
         //        flakiness.
         if !cfg!(target_os = "freebsd") {
             let (tx, rx) = channel();
-            spawn(proc() {
+            spawn(move|| {
                 tx.send(TcpStream::connect(addr).unwrap());
             });
             let _l = rx.recv();
@@ -1131,14 +1158,14 @@ mod test {
                     Err(ref e) if e.kind == TimedOut => {}
                     Err(e) => panic!("error: {}", e),
                 }
-                ::task::deschedule();
+                ::thread::Thread::yield_now();
                 if i == 1000 { panic!("should have a pending connection") }
             }
         }
 
         // Unset the timeout and make sure that this always blocks.
         a.set_timeout(None);
-        spawn(proc() {
+        spawn(move|| {
             drop(TcpStream::connect(addr).unwrap());
         });
         a.accept().unwrap();
@@ -1149,7 +1176,7 @@ mod test {
         let addr = next_test_ip4();
         let a = TcpListener::bind(addr).listen().unwrap();
         let (_tx, rx) = channel::<()>();
-        spawn(proc() {
+        spawn(move|| {
             let mut a = a;
             let _s = a.accept().unwrap();
             let _ = rx.recv_opt();
@@ -1186,7 +1213,7 @@ mod test {
         let addr = next_test_ip4();
         let a = TcpListener::bind(addr).listen().unwrap();
         let (_tx, rx) = channel::<()>();
-        spawn(proc() {
+        spawn(move|| {
             let mut a = a;
             let _s = a.accept().unwrap();
             let _ = rx.recv_opt();
@@ -1195,7 +1222,7 @@ mod test {
         let mut s = TcpStream::connect(addr).unwrap();
         let s2 = s.clone();
         let (tx, rx) = channel();
-        spawn(proc() {
+        spawn(move|| {
             let mut s2 = s2;
             assert!(s2.read(&mut [0]).is_err());
             tx.send(());
@@ -1212,7 +1239,7 @@ mod test {
         let addr = next_test_ip6();
         let mut a = TcpListener::bind(addr).listen().unwrap();
         let (tx, rx) = channel::<()>();
-        spawn(proc() {
+        spawn(move|| {
             let mut s = TcpStream::connect(addr).unwrap();
             rx.recv();
             assert!(s.write(&[0]).is_ok());
@@ -1245,7 +1272,7 @@ mod test {
         let addr = next_test_ip6();
         let mut a = TcpListener::bind(addr).listen().unwrap();
         let (tx, rx) = channel::<()>();
-        spawn(proc() {
+        spawn(move|| {
             let mut s = TcpStream::connect(addr).unwrap();
             rx.recv();
             let mut amt = 0;
@@ -1274,7 +1301,7 @@ mod test {
         let addr = next_test_ip6();
         let mut a = TcpListener::bind(addr).listen().unwrap();
         let (tx, rx) = channel::<()>();
-        spawn(proc() {
+        spawn(move|| {
             let mut s = TcpStream::connect(addr).unwrap();
             rx.recv();
             assert!(s.write(&[0]).is_ok());
@@ -1302,7 +1329,7 @@ mod test {
         let addr = next_test_ip6();
         let mut a = TcpListener::bind(addr).listen().unwrap();
         let (tx, rx) = channel::<()>();
-        spawn(proc() {
+        spawn(move|| {
             let mut s = TcpStream::connect(addr).unwrap();
             rx.recv();
             assert_eq!(s.write(&[0]), Ok(()));
@@ -1312,7 +1339,7 @@ mod test {
         let mut s = a.accept().unwrap();
         let s2 = s.clone();
         let (tx2, rx2) = channel();
-        spawn(proc() {
+        spawn(move|| {
             let mut s2 = s2;
             assert_eq!(s2.read(&mut [0]), Ok(1));
             tx2.send(());
@@ -1335,7 +1362,7 @@ mod test {
         let (tx, rx) = channel();
         let (txdone, rxdone) = channel();
         let txdone2 = txdone.clone();
-        spawn(proc() {
+        spawn(move|| {
             let mut tcp = TcpStream::connect(addr).unwrap();
             rx.recv();
             tcp.write_u8(0).unwrap();
@@ -1346,7 +1373,7 @@ mod test {
         let tcp = accept.accept().unwrap();
         let tcp2 = tcp.clone();
         let txdone3 = txdone.clone();
-        spawn(proc() {
+        spawn(move|| {
             let mut tcp2 = tcp2;
             tcp2.read_u8().unwrap();
             txdone3.send(());
@@ -1354,7 +1381,7 @@ mod test {
 
         // Try to ensure that the reading clone is indeed reading
         for _ in range(0i, 50) {
-            ::task::deschedule();
+            ::thread::Thread::yield_now();
         }
 
         // clone the handle again while it's reading, then let it finish the
@@ -1372,10 +1399,10 @@ mod test {
         let mut a = l.listen().unwrap();
         let mut a2 = a.clone();
 
-        spawn(proc() {
+        spawn(move|| {
             let _ = TcpStream::connect(addr);
         });
-        spawn(proc() {
+        spawn(move|| {
             let _ = TcpStream::connect(addr);
         });
 
@@ -1393,13 +1420,13 @@ mod test {
         let (tx, rx) = channel();
         let tx2 = tx.clone();
 
-        spawn(proc() { let mut a = a; tx.send(a.accept()) });
-        spawn(proc() { let mut a = a2; tx2.send(a.accept()) });
+        spawn(move|| { let mut a = a; tx.send(a.accept()) });
+        spawn(move|| { let mut a = a2; tx2.send(a.accept()) });
 
-        spawn(proc() {
+        spawn(move|| {
             let _ = TcpStream::connect(addr);
         });
-        spawn(proc() {
+        spawn(move|| {
             let _ = TcpStream::connect(addr);
         });
 
@@ -1425,7 +1452,7 @@ mod test {
         let mut a2 = a.clone();
 
         let (tx, rx) = channel();
-        spawn(proc() {
+        spawn(move|| {
             let mut a = a;
             tx.send(a.accept());
         });
diff --git a/src/libstd/io/net/udp.rs b/src/libstd/io/net/udp.rs
index 567e7da0c00..f462143faf4 100644
--- a/src/libstd/io/net/udp.rs
+++ b/src/libstd/io/net/udp.rs
@@ -18,9 +18,11 @@
 use clone::Clone;
 use io::net::ip::{SocketAddr, IpAddr, ToSocketAddr};
 use io::{Reader, Writer, IoResult};
+use ops::FnOnce;
 use option::Option;
-use result::{Ok, Err};
+use result::Result::{Ok, Err};
 use sys::udp::UdpSocket as UdpSocketImp;
+use sys_common;
 
 /// A User Datagram Protocol socket.
 ///
@@ -80,7 +82,7 @@ impl UdpSocket {
     /// Sends data on the socket to the given address. Returns nothing on
     /// success.
     ///
-    /// Address type can be any implementor of `ToSocketAddr` trait. See its
+    /// Address type can be any implementer of `ToSocketAddr` trait. See its
     /// documentation for concrete examples.
     pub fn send_to<A: ToSocketAddr>(&mut self, buf: &[u8], addr: A) -> IoResult<()> {
         super::with_addresses(addr, |addr| self.inner.send_to(buf, addr))
@@ -184,6 +186,12 @@ impl Clone for UdpSocket {
     }
 }
 
+impl sys_common::AsInner<UdpSocketImp> for UdpSocket {
+    fn as_inner(&self) -> &UdpSocketImp {
+        &self.inner
+    }
+}
+
 /// A type that allows convenient usage of a UDP stream connected to one
 /// address via the `Reader` and `Writer` traits.
 ///
@@ -203,7 +211,9 @@ impl UdpStream {
     /// Allows access to the underlying UDP socket owned by this stream. This
     /// is useful to, for example, use the socket to send data to hosts other
     /// than the one that this stream is connected to.
-    pub fn as_socket<T>(&mut self, f: |&mut UdpSocket| -> T) -> T {
+    pub fn as_socket<T, F>(&mut self, f: F) -> T where
+        F: FnOnce(&mut UdpSocket) -> T,
+    {
         f(&mut self.socket)
     }
 
@@ -262,7 +272,7 @@ mod test {
         let (tx1, rx1) = channel();
         let (tx2, rx2) = channel();
 
-        spawn(proc() {
+        spawn(move|| {
             match UdpSocket::bind(client_ip) {
                 Ok(ref mut client) => {
                     rx1.recv();
@@ -297,7 +307,7 @@ mod test {
         let client_ip = next_test_ip6();
         let (tx, rx) = channel::<()>();
 
-        spawn(proc() {
+        spawn(move|| {
             match UdpSocket::bind(client_ip) {
                 Ok(ref mut client) => {
                     rx.recv();
@@ -333,7 +343,7 @@ mod test {
         let (tx1, rx1) = channel();
         let (tx2, rx2) = channel();
 
-        spawn(proc() {
+        spawn(move|| {
             let send_as = |ip, val: &[u8]| {
                 match UdpSocket::bind(ip) {
                     Ok(client) => {
@@ -377,7 +387,7 @@ mod test {
         let (tx1, rx1) = channel();
         let (tx2, rx2) = channel();
 
-        spawn(proc() {
+        spawn(move|| {
             match UdpSocket::bind(client_ip) {
                 Ok(client) => {
                     let client = box client;
@@ -439,7 +449,7 @@ mod test {
         let mut sock1 = UdpSocket::bind(addr1).unwrap();
         let sock2 = UdpSocket::bind(addr2).unwrap();
 
-        spawn(proc() {
+        spawn(move|| {
             let mut sock2 = sock2;
             let mut buf = [0, 0];
             assert_eq!(sock2.recv_from(&mut buf), Ok((1, addr1)));
@@ -451,7 +461,7 @@ mod test {
 
         let (tx1, rx1) = channel();
         let (tx2, rx2) = channel();
-        spawn(proc() {
+        spawn(move|| {
             let mut sock3 = sock3;
             rx1.recv();
             sock3.send_to(&[1], addr2).unwrap();
@@ -472,7 +482,7 @@ mod test {
         let (tx1, rx) = channel();
         let tx2 = tx1.clone();
 
-        spawn(proc() {
+        spawn(move|| {
             let mut sock2 = sock2;
             sock2.send_to(&[1], addr1).unwrap();
             rx.recv();
@@ -483,7 +493,7 @@ mod test {
         let sock3 = sock1.clone();
 
         let (done, rx) = channel();
-        spawn(proc() {
+        spawn(move|| {
             let mut sock3 = sock3;
             let mut buf = [0, 0];
             sock3.recv_from(&mut buf).unwrap();
@@ -507,7 +517,7 @@ mod test {
         let (tx, rx) = channel();
         let (serv_tx, serv_rx) = channel();
 
-        spawn(proc() {
+        spawn(move|| {
             let mut sock2 = sock2;
             let mut buf = [0, 1];
 
@@ -523,7 +533,7 @@ mod test {
 
         let (done, rx) = channel();
         let tx2 = tx.clone();
-        spawn(proc() {
+        spawn(move|| {
             let mut sock3 = sock3;
             match sock3.send_to(&[1], addr2) {
                 Ok(..) => { let _ = tx2.send_opt(()); }
@@ -547,11 +557,12 @@ mod test {
         let addr1 = next_test_ip4();
         let addr2 = next_test_ip4();
         let mut a = UdpSocket::bind(addr1).unwrap();
+        let a2 = UdpSocket::bind(addr2).unwrap();
 
         let (tx, rx) = channel();
         let (tx2, rx2) = channel();
-        spawn(proc() {
-            let mut a = UdpSocket::bind(addr2).unwrap();
+        spawn(move|| {
+            let mut a = a2;
             assert_eq!(a.recv_from(&mut [0]), Ok((1, addr1)));
             assert_eq!(a.send_to(&[0], addr1), Ok(()));
             rx.recv();
diff --git a/src/libstd/io/pipe.rs b/src/libstd/io/pipe.rs
index 8c20ea08863..73a893c4f2d 100644
--- a/src/libstd/io/pipe.rs
+++ b/src/libstd/io/pipe.rs
@@ -86,8 +86,8 @@ impl PipeStream {
     }
 }
 
-impl sys_common::AsFileDesc for PipeStream {
-    fn as_fd(&self) -> &sys::fs::FileDesc {
+impl sys_common::AsInner<sys::fs::FileDesc> for PipeStream {
+    fn as_inner(&self) -> &sys::fs::FileDesc {
         &*self.inner
     }
 }
@@ -123,7 +123,7 @@ mod test {
         let out = PipeStream::open(writer);
         let mut input = PipeStream::open(reader);
         let (tx, rx) = channel();
-        spawn(proc() {
+        spawn(move|| {
             let mut out = out;
             out.write(&[10]).unwrap();
             rx.recv(); // don't close the pipe until the other read has finished
diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs
index d4d24c1e12f..4a0a3936424 100644
--- a/src/libstd/io/process.rs
+++ b/src/libstd/io/process.rs
@@ -30,6 +30,7 @@ use hash::Hash;
 use std::hash::sip::SipState;
 use io::pipe::{PipeStream, PipePair};
 use path::BytesContainer;
+use thread::Thread;
 
 use sys;
 use sys::fs::FileDesc;
@@ -236,8 +237,8 @@ impl Command {
                 // if the env is currently just inheriting from the parent's,
                 // materialize the parent's env into a hashtable.
                 self.env = Some(os::env_as_bytes().into_iter()
-                                   .map(|(k, v)| (EnvKey(k.as_slice().to_c_str()),
-                                                  v.as_slice().to_c_str()))
+                                   .map(|(k, v)| (EnvKey(k.to_c_str()),
+                                                  v.to_c_str()))
                                    .collect());
                 self.env.as_mut().unwrap()
             }
@@ -460,7 +461,7 @@ pub struct ProcessOutput {
 }
 
 /// Describes what to do with a standard io stream for a child process.
-#[deriving(Clone)]
+#[deriving(Clone, Copy)]
 pub enum StdioContainer {
     /// This stream will be ignored. This is the equivalent of attaching the
     /// stream to `/dev/null`
@@ -482,7 +483,7 @@ pub enum StdioContainer {
 
 /// Describes the result of a process after it has terminated.
 /// Note that Windows have no signals, so the result is usually ExitStatus.
-#[deriving(PartialEq, Eq, Clone)]
+#[deriving(PartialEq, Eq, Clone, Copy)]
 pub enum ProcessExit {
     /// Normal termination with an exit status.
     ExitStatus(int),
@@ -689,10 +690,12 @@ impl Process {
         fn read(stream: Option<io::PipeStream>) -> Receiver<IoResult<Vec<u8>>> {
             let (tx, rx) = channel();
             match stream {
-                Some(stream) => spawn(proc() {
-                    let mut stream = stream;
-                    tx.send(stream.read_to_end())
-                }),
+                Some(stream) => {
+                    Thread::spawn(move |:| {
+                        let mut stream = stream;
+                        tx.send(stream.read_to_end())
+                    }).detach();
+                }
                 None => tx.send(Ok(Vec::new()))
             }
             rx
@@ -810,7 +813,7 @@ mod tests {
     fn stdout_works() {
         let mut cmd = Command::new("echo");
         cmd.arg("foobar").stdout(CreatePipe(false, true));
-        assert_eq!(run_output(cmd), "foobar\n".to_string());
+        assert_eq!(run_output(cmd), "foobar\n");
     }
 
     #[cfg(all(unix, not(target_os="android")))]
@@ -820,7 +823,7 @@ mod tests {
         cmd.arg("-c").arg("pwd")
            .cwd(&Path::new("/"))
            .stdout(CreatePipe(false, true));
-        assert_eq!(run_output(cmd), "/\n".to_string());
+        assert_eq!(run_output(cmd), "/\n");
     }
 
     #[cfg(all(unix, not(target_os="android")))]
@@ -835,7 +838,7 @@ mod tests {
         drop(p.stdin.take());
         let out = read_all(p.stdout.as_mut().unwrap() as &mut Reader);
         assert!(p.wait().unwrap().success());
-        assert_eq!(out, "foobar\n".to_string());
+        assert_eq!(out, "foobar\n");
     }
 
     #[cfg(not(target_os="android"))]
@@ -900,7 +903,7 @@ mod tests {
         let output_str = str::from_utf8(output.as_slice()).unwrap();
 
         assert!(status.success());
-        assert_eq!(output_str.trim().to_string(), "hello".to_string());
+        assert_eq!(output_str.trim().to_string(), "hello");
         // FIXME #7224
         if !running_on_valgrind() {
             assert_eq!(error, Vec::new());
@@ -941,7 +944,7 @@ mod tests {
         let output_str = str::from_utf8(output.as_slice()).unwrap();
 
         assert!(status.success());
-        assert_eq!(output_str.trim().to_string(), "hello".to_string());
+        assert_eq!(output_str.trim().to_string(), "hello");
         // FIXME #7224
         if !running_on_valgrind() {
             assert_eq!(error, Vec::new());
@@ -973,7 +976,7 @@ mod tests {
 
         let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap();
         let parent_dir = os::getcwd().unwrap();
-        let child_dir = Path::new(output.as_slice().trim());
+        let child_dir = Path::new(output.trim());
 
         let parent_stat = parent_dir.stat().unwrap();
         let child_stat = child_dir.stat().unwrap();
@@ -991,7 +994,7 @@ mod tests {
         let prog = pwd_cmd().cwd(&parent_dir).spawn().unwrap();
 
         let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap();
-        let child_dir = Path::new(output.as_slice().trim());
+        let child_dir = Path::new(output.trim());
 
         let parent_stat = parent_dir.stat().unwrap();
         let child_stat = child_dir.stat().unwrap();
@@ -1031,8 +1034,7 @@ mod tests {
         for &(ref k, ref v) in r.iter() {
             // don't check windows magical empty-named variables
             assert!(k.is_empty() ||
-                    output.as_slice()
-                          .contains(format!("{}={}", *k, *v).as_slice()),
+                    output.contains(format!("{}={}", *k, *v).as_slice()),
                     "output doesn't contain `{}={}`\n{}",
                     k, v, output);
         }
@@ -1050,12 +1052,10 @@ mod tests {
         for &(ref k, ref v) in r.iter() {
             // don't check android RANDOM variables
             if *k != "RANDOM".to_string() {
-                assert!(output.as_slice()
-                              .contains(format!("{}={}",
+                assert!(output.contains(format!("{}={}",
                                                 *k,
                                                 *v).as_slice()) ||
-                        output.as_slice()
-                              .contains(format!("{}=\'{}\'",
+                        output.contains(format!("{}=\'{}\'",
                                                 *k,
                                                 *v).as_slice()));
             }
@@ -1082,9 +1082,9 @@ mod tests {
 
         let prog = env_cmd().env_set_all(new_env.as_slice()).spawn().unwrap();
         let result = prog.wait_with_output().unwrap();
-        let output = String::from_utf8_lossy(result.output.as_slice()).into_string();
+        let output = String::from_utf8_lossy(result.output.as_slice()).to_string();
 
-        assert!(output.as_slice().contains("RUN_TEST_NEW_ENV=123"),
+        assert!(output.contains("RUN_TEST_NEW_ENV=123"),
                 "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output);
     }
 
@@ -1092,9 +1092,9 @@ mod tests {
     fn test_add_to_env() {
         let prog = env_cmd().env("RUN_TEST_NEW_ENV", "123").spawn().unwrap();
         let result = prog.wait_with_output().unwrap();
-        let output = String::from_utf8_lossy(result.output.as_slice()).into_string();
+        let output = String::from_utf8_lossy(result.output.as_slice()).to_string();
 
-        assert!(output.as_slice().contains("RUN_TEST_NEW_ENV=123"),
+        assert!(output.contains("RUN_TEST_NEW_ENV=123"),
                 "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output);
     }
 
@@ -1154,14 +1154,14 @@ mod tests {
     fn wait_timeout2() {
         let (tx, rx) = channel();
         let tx2 = tx.clone();
-        spawn(proc() {
+        spawn(move|| {
             let mut p = sleeper();
             p.set_timeout(Some(10));
             assert_eq!(p.wait().err().unwrap().kind, TimedOut);
             p.signal_kill().unwrap();
             tx.send(());
         });
-        spawn(proc() {
+        spawn(move|| {
             let mut p = sleeper();
             p.set_timeout(Some(10));
             assert_eq!(p.wait().err().unwrap().kind, TimedOut);
diff --git a/src/libstd/io/result.rs b/src/libstd/io/result.rs
index 305bcf9ecbc..32965d23971 100644
--- a/src/libstd/io/result.rs
+++ b/src/libstd/io/result.rs
@@ -15,7 +15,7 @@
 //! as a `Reader` without unwrapping the result first.
 
 use clone::Clone;
-use result::{Ok, Err};
+use result::Result::{Ok, Err};
 use super::{Reader, Writer, Listener, Acceptor, Seek, SeekStyle, IoResult};
 
 impl<W: Writer> Writer for IoResult<W> {
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index 7374668a69d..1c5ceaf2450 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -8,44 +8,47 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/*! Non-blocking access to stdin, stdout, and stderr.
-
-This module provides bindings to the local event loop's TTY interface, using it
-to offer synchronous but non-blocking versions of stdio. These handles can be
-inspected for information about terminal dimensions or for related information
-about the stream or terminal to which it is attached.
-
-# Example
-
-```rust
-# #![allow(unused_must_use)]
-use std::io;
-
-let mut out = io::stdout();
-out.write(b"Hello, world!");
-```
-
-*/
+//! Non-blocking access to stdin, stdout, and stderr.
+//!
+//! This module provides bindings to the local event loop's TTY interface, using it
+//! to offer synchronous but non-blocking versions of stdio. These handles can be
+//! inspected for information about terminal dimensions or for related information
+//! about the stream or terminal to which it is attached.
+//!
+//! # Example
+//!
+//! ```rust
+//! # #![allow(unused_must_use)]
+//! use std::io;
+//!
+//! let mut out = io::stdout();
+//! out.write(b"Hello, world!");
+//! ```
 
 use self::StdSource::*;
 
-use failure::local_stderr;
+use boxed::Box;
+use cell::RefCell;
+use clone::Clone;
+use failure::LOCAL_STDERR;
 use fmt;
-use io::{Reader, Writer, IoResult, IoError, OtherIoError,
+use io::{Reader, Writer, IoResult, IoError, OtherIoError, Buffer,
          standard_error, EndOfFile, LineBufferedWriter, BufferedReader};
-use iter::Iterator;
 use kinds::Send;
 use libc;
-use option::{Option, Some, None};
-use boxed::Box;
+use mem;
+use option::Option;
+use option::Option::{Some, None};
+use ops::{Deref, DerefMut, FnOnce};
+use result::Result::{Ok, Err};
+use rt;
+use slice::SliceExt;
+use str::StrExt;
+use string::String;
 use sys::{fs, tty};
-use result::{Ok, Err};
-use rustrt;
-use rustrt::local::Local;
-use rustrt::task::Task;
-use slice::SlicePrelude;
-use str::StrPrelude;
+use sync::{Arc, Mutex, MutexGuard, Once, ONCE_INIT};
 use uint;
+use vec::Vec;
 
 // And so begins the tale of acquiring a uv handle to a stdio stream on all
 // platforms in all situations. Our story begins by splitting the world into two
@@ -80,37 +83,156 @@ enum StdSource {
     File(fs::FileDesc),
 }
 
-fn src<T>(fd: libc::c_int, _readable: bool, f: |StdSource| -> T) -> T {
+fn src<T, F>(fd: libc::c_int, _readable: bool, f: F) -> T where
+    F: FnOnce(StdSource) -> T,
+{
     match tty::TTY::new(fd) {
         Ok(tty) => f(TTY(tty)),
         Err(_) => f(File(fs::FileDesc::new(fd, false))),
     }
 }
 
-local_data_key!(local_stdout: Box<Writer + Send>)
+thread_local! {
+    static LOCAL_STDOUT: RefCell<Option<Box<Writer + Send>>> = {
+        RefCell::new(None)
+    }
+}
 
-/// Creates a new non-blocking handle to the stdin of the current process.
-///
-/// The returned handled is buffered by default with a `BufferedReader`. If
-/// buffered access is not desired, the `stdin_raw` function is provided to
-/// provided unbuffered access to stdin.
+/// A synchronized wrapper around a buffered reader from stdin
+#[deriving(Clone)]
+pub struct StdinReader {
+    inner: Arc<Mutex<BufferedReader<StdReader>>>,
+}
+
+/// A guard for exclusive access to `StdinReader`'s internal `BufferedReader`.
+pub struct StdinReaderGuard<'a> {
+    inner: MutexGuard<'a, BufferedReader<StdReader>>,
+}
+
+impl<'a> Deref<BufferedReader<StdReader>> for StdinReaderGuard<'a> {
+    fn deref(&self) -> &BufferedReader<StdReader> {
+        &*self.inner
+    }
+}
+
+impl<'a> DerefMut<BufferedReader<StdReader>> for StdinReaderGuard<'a> {
+    fn deref_mut(&mut self) -> &mut BufferedReader<StdReader> {
+        &mut *self.inner
+    }
+}
+
+impl StdinReader {
+    /// Locks the `StdinReader`, granting the calling thread exclusive access
+    /// to the underlying `BufferedReader`.
+    ///
+    /// This provides access to methods like `chars` and `lines`.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// use std::io;
+    ///
+    /// for line in io::stdin().lock().lines() {
+    ///     println!("{}", line.unwrap());
+    /// }
+    /// ```
+    pub fn lock<'a>(&'a mut self) -> StdinReaderGuard<'a> {
+        StdinReaderGuard {
+            inner: self.inner.lock()
+        }
+    }
+
+    /// Like `Buffer::read_line`.
+    ///
+    /// The read is performed atomically - concurrent read calls in other
+    /// threads will not interleave with this one.
+    pub fn read_line(&mut self) -> IoResult<String> {
+        self.inner.lock().read_line()
+    }
+
+    /// Like `Buffer::read_until`.
+    ///
+    /// The read is performed atomically - concurrent read calls in other
+    /// threads will not interleave with this one.
+    pub fn read_until(&mut self, byte: u8) -> IoResult<Vec<u8>> {
+        self.inner.lock().read_until(byte)
+    }
+
+    /// Like `Buffer::read_char`.
+    ///
+    /// The read is performed atomically - concurrent read calls in other
+    /// threads will not interleave with this one.
+    pub fn read_char(&mut self) -> IoResult<char> {
+        self.inner.lock().read_char()
+    }
+}
+
+impl Reader for StdinReader {
+    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
+        self.inner.lock().read(buf)
+    }
+
+    // We have to manually delegate all of these because the default impls call
+    // read more than once and we don't want those calls to interleave (or
+    // incur the costs of repeated locking).
+
+    fn read_at_least(&mut self, min: uint, buf: &mut [u8]) -> IoResult<uint> {
+        self.inner.lock().read_at_least(min, buf)
+    }
+
+    fn push_at_least(&mut self, min: uint, len: uint, buf: &mut Vec<u8>) -> IoResult<uint> {
+        self.inner.lock().push_at_least(min, len, buf)
+    }
+
+    fn read_to_end(&mut self) -> IoResult<Vec<u8>> {
+        self.inner.lock().read_to_end()
+    }
+
+    fn read_le_uint_n(&mut self, nbytes: uint) -> IoResult<u64> {
+        self.inner.lock().read_le_uint_n(nbytes)
+    }
+
+    fn read_be_uint_n(&mut self, nbytes: uint) -> IoResult<u64> {
+        self.inner.lock().read_be_uint_n(nbytes)
+    }
+}
+
+/// Creates a new handle to the stdin of the current process.
 ///
-/// Care should be taken when creating multiple handles to the stdin of a
-/// process. Because this is a buffered reader by default, it's possible for
-/// pending input to be unconsumed in one reader and unavailable to other
-/// readers. It is recommended that only one handle at a time is created for the
-/// stdin of a process.
+/// The returned handle is a wrapper around a global `BufferedReader` shared
+/// by all threads. If buffered access is not desired, the `stdin_raw` function
+/// is provided to provided unbuffered access to stdin.
 ///
 /// See `stdout()` for more notes about this function.
-pub fn stdin() -> BufferedReader<StdReader> {
-    // The default buffer capacity is 64k, but apparently windows doesn't like
-    // 64k reads on stdin. See #13304 for details, but the idea is that on
-    // windows we use a slightly smaller buffer that's been seen to be
-    // acceptable.
-    if cfg!(windows) {
-        BufferedReader::with_capacity(8 * 1024, stdin_raw())
-    } else {
-        BufferedReader::new(stdin_raw())
+pub fn stdin() -> StdinReader {
+    // We're following the same strategy as kimundi's lazy_static library
+    static mut STDIN: *const StdinReader = 0 as *const StdinReader;
+    static ONCE: Once = ONCE_INIT;
+
+    unsafe {
+        ONCE.doit(|| {
+            // The default buffer capacity is 64k, but apparently windows doesn't like
+            // 64k reads on stdin. See #13304 for details, but the idea is that on
+            // windows we use a slightly smaller buffer that's been seen to be
+            // acceptable.
+            let stdin = if cfg!(windows) {
+                BufferedReader::with_capacity(8 * 1024, stdin_raw())
+            } else {
+                BufferedReader::new(stdin_raw())
+            };
+            let stdin = StdinReader {
+                inner: Arc::new(Mutex::new(stdin))
+            };
+            STDIN = mem::transmute(box stdin);
+
+            // Make sure to free it at exit
+            rt::at_exit(|| {
+                mem::transmute::<_, Box<StdinReader>>(STDIN);
+                STDIN = 0 as *const _;
+            });
+        });
+
+        (*STDIN).clone()
     }
 }
 
@@ -167,7 +289,10 @@ pub fn stderr_raw() -> StdWriter {
 /// Note that this does not need to be called for all new tasks; the default
 /// output handle is to the process's stdout stream.
 pub fn set_stdout(stdout: Box<Writer + Send>) -> Option<Box<Writer + Send>> {
-    local_stdout.replace(Some(stdout)).and_then(|mut s| {
+    let mut new = Some(stdout);
+    LOCAL_STDOUT.with(|slot| {
+        mem::replace(&mut *slot.borrow_mut(), new.take())
+    }).and_then(|mut s| {
         let _ = s.flush();
         Some(s)
     })
@@ -182,7 +307,10 @@ pub fn set_stdout(stdout: Box<Writer + Send>) -> Option<Box<Writer + Send>> {
 /// Note that this does not need to be called for all new tasks; the default
 /// output handle is to the process's stderr stream.
 pub fn set_stderr(stderr: Box<Writer + Send>) -> Option<Box<Writer + Send>> {
-    local_stderr.replace(Some(stderr)).and_then(|mut s| {
+    let mut new = Some(stderr);
+    LOCAL_STDERR.with(|slot| {
+        mem::replace(&mut *slot.borrow_mut(), new.take())
+    }).and_then(|mut s| {
         let _ = s.flush();
         Some(s)
     })
@@ -199,17 +327,16 @@ pub fn set_stderr(stderr: Box<Writer + Send>) -> Option<Box<Writer + Send>> {
 //      })
 //  })
 fn with_task_stdout(f: |&mut Writer| -> IoResult<()>) {
-    let result = if Local::exists(None::<Task>) {
-        let mut my_stdout = local_stdout.replace(None).unwrap_or_else(|| {
-            box stdout() as Box<Writer + Send>
-        });
-        let result = f(&mut *my_stdout);
-        local_stdout.replace(Some(my_stdout));
-        result
-    } else {
-        let mut io = rustrt::Stdout;
-        f(&mut io as &mut Writer)
-    };
+    let mut my_stdout = LOCAL_STDOUT.with(|slot| {
+        slot.borrow_mut().take()
+    }).unwrap_or_else(|| {
+        box stdout() as Box<Writer + Send>
+    });
+    let result = f(&mut *my_stdout);
+    let mut var = Some(my_stdout);
+    LOCAL_STDOUT.with(|slot| {
+        *slot.borrow_mut() = var.take();
+    });
     match result {
         Ok(()) => {}
         Err(e) => panic!("failed printing to stdout: {}", e),
@@ -399,25 +526,24 @@ mod tests {
 
         let (tx, rx) = channel();
         let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
-        spawn(proc() {
+        spawn(move|| {
             set_stdout(box w);
             println!("hello!");
         });
-        assert_eq!(r.read_to_string().unwrap(), "hello!\n".to_string());
+        assert_eq!(r.read_to_string().unwrap(), "hello!\n");
     }
 
     #[test]
     fn capture_stderr() {
-        use realstd::comm::channel;
-        use realstd::io::{ChanReader, ChanWriter, Reader};
+        use io::{ChanReader, ChanWriter, Reader};
 
         let (tx, rx) = channel();
         let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
-        spawn(proc() {
-            ::realstd::io::stdio::set_stderr(box w);
+        spawn(move|| {
+            set_stderr(box w);
             panic!("my special message");
         });
         let s = r.read_to_string().unwrap();
-        assert!(s.as_slice().contains("my special message"));
+        assert!(s.contains("my special message"));
     }
 }
diff --git a/src/libstd/io/tempfile.rs b/src/libstd/io/tempfile.rs
index a232231733d..c2b4d5a1fa9 100644
--- a/src/libstd/io/tempfile.rs
+++ b/src/libstd/io/tempfile.rs
@@ -14,14 +14,65 @@ use io::{fs, IoResult};
 use io;
 use libc;
 use ops::Drop;
-use option::{Option, None, Some};
+use option::Option;
+use option::Option::{None, Some};
 use os;
 use path::{Path, GenericPath};
-use result::{Ok, Err};
+use result::Result::{Ok, Err};
 use sync::atomic;
 
 /// A wrapper for a path to temporary directory implementing automatic
 /// scope-based deletion.
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::io::TempDir;
+///
+/// {
+///     // create a temporary directory
+///     let tmpdir = match TempDir::new("mysuffix") {
+///         Ok(dir) => dir,
+///         Err(e) => panic!("couldn't create temporary directory: {}", e)
+///     };
+///
+///     // get the path of the temporary directory without affecting the wrapper
+///     let tmppath = tmpdir.path();
+///
+///     println!("The path of temporary directory is {}", tmppath.display());
+///
+///     // the temporary directory is automatically removed when tmpdir goes
+///     // out of scope at the end of the block
+/// }
+/// {
+///     // create a temporary directory, this time using a custom path
+///     let tmpdir = match TempDir::new_in(&Path::new("/tmp/best/custom/path"), "mysuffix") {
+///         Ok(dir) => dir,
+///         Err(e) => panic!("couldn't create temporary directory: {}", e)
+///     };
+///
+///     // get the path of the temporary directory and disable automatic deletion in the wrapper
+///     let tmppath = tmpdir.into_inner();
+///
+///     println!("The path of the not-so-temporary directory is {}", tmppath.display());
+///
+///     // the temporary directory is not removed here
+///     // because the directory is detached from the wrapper
+/// }
+/// {
+///     // create a temporary directory
+///     let tmpdir = match TempDir::new("mysuffix") {
+///         Ok(dir) => dir,
+///         Err(e) => panic!("couldn't create temporary directory: {}", e)
+///     };
+///
+///     // close the temporary directory manually and check the result
+///     match tmpdir.close() {
+///         Ok(_) => println!("success!"),
+///         Err(e) => panic!("couldn't remove temporary directory: {}", e)
+///     };
+/// }
+/// ```
 pub struct TempDir {
     path: Option<Path>,
     disarmed: bool
@@ -73,11 +124,15 @@ impl TempDir {
     /// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper.
     /// This discards the wrapper so that the automatic deletion of the
     /// temporary directory is prevented.
-    pub fn unwrap(self) -> Path {
+    pub fn into_inner(self) -> Path {
         let mut tmpdir = self;
         tmpdir.path.take().unwrap()
     }
 
+    /// Deprecated, use into_inner() instead
+    #[deprecated = "renamed to into_inner()"]
+    pub fn unwrap(self) -> Path { self.into_inner() }
+
     /// Access the wrapped `std::path::Path` to the temporary directory.
     pub fn path<'a>(&'a self) -> &'a Path {
         self.path.as_ref().unwrap()
diff --git a/src/libstd/io/test.rs b/src/libstd/io/test.rs
index a153ead2a38..af56735021e 100644
--- a/src/libstd/io/test.rs
+++ b/src/libstd/io/test.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/*! Various utility functions useful for writing I/O tests */
+//! Various utility functions useful for writing I/O tests
 
 #![macro_escape]
 
@@ -95,17 +95,14 @@ pub fn raise_fd_limit() {
     unsafe { darwin_fd_limit::raise_fd_limit() }
 }
 
+/// darwin_fd_limit exists to work around an issue where launchctl on Mac OS X defaults the rlimit
+/// maxfiles to 256/unlimited. The default soft limit of 256 ends up being far too low for our
+/// multithreaded scheduler testing, depending on the number of cores available.
+///
+/// This fixes issue #7772.
 #[cfg(target_os="macos")]
 #[allow(non_camel_case_types)]
 mod darwin_fd_limit {
-    /*!
-     * darwin_fd_limit exists to work around an issue where launchctl on Mac OS X defaults the
-     * rlimit maxfiles to 256/unlimited. The default soft limit of 256 ends up being far too low
-     * for our multithreaded scheduler testing, depending on the number of cores available.
-     *
-     * This fixes issue #7772.
-     */
-
     use libc;
     type rlim_t = libc::uint64_t;
     #[repr(C)]
diff --git a/src/libstd/io/timer.rs b/src/libstd/io/timer.rs
index ec588f13478..953effe4345 100644
--- a/src/libstd/io/timer.rs
+++ b/src/libstd/io/timer.rs
@@ -8,14 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/*!
-
-Synchronous Timers
-
-This module exposes the functionality to create timers, block the current task,
-and create receivers which will receive notifications after a period of time.
-
-*/
+//! Synchronous Timers
+//!
+//! This module exposes the functionality to create timers, block the current task,
+//! and create receivers which will receive notifications after a period of time.
 
 // FIXME: These functions take Durations but only pass ms to the backend impls.
 
@@ -229,11 +225,11 @@ fn in_ms_u64(d: Duration) -> u64 {
 
 #[cfg(test)]
 mod test {
-    use super::*;
-    use time::Duration;
-    use task::spawn;
     use prelude::*;
 
+    use super::Timer;
+    use time::Duration;
+
     #[test]
     fn test_io_timer_sleep_simple() {
         let mut timer = Timer::new().unwrap();
@@ -361,7 +357,7 @@ mod test {
         let mut timer = Timer::new().unwrap();
         let timer_rx = timer.periodic(Duration::milliseconds(1000));
 
-        spawn(proc() {
+        spawn(move|| {
             let _ = timer_rx.recv_opt();
         });
 
@@ -375,7 +371,7 @@ mod test {
         let mut timer = Timer::new().unwrap();
         let timer_rx = timer.periodic(Duration::milliseconds(1000));
 
-        spawn(proc() {
+        spawn(move|| {
             let _ = timer_rx.recv_opt();
         });
 
@@ -388,7 +384,7 @@ mod test {
         let mut timer = Timer::new().unwrap();
         let timer_rx = timer.periodic(Duration::milliseconds(1000));
 
-        spawn(proc() {
+        spawn(move|| {
             let _ = timer_rx.recv_opt();
         });
 
diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs
index 4d491beb87b..18fabcbd1a2 100644
--- a/src/libstd/io/util.rs
+++ b/src/libstd/io/util.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/*! Utility implementations of Reader and Writer */
+//! Utility implementations of Reader and Writer
 
 use prelude::*;
 use cmp;
@@ -28,7 +28,11 @@ impl<R: Reader> LimitReader<R> {
     }
 
     /// Consumes the `LimitReader`, returning the underlying `Reader`.
-    pub fn unwrap(self) -> R { self.inner }
+    pub fn into_inner(self) -> R { self.inner }
+
+    /// Deprecated, use into_inner() instead
+    #[deprecated = "renamed to into_inner"]
+    pub fn unwrap(self) -> R { self.into_inner() }
 
     /// Returns the number of bytes that can be read before the `LimitReader`
     /// will return EOF.
@@ -77,6 +81,7 @@ impl<R: Buffer> Buffer for LimitReader<R> {
 }
 
 /// A `Writer` which ignores bytes written to it, like /dev/null.
+#[deriving(Copy)]
 pub struct NullWriter;
 
 impl Writer for NullWriter {
@@ -85,6 +90,7 @@ impl Writer for NullWriter {
 }
 
 /// A `Reader` which returns an infinite stream of 0 bytes, like /dev/zero.
+#[deriving(Copy)]
 pub struct ZeroReader;
 
 impl Reader for ZeroReader {
@@ -105,6 +111,7 @@ impl Buffer for ZeroReader {
 }
 
 /// A `Reader` which is always at EOF, like /dev/null.
+#[deriving(Copy)]
 pub struct NullReader;
 
 impl Reader for NullReader {
@@ -207,10 +214,14 @@ impl<R: Reader, W: Writer> TeeReader<R, W> {
 
     /// Consumes the `TeeReader`, returning the underlying `Reader` and
     /// `Writer`.
-    pub fn unwrap(self) -> (R, W) {
+    pub fn into_inner(self) -> (R, W) {
         let TeeReader { reader, writer } = self;
         (reader, writer)
     }
+
+    /// Deprecated, use into_inner() instead
+    #[deprecated = "renamed to into_inner"]
+    pub fn unwrap(self) -> (R, W) { self.into_inner() }
 }
 
 impl<R: Reader, W: Writer> Reader for TeeReader<R, W> {
@@ -265,7 +276,7 @@ impl<T: Iterator<u8>> Reader for IterReader<T> {
 
 #[cfg(test)]
 mod test {
-    use io::{MemReader, BufReader, ByRefReader};
+    use io::{MemReader, ByRefReader};
     use io;
     use boxed::Box;
     use super::*;
@@ -387,8 +398,7 @@ mod test {
 
     #[test]
     fn limit_reader_buffer() {
-        let data = "0123456789\n0123456789\n";
-        let mut r = BufReader::new(data.as_bytes());
+        let r = &mut b"0123456789\n0123456789\n";
         {
             let mut r = LimitReader::new(r.by_ref(), 3);
             assert_eq!(r.read_line(), Ok("012".to_string()));
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index b35c49efdd8..8274baeacfa 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -96,8 +96,6 @@
 
 #![crate_name = "std"]
 #![unstable]
-#![comment = "The Rust standard library"]
-#![license = "MIT/ASL2"]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -106,9 +104,9 @@
        html_playground_url = "http://play.rust-lang.org/")]
 
 #![allow(unknown_features)]
-#![feature(macro_rules, globs, linkage)]
+#![feature(macro_rules, globs, linkage, thread_local, asm)]
 #![feature(default_type_params, phase, lang_items, unsafe_destructor)]
-#![feature(import_shadowing, slicing_syntax)]
+#![feature(slicing_syntax, unboxed_closures)]
 
 // Don't link to std. We are std.
 #![no_std]
@@ -124,9 +122,7 @@ extern crate unicode;
 extern crate core;
 extern crate "collections" as core_collections;
 extern crate "rand" as core_rand;
-extern crate "sync" as core_sync;
 extern crate libc;
-extern crate rustrt;
 
 // Make std testable by not duplicating lang items. See #2912
 #[cfg(test)] extern crate "std" as realstd;
@@ -139,7 +135,6 @@ extern crate rustrt;
 // NB: These reexports are in the order they should be listed in rustdoc
 
 pub use core::any;
-pub use core::bool;
 pub use core::borrow;
 pub use core::cell;
 pub use core::clone;
@@ -154,14 +149,10 @@ pub use core::mem;
 pub use core::ptr;
 pub use core::raw;
 pub use core::simd;
-pub use core::tuple;
-// FIXME #15320: primitive documentation needs top-level modules, this
-// should be `std::tuple::unit`.
-pub use core::unit;
 pub use core::result;
 pub use core::option;
 
-pub use alloc::boxed;
+#[cfg(not(test))] pub use alloc::boxed;
 pub use alloc::rc;
 
 pub use core_collections::slice;
@@ -169,13 +160,8 @@ pub use core_collections::str;
 pub use core_collections::string;
 pub use core_collections::vec;
 
-pub use rustrt::c_str;
-pub use rustrt::local_data;
-
 pub use unicode::char;
 
-pub use core_sync::comm;
-
 /* Exported macros */
 
 pub mod macros;
@@ -209,35 +195,38 @@ pub mod prelude;
 #[path = "num/f32.rs"]   pub mod f32;
 #[path = "num/f64.rs"]   pub mod f64;
 
-pub mod rand;
-
 pub mod ascii;
-
-pub mod time;
+pub mod thunk;
 
 /* Common traits */
 
 pub mod error;
 pub mod num;
 
+/* Runtime and platform support */
+
+pub mod thread_local;
+pub mod c_str;
+pub mod c_vec;
+pub mod dynamic_lib;
+pub mod fmt;
+pub mod io;
+pub mod os;
+pub mod path;
+pub mod rand;
+pub mod time;
+
 /* Common data structures */
 
 pub mod collections;
 pub mod hash;
 
-/* Tasks and communication */
+/* Threads and communication */
 
 pub mod task;
+pub mod thread;
 pub mod sync;
-
-/* Runtime and platform support */
-
-pub mod c_vec;
-pub mod dynamic_lib;
-pub mod os;
-pub mod io;
-pub mod path;
-pub mod fmt;
+pub mod comm;
 
 #[cfg(unix)]
 #[path = "sys/unix/mod.rs"] mod sys;
@@ -249,6 +238,12 @@ pub mod fmt;
 pub mod rt;
 mod failure;
 
+// Documentation for primitive types
+
+mod bool;
+mod unit;
+mod tuple;
+
 // A curious inner-module that's not exported that contains the binding
 // 'std' so that macro-expanded references to std::error and such
 // can be resolved within libstd.
@@ -263,10 +258,12 @@ mod std {
     pub use error; // used for try!()
     pub use fmt; // used for any formatting strings
     pub use io; // used for println!()
-    pub use local_data; // used for local_data_key!()
     pub use option; // used for bitflags!{}
     pub use rt; // used for panic!()
     pub use vec; // used for vec![]
+    pub use cell; // used for tls!
+    pub use thread_local; // used for thread_local!
+    pub use kinds; // used for tls!
 
     // The test runner calls ::std::os::args() but really wants realstd
     #[cfg(test)] pub use realstd::os as os;
@@ -276,4 +273,5 @@ mod std {
     pub use slice;
 
     pub use boxed; // used for vec![]
+
 }
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index 18c109d92a0..3d03b5324b9 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -37,7 +37,7 @@
 /// panic!("this is a {} {message}", "fancy", message = "message");
 /// ```
 #[macro_export]
-macro_rules! panic(
+macro_rules! panic {
     () => ({
         panic!("explicit panic")
     });
@@ -70,7 +70,7 @@ macro_rules! panic(
         }
         format_args!(_run_fmt, $fmt, $($arg)*)
     });
-)
+}
 
 /// Ensure that a boolean expression is `true` at runtime.
 ///
@@ -93,7 +93,7 @@ macro_rules! panic(
 /// assert!(a + b == 30, "a = {}, b = {}", a, b);
 /// ```
 #[macro_export]
-macro_rules! assert(
+macro_rules! assert {
     ($cond:expr) => (
         if !$cond {
             panic!(concat!("assertion failed: ", stringify!($cond)))
@@ -104,7 +104,7 @@ macro_rules! assert(
             panic!($($arg),+)
         }
     );
-)
+}
 
 /// Asserts that two expressions are equal to each other, testing equality in
 /// both directions.
@@ -119,20 +119,20 @@ macro_rules! assert(
 /// assert_eq!(a, b);
 /// ```
 #[macro_export]
-macro_rules! assert_eq(
-    ($given:expr , $expected:expr) => ({
-        match (&($given), &($expected)) {
-            (given_val, expected_val) => {
+macro_rules! assert_eq {
+    ($left:expr , $right:expr) => ({
+        match (&($left), &($right)) {
+            (left_val, right_val) => {
                 // check both directions of equality....
-                if !((*given_val == *expected_val) &&
-                     (*expected_val == *given_val)) {
+                if !((*left_val == *right_val) &&
+                     (*right_val == *left_val)) {
                     panic!("assertion failed: `(left == right) && (right == left)` \
-                           (left: `{}`, right: `{}`)", *given_val, *expected_val)
+                           (left: `{}`, right: `{}`)", *left_val, *right_val)
                 }
             }
         }
     })
-)
+}
 
 /// Ensure that a boolean expression is `true` at runtime.
 ///
@@ -160,9 +160,9 @@ macro_rules! assert_eq(
 /// debug_assert!(a + b == 30, "a = {}, b = {}", a, b);
 /// ```
 #[macro_export]
-macro_rules! debug_assert(
+macro_rules! debug_assert {
     ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); })
-)
+}
 
 /// Asserts that two expressions are equal to each other, testing equality in
 /// both directions.
@@ -182,35 +182,51 @@ macro_rules! debug_assert(
 /// debug_assert_eq!(a, b);
 /// ```
 #[macro_export]
-macro_rules! debug_assert_eq(
+macro_rules! debug_assert_eq {
     ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert_eq!($($arg)*); })
-)
+}
 
-/// A utility macro for indicating unreachable code. It will panic if
-/// executed. This is occasionally useful to put after loops that never
-/// terminate normally, but instead directly return from a function.
+/// A utility macro for indicating unreachable code.
 ///
-/// # Example
+/// This is useful any time that the compiler can't determine that some code is unreachable. For
+/// example:
+///
+/// * Match arms with guard conditions.
+/// * Loops that dynamically terminate.
+/// * Iterators that dynamically terminate.
+///
+/// # Panics
+///
+/// This will always panic.
+///
+/// # Examples
 ///
-/// ```{.rust}
-/// struct Item { weight: uint }
-///
-/// fn choose_weighted_item(v: &[Item]) -> Item {
-///     assert!(!v.is_empty());
-///     let mut so_far = 0u;
-///     for item in v.iter() {
-///         so_far += item.weight;
-///         if so_far > 100 {
-///             return *item;
-///         }
+/// Match arms:
+///
+/// ```rust
+/// fn foo(x: Option<int>) {
+///     match x {
+///         Some(n) if n >= 0 => println!("Some(Non-negative)"),
+///         Some(n) if n <  0 => println!("Some(Negative)"),
+///         Some(_)           => unreachable!(), // compile error if commented out
+///         None              => println!("None")
+///     }
+/// }
+/// ```
+///
+/// Iterators:
+///
+/// ```rust
+/// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3
+///     for i in std::iter::count(0_u32, 1) {
+///         if 3*i < i { panic!("u32 overflow"); }
+///         if x < 3*i { return i-1; }
 ///     }
-///     // The above loop always returns, so we must hint to the
-///     // type checker that it isn't possible to get down here
 ///     unreachable!();
 /// }
 /// ```
 #[macro_export]
-macro_rules! unreachable(
+macro_rules! unreachable {
     () => ({
         panic!("internal error: entered unreachable code")
     });
@@ -220,14 +236,14 @@ macro_rules! unreachable(
     ($fmt:expr, $($arg:tt)*) => ({
         panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
     });
-)
+}
 
 /// A standardised placeholder for marking unfinished code. It panics with the
 /// message `"not yet implemented"` when executed.
 #[macro_export]
-macro_rules! unimplemented(
+macro_rules! unimplemented {
     () => (panic!("not yet implemented"))
-)
+}
 
 /// Use the syntax described in `std::fmt` to create a value of type `String`.
 /// See `std::fmt` for more information.
@@ -241,11 +257,11 @@ macro_rules! unimplemented(
 /// ```
 #[macro_export]
 #[stable]
-macro_rules! format(
+macro_rules! format {
     ($($arg:tt)*) => (
         format_args!(::std::fmt::format, $($arg)*)
     )
-)
+}
 
 /// Use the `format!` syntax to write data into a buffer of type `&mut Writer`.
 /// See `std::fmt` for more information.
@@ -261,30 +277,30 @@ macro_rules! format(
 /// ```
 #[macro_export]
 #[stable]
-macro_rules! write(
+macro_rules! write {
     ($dst:expr, $($arg:tt)*) => ({
         let dst = &mut *$dst;
         format_args!(|args| { dst.write_fmt(args) }, $($arg)*)
     })
-)
+}
 
 /// Equivalent to the `write!` macro, except that a newline is appended after
 /// the message is written.
 #[macro_export]
 #[stable]
-macro_rules! writeln(
+macro_rules! writeln {
     ($dst:expr, $fmt:expr $($arg:tt)*) => (
         write!($dst, concat!($fmt, "\n") $($arg)*)
     )
-)
+}
 
 /// Equivalent to the `println!` macro except that a newline is not printed at
 /// the end of the message.
 #[macro_export]
 #[stable]
-macro_rules! print(
+macro_rules! print {
     ($($arg:tt)*) => (format_args!(::std::io::stdio::print_args, $($arg)*))
-)
+}
 
 /// Macro for printing to a task's stdout handle.
 ///
@@ -300,55 +316,33 @@ macro_rules! print(
 /// ```
 #[macro_export]
 #[stable]
-macro_rules! println(
+macro_rules! println {
     ($($arg:tt)*) => (format_args!(::std::io::stdio::println_args, $($arg)*))
-)
-
-/// Declare a task-local key with a specific type.
-///
-/// # Example
-///
-/// ```
-/// local_data_key!(my_integer: int)
-///
-/// my_integer.replace(Some(2));
-/// println!("{}", my_integer.get().map(|a| *a));
-/// ```
-#[macro_export]
-macro_rules! local_data_key(
-    ($name:ident: $ty:ty) => (
-        #[allow(non_upper_case_globals)]
-        static $name: ::std::local_data::Key<$ty> = &::std::local_data::KeyValueKey;
-    );
-    (pub $name:ident: $ty:ty) => (
-        #[allow(non_upper_case_globals)]
-        pub static $name: ::std::local_data::Key<$ty> = &::std::local_data::KeyValueKey;
-    );
-)
+}
 
 /// Helper macro for unwrapping `Result` values while returning early with an
 /// error if the value of the expression is `Err`. For more information, see
 /// `std::io`.
 #[macro_export]
-macro_rules! try (
+macro_rules! try {
     ($expr:expr) => ({
         match $expr {
             Ok(val) => val,
             Err(err) => return Err(::std::error::FromError::from_error(err))
         }
     })
-)
+}
 
 /// Create a `std::vec::Vec` containing the arguments.
 #[macro_export]
-macro_rules! vec[
+macro_rules! vec {
     ($($x:expr),*) => ({
-        use std::slice::BoxedSlicePrelude;
+        use std::slice::BoxedSliceExt;
         let xs: ::std::boxed::Box<[_]> = box [$($x),*];
         xs.into_vec()
     });
     ($($x:expr,)*) => (vec![$($x),*])
-]
+}
 
 /// A macro to select an event from a number of receivers.
 ///
@@ -359,13 +353,15 @@ macro_rules! vec[
 /// # Example
 ///
 /// ```
+/// use std::thread::Thread;
+///
 /// let (tx1, rx1) = channel();
 /// let (tx2, rx2) = channel();
 /// # fn long_running_task() {}
 /// # fn calculate_the_answer() -> int { 42i }
 ///
-/// spawn(proc() { long_running_task(); tx1.send(()) });
-/// spawn(proc() { tx2.send(calculate_the_answer()) });
+/// Thread::spawn(move|| { long_running_task(); tx1.send(()) }).detach();
+/// Thread::spawn(move|| { tx2.send(calculate_the_answer()) }).detach();
 ///
 /// select! (
 ///     () = rx1.recv() => println!("the long running task finished first"),
@@ -400,11 +396,11 @@ macro_rules! select {
 // uses. To get around this difference, we redefine the log!() macro here to be
 // just a dumb version of what it should be.
 #[cfg(test)]
-macro_rules! log (
+macro_rules! log {
     ($lvl:expr, $($args:tt)*) => (
         if log_enabled!($lvl) { println!($($args)*) }
     )
-)
+}
 
 /// Built-in macros to the compiler itself.
 ///
@@ -436,9 +432,9 @@ pub mod builtin {
     /// }, "hello {}", "world");
     /// ```
     #[macro_export]
-    macro_rules! format_args( ($closure:expr, $fmt:expr $($args:tt)*) => ({
+    macro_rules! format_args { ($closure:expr, $fmt:expr $($args:tt)*) => ({
         /* compiler built-in */
-    }) )
+    }) }
 
     /// Inspect an environment variable at compile time.
     ///
@@ -456,7 +452,7 @@ pub mod builtin {
     /// println!("the $PATH variable at the time of compiling was: {}", path);
     /// ```
     #[macro_export]
-    macro_rules! env( ($name:expr) => ({ /* compiler built-in */ }) )
+    macro_rules! env { ($name:expr) => ({ /* compiler built-in */ }) }
 
     /// Optionally inspect an environment variable at compile time.
     ///
@@ -475,7 +471,7 @@ pub mod builtin {
     /// println!("the secret key might be: {}", key);
     /// ```
     #[macro_export]
-    macro_rules! option_env( ($name:expr) => ({ /* compiler built-in */ }) )
+    macro_rules! option_env { ($name:expr) => ({ /* compiler built-in */ }) }
 
     /// Concatenate literals into a static byte slice.
     ///
@@ -495,7 +491,7 @@ pub mod builtin {
     /// assert_eq!(rust[4], 255);
     /// ```
     #[macro_export]
-    macro_rules! bytes( ($($e:expr),*) => ({ /* compiler built-in */ }) )
+    macro_rules! bytes { ($($e:expr),*) => ({ /* compiler built-in */ }) }
 
     /// Concatenate identifiers into one identifier.
     ///
@@ -519,7 +515,9 @@ pub mod builtin {
     /// # }
     /// ```
     #[macro_export]
-    macro_rules! concat_idents( ($($e:ident),*) => ({ /* compiler built-in */ }) )
+    macro_rules! concat_idents {
+        ($($e:ident),*) => ({ /* compiler built-in */ })
+    }
 
     /// Concatenates literals into a static string slice.
     ///
@@ -537,7 +535,7 @@ pub mod builtin {
     /// assert_eq!(s, "test10btrue");
     /// ```
     #[macro_export]
-    macro_rules! concat( ($($e:expr),*) => ({ /* compiler built-in */ }) )
+    macro_rules! concat { ($($e:expr),*) => ({ /* compiler built-in */ }) }
 
     /// A macro which expands to the line number on which it was invoked.
     ///
@@ -552,7 +550,7 @@ pub mod builtin {
     /// println!("defined on line: {}", current_line);
     /// ```
     #[macro_export]
-    macro_rules! line( () => ({ /* compiler built-in */ }) )
+    macro_rules! line { () => ({ /* compiler built-in */ }) }
 
     /// A macro which expands to the column number on which it was invoked.
     ///
@@ -567,7 +565,7 @@ pub mod builtin {
     /// println!("defined on column: {}", current_col);
     /// ```
     #[macro_export]
-    macro_rules! column( () => ({ /* compiler built-in */ }) )
+    macro_rules! column { () => ({ /* compiler built-in */ }) }
 
     /// A macro which expands to the file name from which it was invoked.
     ///
@@ -583,7 +581,7 @@ pub mod builtin {
     /// println!("defined in file: {}", this_file);
     /// ```
     #[macro_export]
-    macro_rules! file( () => ({ /* compiler built-in */ }) )
+    macro_rules! file { () => ({ /* compiler built-in */ }) }
 
     /// A macro which stringifies its argument.
     ///
@@ -598,7 +596,7 @@ pub mod builtin {
     /// assert_eq!(one_plus_one, "1 + 1");
     /// ```
     #[macro_export]
-    macro_rules! stringify( ($t:tt) => ({ /* compiler built-in */ }) )
+    macro_rules! stringify { ($t:tt) => ({ /* compiler built-in */ }) }
 
     /// Includes a utf8-encoded file as a string.
     ///
@@ -612,7 +610,7 @@ pub mod builtin {
     /// let secret_key = include_str!("secret-key.ascii");
     /// ```
     #[macro_export]
-    macro_rules! include_str( ($file:expr) => ({ /* compiler built-in */ }) )
+    macro_rules! include_str { ($file:expr) => ({ /* compiler built-in */ }) }
 
     /// Includes a file as a byte slice.
     ///
@@ -626,7 +624,7 @@ pub mod builtin {
     /// let secret_key = include_bin!("secret-key.bin");
     /// ```
     #[macro_export]
-    macro_rules! include_bin( ($file:expr) => ({ /* compiler built-in */ }) )
+    macro_rules! include_bin { ($file:expr) => ({ /* compiler built-in */ }) }
 
     /// Expands to a string that represents the current module path.
     ///
@@ -646,7 +644,7 @@ pub mod builtin {
     /// test::foo();
     /// ```
     #[macro_export]
-    macro_rules! module_path( () => ({ /* compiler built-in */ }) )
+    macro_rules! module_path { () => ({ /* compiler built-in */ }) }
 
     /// Boolean evaluation of configuration flags.
     ///
@@ -667,5 +665,5 @@ pub mod builtin {
     /// };
     /// ```
     #[macro_export]
-    macro_rules! cfg( ($cfg:tt) => ({ /* compiler built-in */ }) )
+    macro_rules! cfg { ($cfg:tt) => ({ /* compiler built-in */ }) }
 }
diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs
index 9aac857bb65..1f76382ce8a 100644
--- a/src/libstd/num/f32.rs
+++ b/src/libstd/num/f32.rs
@@ -21,6 +21,9 @@ use intrinsics;
 use libc::c_int;
 use num::{Float, FloatMath};
 use num::strconv;
+use num::strconv::ExponentFormat::{ExpNone, ExpDec};
+use num::strconv::SignificantDigits::{DigAll, DigMax, DigExact};
+use num::strconv::SignFormat::SignNeg;
 
 pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON, MIN_VALUE};
 pub use core::f32::{MIN_POS_VALUE, MAX_VALUE, MIN_EXP, MAX_EXP, MIN_10_EXP};
@@ -252,7 +255,7 @@ impl FloatMath for f32 {
 #[experimental = "may be removed or relocated"]
 pub fn to_string(num: f32) -> String {
     let (r, _) = strconv::float_to_str_common(
-        num, 10u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false);
+        num, 10u, true, SignNeg, DigAll, ExpNone, false);
     r
 }
 
@@ -265,7 +268,7 @@ pub fn to_string(num: f32) -> String {
 #[experimental = "may be removed or relocated"]
 pub fn to_str_hex(num: f32) -> String {
     let (r, _) = strconv::float_to_str_common(
-        num, 16u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false);
+        num, 16u, true, SignNeg, DigAll, ExpNone, false);
     r
 }
 
@@ -279,8 +282,7 @@ pub fn to_str_hex(num: f32) -> String {
 #[inline]
 #[experimental = "may be removed or relocated"]
 pub fn to_str_radix_special(num: f32, rdx: uint) -> (String, bool) {
-    strconv::float_to_str_common(num, rdx, true,
-                           strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false)
+    strconv::float_to_str_common(num, rdx, true, SignNeg, DigAll, ExpNone, false)
 }
 
 /// Converts a float to a string with exactly the number of
@@ -294,7 +296,7 @@ pub fn to_str_radix_special(num: f32, rdx: uint) -> (String, bool) {
 #[experimental = "may be removed or relocated"]
 pub fn to_str_exact(num: f32, dig: uint) -> String {
     let (r, _) = strconv::float_to_str_common(
-        num, 10u, true, strconv::SignNeg, strconv::DigExact(dig), strconv::ExpNone, false);
+        num, 10u, true, SignNeg, DigExact(dig), ExpNone, false);
     r
 }
 
@@ -309,7 +311,7 @@ pub fn to_str_exact(num: f32, dig: uint) -> String {
 #[experimental = "may be removed or relocated"]
 pub fn to_str_digits(num: f32, dig: uint) -> String {
     let (r, _) = strconv::float_to_str_common(
-        num, 10u, true, strconv::SignNeg, strconv::DigMax(dig), strconv::ExpNone, false);
+        num, 10u, true, SignNeg, DigMax(dig), ExpNone, false);
     r
 }
 
@@ -325,7 +327,7 @@ pub fn to_str_digits(num: f32, dig: uint) -> String {
 #[experimental = "may be removed or relocated"]
 pub fn to_str_exp_exact(num: f32, dig: uint, upper: bool) -> String {
     let (r, _) = strconv::float_to_str_common(
-        num, 10u, true, strconv::SignNeg, strconv::DigExact(dig), strconv::ExpDec, upper);
+        num, 10u, true, SignNeg, DigExact(dig), ExpDec, upper);
     r
 }
 
@@ -341,7 +343,7 @@ pub fn to_str_exp_exact(num: f32, dig: uint, upper: bool) -> String {
 #[experimental = "may be removed or relocated"]
 pub fn to_str_exp_digits(num: f32, dig: uint, upper: bool) -> String {
     let (r, _) = strconv::float_to_str_common(
-        num, 10u, true, strconv::SignNeg, strconv::DigMax(dig), strconv::ExpDec, upper);
+        num, 10u, true, SignNeg, DigMax(dig), ExpDec, upper);
     r
 }
 
@@ -349,7 +351,7 @@ pub fn to_str_exp_digits(num: f32, dig: uint, upper: bool) -> String {
 mod tests {
     use f32::*;
     use num::*;
-    use num;
+    use num::FpCategory as Fp;
 
     #[test]
     fn test_min_nan() {
@@ -364,8 +366,8 @@ mod tests {
     }
 
     #[test]
-    fn test_num() {
-        num::test_num(10f32, 2f32);
+    fn test_num_f32() {
+        test_num(10f32, 2f32);
     }
 
     #[test]
@@ -619,14 +621,14 @@ mod tests {
         let neg_inf: f32 = Float::neg_infinity();
         let zero: f32 = Float::zero();
         let neg_zero: f32 = Float::neg_zero();
-        assert_eq!(nan.classify(), FPNaN);
-        assert_eq!(inf.classify(), FPInfinite);
-        assert_eq!(neg_inf.classify(), FPInfinite);
-        assert_eq!(zero.classify(), FPZero);
-        assert_eq!(neg_zero.classify(), FPZero);
-        assert_eq!(1f32.classify(), FPNormal);
-        assert_eq!(1e-37f32.classify(), FPNormal);
-        assert_eq!(1e-38f32.classify(), FPSubnormal);
+        assert_eq!(nan.classify(), Fp::Nan);
+        assert_eq!(inf.classify(), Fp::Infinite);
+        assert_eq!(neg_inf.classify(), Fp::Infinite);
+        assert_eq!(zero.classify(), Fp::Zero);
+        assert_eq!(neg_zero.classify(), Fp::Zero);
+        assert_eq!(1f32.classify(), Fp::Normal);
+        assert_eq!(1e-37f32.classify(), Fp::Normal);
+        assert_eq!(1e-38f32.classify(), Fp::Subnormal);
     }
 
     #[test]
@@ -671,8 +673,8 @@ mod tests {
         let inf: f32 = Float::infinity();
         let neg_inf: f32 = Float::neg_infinity();
         let nan: f32 = Float::nan();
-        assert_eq!(match inf.frexp() { (x, _) => x }, inf)
-        assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf)
+        assert_eq!(match inf.frexp() { (x, _) => x }, inf);
+        assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf);
         assert!(match nan.frexp() { (x, _) => x.is_nan() })
     }
 
diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs
index 29ccfe512b9..221ecf62c05 100644
--- a/src/libstd/num/f64.rs
+++ b/src/libstd/num/f64.rs
@@ -20,6 +20,9 @@ use intrinsics;
 use libc::c_int;
 use num::{Float, FloatMath};
 use num::strconv;
+use num::strconv::ExponentFormat::{ExpNone, ExpDec};
+use num::strconv::SignificantDigits::{DigAll, DigMax, DigExact};
+use num::strconv::SignFormat::SignNeg;
 
 pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON, MIN_VALUE};
 pub use core::f64::{MIN_POS_VALUE, MAX_VALUE, MIN_EXP, MAX_EXP, MIN_10_EXP};
@@ -260,7 +263,7 @@ impl FloatMath for f64 {
 #[experimental = "may be removed or relocated"]
 pub fn to_string(num: f64) -> String {
     let (r, _) = strconv::float_to_str_common(
-        num, 10u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false);
+        num, 10u, true, SignNeg, DigAll, ExpNone, false);
     r
 }
 
@@ -273,7 +276,7 @@ pub fn to_string(num: f64) -> String {
 #[experimental = "may be removed or relocated"]
 pub fn to_str_hex(num: f64) -> String {
     let (r, _) = strconv::float_to_str_common(
-        num, 16u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false);
+        num, 16u, true, SignNeg, DigAll, ExpNone, false);
     r
 }
 
@@ -287,8 +290,7 @@ pub fn to_str_hex(num: f64) -> String {
 #[inline]
 #[experimental = "may be removed or relocated"]
 pub fn to_str_radix_special(num: f64, rdx: uint) -> (String, bool) {
-    strconv::float_to_str_common(num, rdx, true,
-                           strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false)
+    strconv::float_to_str_common(num, rdx, true, SignNeg, DigAll, ExpNone, false)
 }
 
 /// Converts a float to a string with exactly the number of
@@ -302,7 +304,7 @@ pub fn to_str_radix_special(num: f64, rdx: uint) -> (String, bool) {
 #[experimental = "may be removed or relocated"]
 pub fn to_str_exact(num: f64, dig: uint) -> String {
     let (r, _) = strconv::float_to_str_common(
-        num, 10u, true, strconv::SignNeg, strconv::DigExact(dig), strconv::ExpNone, false);
+        num, 10u, true, SignNeg, DigExact(dig), ExpNone, false);
     r
 }
 
@@ -317,7 +319,7 @@ pub fn to_str_exact(num: f64, dig: uint) -> String {
 #[experimental = "may be removed or relocated"]
 pub fn to_str_digits(num: f64, dig: uint) -> String {
     let (r, _) = strconv::float_to_str_common(
-        num, 10u, true, strconv::SignNeg, strconv::DigMax(dig), strconv::ExpNone, false);
+        num, 10u, true, SignNeg, DigMax(dig), ExpNone, false);
     r
 }
 
@@ -333,7 +335,7 @@ pub fn to_str_digits(num: f64, dig: uint) -> String {
 #[experimental = "may be removed or relocated"]
 pub fn to_str_exp_exact(num: f64, dig: uint, upper: bool) -> String {
     let (r, _) = strconv::float_to_str_common(
-        num, 10u, true, strconv::SignNeg, strconv::DigExact(dig), strconv::ExpDec, upper);
+        num, 10u, true, SignNeg, DigExact(dig), ExpDec, upper);
     r
 }
 
@@ -349,7 +351,7 @@ pub fn to_str_exp_exact(num: f64, dig: uint, upper: bool) -> String {
 #[experimental = "may be removed or relocated"]
 pub fn to_str_exp_digits(num: f64, dig: uint, upper: bool) -> String {
     let (r, _) = strconv::float_to_str_common(
-        num, 10u, true, strconv::SignNeg, strconv::DigMax(dig), strconv::ExpDec, upper);
+        num, 10u, true, SignNeg, DigMax(dig), ExpDec, upper);
     r
 }
 
@@ -357,7 +359,7 @@ pub fn to_str_exp_digits(num: f64, dig: uint, upper: bool) -> String {
 mod tests {
     use f64::*;
     use num::*;
-    use num;
+    use num::FpCategory as Fp;
 
     #[test]
     fn test_min_nan() {
@@ -372,8 +374,8 @@ mod tests {
     }
 
     #[test]
-    fn test_num() {
-        num::test_num(10f64, 2f64);
+    fn test_num_f64() {
+        test_num(10f64, 2f64);
     }
 
     #[test]
@@ -622,13 +624,13 @@ mod tests {
         let neg_inf: f64 = Float::neg_infinity();
         let zero: f64 = Float::zero();
         let neg_zero: f64 = Float::neg_zero();
-        assert_eq!(nan.classify(), FPNaN);
-        assert_eq!(inf.classify(), FPInfinite);
-        assert_eq!(neg_inf.classify(), FPInfinite);
-        assert_eq!(zero.classify(), FPZero);
-        assert_eq!(neg_zero.classify(), FPZero);
-        assert_eq!(1e-307f64.classify(), FPNormal);
-        assert_eq!(1e-308f64.classify(), FPSubnormal);
+        assert_eq!(nan.classify(), Fp::Nan);
+        assert_eq!(inf.classify(), Fp::Infinite);
+        assert_eq!(neg_inf.classify(), Fp::Infinite);
+        assert_eq!(zero.classify(), Fp::Zero);
+        assert_eq!(neg_zero.classify(), Fp::Zero);
+        assert_eq!(1e-307f64.classify(), Fp::Normal);
+        assert_eq!(1e-308f64.classify(), Fp::Subnormal);
     }
 
     #[test]
@@ -673,8 +675,8 @@ mod tests {
         let inf: f64 = Float::infinity();
         let neg_inf: f64 = Float::neg_infinity();
         let nan: f64 = Float::nan();
-        assert_eq!(match inf.frexp() { (x, _) => x }, inf)
-        assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf)
+        assert_eq!(match inf.frexp() { (x, _) => x }, inf);
+        assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf);
         assert!(match nan.frexp() { (x, _) => x.is_nan() })
     }
 
diff --git a/src/libstd/num/float_macros.rs b/src/libstd/num/float_macros.rs
index 4b3727ead61..fd00f15662a 100644
--- a/src/libstd/num/float_macros.rs
+++ b/src/libstd/num/float_macros.rs
@@ -12,11 +12,11 @@
 #![macro_escape]
 #![doc(hidden)]
 
-macro_rules! assert_approx_eq(
+macro_rules! assert_approx_eq {
     ($a:expr, $b:expr) => ({
         use num::Float;
         let (a, b) = (&$a, &$b);
         assert!((*a - *b).abs() < 1.0e-6,
                 "{} is not approximately equal to {}", *a, *b);
     })
-)
+}
diff --git a/src/libstd/num/i16.rs b/src/libstd/num/i16.rs
index 333d1d7df0b..367147b84be 100644
--- a/src/libstd/num/i16.rs
+++ b/src/libstd/num/i16.rs
@@ -15,4 +15,4 @@
 
 pub use core::i16::{BITS, BYTES, MIN, MAX};
 
-int_module!(i16)
+int_module! { i16 }
diff --git a/src/libstd/num/i32.rs b/src/libstd/num/i32.rs
index 44b5397bf74..19fb40c9644 100644
--- a/src/libstd/num/i32.rs
+++ b/src/libstd/num/i32.rs
@@ -15,4 +15,4 @@
 
 pub use core::i32::{BITS, BYTES, MIN, MAX};
 
-int_module!(i32)
+int_module! { i32 }
diff --git a/src/libstd/num/i64.rs b/src/libstd/num/i64.rs
index de6fa0d3ef8..2379b03c64f 100644
--- a/src/libstd/num/i64.rs
+++ b/src/libstd/num/i64.rs
@@ -15,4 +15,4 @@
 
 pub use core::i64::{BITS, BYTES, MIN, MAX};
 
-int_module!(i64)
+int_module! { i64 }
diff --git a/src/libstd/num/i8.rs b/src/libstd/num/i8.rs
index 3b9fbcb768b..a09ceefc6a0 100644
--- a/src/libstd/num/i8.rs
+++ b/src/libstd/num/i8.rs
@@ -15,4 +15,4 @@
 
 pub use core::i8::{BITS, BYTES, MIN, MAX};
 
-int_module!(i8)
+int_module! { i8 }
diff --git a/src/libstd/num/int.rs b/src/libstd/num/int.rs
index 36c021efe0a..9ccb1544fdc 100644
--- a/src/libstd/num/int.rs
+++ b/src/libstd/num/int.rs
@@ -10,9 +10,9 @@
 
 //! Operations and constants for architecture-sized signed integers (`int` type)
 
-#![unstable]
+#![stable]
 #![doc(primitive = "int")]
 
 pub use core::int::{BITS, BYTES, MIN, MAX};
 
-int_module!(int)
+int_module! { int }
diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs
index 2f1162d28e5..fce150c4ad1 100644
--- a/src/libstd/num/int_macros.rs
+++ b/src/libstd/num/int_macros.rs
@@ -12,6 +12,6 @@
 #![macro_escape]
 #![doc(hidden)]
 
-macro_rules! int_module (($T:ty) => (
+macro_rules! int_module { ($T:ty) => (
 
-))
+) }
diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs
index a15e71b4a2a..7c8763979bb 100644
--- a/src/libstd/num/mod.rs
+++ b/src/libstd/num/mod.rs
@@ -19,6 +19,7 @@
 #[cfg(test)] use cmp::PartialEq;
 #[cfg(test)] use fmt::Show;
 #[cfg(test)] use ops::{Add, Sub, Mul, Div, Rem};
+#[cfg(test)] use kinds::Copy;
 
 pub use core::num::{Num, div_rem, Zero, zero, One, one};
 pub use core::num::{Unsigned, pow, Bounded};
@@ -30,8 +31,7 @@ pub use core::num::{from_int, from_i8, from_i16, from_i32, from_i64};
 pub use core::num::{from_uint, from_u8, from_u16, from_u32, from_u64};
 pub use core::num::{from_f32, from_f64};
 pub use core::num::{FromStrRadix, from_str_radix};
-pub use core::num::{FPCategory, FPNaN, FPInfinite, FPZero, FPSubnormal};
-pub use core::num::{FPNormal, Float};
+pub use core::num::{FpCategory, Float};
 
 #[experimental = "may be removed or relocated"]
 pub mod strconv;
@@ -130,18 +130,19 @@ pub fn test_num<T>(ten: T, two: T) where
      + Add<T, T> + Sub<T, T>
      + Mul<T, T> + Div<T, T>
      + Rem<T, T> + Show
+     + Copy
 {
-    assert_eq!(ten.add(&two),  cast(12i).unwrap());
-    assert_eq!(ten.sub(&two),  cast(8i).unwrap());
-    assert_eq!(ten.mul(&two),  cast(20i).unwrap());
-    assert_eq!(ten.div(&two),  cast(5i).unwrap());
-    assert_eq!(ten.rem(&two),  cast(0i).unwrap());
-
-    assert_eq!(ten.add(&two),  ten + two);
-    assert_eq!(ten.sub(&two),  ten - two);
-    assert_eq!(ten.mul(&two),  ten * two);
-    assert_eq!(ten.div(&two),  ten / two);
-    assert_eq!(ten.rem(&two),  ten % two);
+    assert_eq!(ten.add(two),  cast(12i).unwrap());
+    assert_eq!(ten.sub(two),  cast(8i).unwrap());
+    assert_eq!(ten.mul(two),  cast(20i).unwrap());
+    assert_eq!(ten.div(two),  cast(5i).unwrap());
+    assert_eq!(ten.rem(two),  cast(0i).unwrap());
+
+    assert_eq!(ten.add(two),  ten + two);
+    assert_eq!(ten.sub(two),  ten - two);
+    assert_eq!(ten.mul(two),  ten * two);
+    assert_eq!(ten.div(two),  ten / two);
+    assert_eq!(ten.rem(two),  ten % two);
 }
 
 #[cfg(test)]
@@ -159,7 +160,7 @@ mod tests {
     use u64;
     use uint;
 
-    macro_rules! test_cast_20(
+    macro_rules! test_cast_20 {
         ($_20:expr) => ({
             let _20 = $_20;
 
@@ -202,7 +203,7 @@ mod tests {
             assert_eq!(_20, cast(20f32).unwrap());
             assert_eq!(_20, cast(20f64).unwrap());
         })
-    )
+    }
 
     #[test] fn test_u8_cast()    { test_cast_20!(20u8)  }
     #[test] fn test_u16_cast()   { test_cast_20!(20u16) }
@@ -662,11 +663,32 @@ mod tests {
         assert_eq!(third.checked_mul(4), None);
     }
 
-    macro_rules! test_next_power_of_two(
+    macro_rules! test_is_power_of_two {
+        ($test_name:ident, $T:ident) => (
+            fn $test_name() {
+                #![test]
+                assert_eq!((0 as $T).is_power_of_two(), false);
+                assert_eq!((1 as $T).is_power_of_two(), true);
+                assert_eq!((2 as $T).is_power_of_two(), true);
+                assert_eq!((3 as $T).is_power_of_two(), false);
+                assert_eq!((4 as $T).is_power_of_two(), true);
+                assert_eq!((5 as $T).is_power_of_two(), false);
+                assert!(($T::MAX / 2 + 1).is_power_of_two(), true);
+            }
+        )
+    }
+
+    test_is_power_of_two!{ test_is_power_of_two_u8, u8 }
+    test_is_power_of_two!{ test_is_power_of_two_u16, u16 }
+    test_is_power_of_two!{ test_is_power_of_two_u32, u32 }
+    test_is_power_of_two!{ test_is_power_of_two_u64, u64 }
+    test_is_power_of_two!{ test_is_power_of_two_uint, uint }
+
+    macro_rules! test_next_power_of_two {
         ($test_name:ident, $T:ident) => (
             fn $test_name() {
                 #![test]
-                assert_eq!((0 as $T).next_power_of_two(), 0);
+                assert_eq!((0 as $T).next_power_of_two(), 1);
                 let mut next_power = 1;
                 for i in range::<$T>(1, 40) {
                      assert_eq!(i.next_power_of_two(), next_power);
@@ -674,36 +696,36 @@ mod tests {
                 }
             }
         )
-    )
+    }
 
-    test_next_power_of_two!(test_next_power_of_two_u8, u8)
-    test_next_power_of_two!(test_next_power_of_two_u16, u16)
-    test_next_power_of_two!(test_next_power_of_two_u32, u32)
-    test_next_power_of_two!(test_next_power_of_two_u64, u64)
-    test_next_power_of_two!(test_next_power_of_two_uint, uint)
+    test_next_power_of_two! { test_next_power_of_two_u8, u8 }
+    test_next_power_of_two! { test_next_power_of_two_u16, u16 }
+    test_next_power_of_two! { test_next_power_of_two_u32, u32 }
+    test_next_power_of_two! { test_next_power_of_two_u64, u64 }
+    test_next_power_of_two! { test_next_power_of_two_uint, uint }
 
-    macro_rules! test_checked_next_power_of_two(
+    macro_rules! test_checked_next_power_of_two {
         ($test_name:ident, $T:ident) => (
             fn $test_name() {
                 #![test]
-                assert_eq!((0 as $T).checked_next_power_of_two(), None);
+                assert_eq!((0 as $T).checked_next_power_of_two(), Some(1));
+                assert!(($T::MAX / 2).checked_next_power_of_two().is_some());
+                assert_eq!(($T::MAX - 1).checked_next_power_of_two(), None);
+                assert_eq!($T::MAX.checked_next_power_of_two(), None);
                 let mut next_power = 1;
                 for i in range::<$T>(1, 40) {
                      assert_eq!(i.checked_next_power_of_two(), Some(next_power));
                      if i == next_power { next_power *= 2 }
                 }
-                assert!(($T::MAX / 2).checked_next_power_of_two().is_some());
-                assert_eq!(($T::MAX - 1).checked_next_power_of_two(), None);
-                assert_eq!($T::MAX.checked_next_power_of_two(), None);
             }
         )
-    )
+    }
 
-    test_checked_next_power_of_two!(test_checked_next_power_of_two_u8, u8)
-    test_checked_next_power_of_two!(test_checked_next_power_of_two_u16, u16)
-    test_checked_next_power_of_two!(test_checked_next_power_of_two_u32, u32)
-    test_checked_next_power_of_two!(test_checked_next_power_of_two_u64, u64)
-    test_checked_next_power_of_two!(test_checked_next_power_of_two_uint, uint)
+    test_checked_next_power_of_two! { test_checked_next_power_of_two_u8, u8 }
+    test_checked_next_power_of_two! { test_checked_next_power_of_two_u16, u16 }
+    test_checked_next_power_of_two! { test_checked_next_power_of_two_u32, u32 }
+    test_checked_next_power_of_two! { test_checked_next_power_of_two_u64, u64 }
+    test_checked_next_power_of_two! { test_checked_next_power_of_two_uint, uint }
 
     #[deriving(PartialEq, Show)]
     struct Value { x: int }
@@ -757,13 +779,13 @@ mod tests {
             let one: T = Int::one();
             range(0, exp).fold(one, |acc, _| acc * base)
         }
-        macro_rules! assert_pow(
+        macro_rules! assert_pow {
             (($num:expr, $exp:expr) => $expected:expr) => {{
                 let result = $num.pow($exp);
                 assert_eq!(result, $expected);
                 assert_eq!(result, naive_pow($num, $exp));
             }}
-        )
+        }
         assert_pow!((3i,     0 ) => 1);
         assert_pow!((5i,     1 ) => 5);
         assert_pow!((-4i,    2 ) => 16);
diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs
index 649298d9c08..b1f4e5acb93 100644
--- a/src/libstd/num/strconv.rs
+++ b/src/libstd/num/strconv.rs
@@ -12,20 +12,21 @@
 
 #![allow(missing_docs)]
 
-pub use self::ExponentFormat::*;
-pub use self::SignificantDigits::*;
-pub use self::SignFormat::*;
-
-use char;
-use char::Char;
-use num;
-use num::{Int, Float, FPNaN, FPInfinite, ToPrimitive};
-use slice::{SlicePrelude, CloneSliceAllocPrelude};
-use str::StrPrelude;
+use self::ExponentFormat::*;
+use self::SignificantDigits::*;
+use self::SignFormat::*;
+
+use char::{mod, Char};
+use num::{mod, Int, Float, ToPrimitive};
+use num::FpCategory as Fp;
+use ops::FnMut;
+use slice::{SliceExt, CloneSliceExt};
+use str::StrExt;
 use string::String;
 use vec::Vec;
 
 /// A flag that specifies whether to use exponential (scientific) notation.
+#[deriving(Copy)]
 pub enum ExponentFormat {
     /// Do not use exponential notation.
     ExpNone,
@@ -40,6 +41,7 @@ pub enum ExponentFormat {
 
 /// The number of digits used for emitting the fractional part of a number, if
 /// any.
+#[deriving(Copy)]
 pub enum SignificantDigits {
     /// All calculable digits will be printed.
     ///
@@ -56,6 +58,7 @@ pub enum SignificantDigits {
 }
 
 /// How to emit the sign of a number.
+#[deriving(Copy)]
 pub enum SignFormat {
     /// No sign will be printed. The exponent sign will also be emitted.
     SignNone,
@@ -67,32 +70,29 @@ pub enum SignFormat {
     SignAll,
 }
 
-/**
- * Converts an integral number to its string representation as a byte vector.
- * This is meant to be a common base implementation for all integral string
- * conversion functions like `to_string()` or `to_str_radix()`.
- *
- * # Arguments
- * - `num`           - The number to convert. Accepts any number that
- *                     implements the numeric traits.
- * - `radix`         - Base to use. Accepts only the values 2-36.
- * - `sign`          - How to emit the sign. Options are:
- *     - `SignNone`: No sign at all. Basically emits `abs(num)`.
- *     - `SignNeg`:  Only `-` on negative values.
- *     - `SignAll`:  Both `+` on positive, and `-` on negative numbers.
- * - `f`             - a callback which will be invoked for each ascii character
- *                     which composes the string representation of this integer
- *
- * # Return value
- * A tuple containing the byte vector, and a boolean flag indicating
- * whether it represents a special value like `inf`, `-inf`, `NaN` or not.
- * It returns a tuple because there can be ambiguity between a special value
- * and a number representation at higher bases.
- *
- * # Panics
- * - Panics if `radix` < 2 or `radix` > 36.
- */
-fn int_to_str_bytes_common<T: Int>(num: T, radix: uint, sign: SignFormat, f: |u8|) {
+/// Converts an integral number to its string representation as a byte vector.
+/// This is meant to be a common base implementation for all integral string
+/// conversion functions like `to_string()` or `to_str_radix()`.
+///
+/// # Arguments
+///
+/// - `num`           - The number to convert. Accepts any number that
+///                     implements the numeric traits.
+/// - `radix`         - Base to use. Accepts only the values 2-36.
+/// - `sign`          - How to emit the sign. Options are:
+///     - `SignNone`: No sign at all. Basically emits `abs(num)`.
+///     - `SignNeg`:  Only `-` on negative values.
+///     - `SignAll`:  Both `+` on positive, and `-` on negative numbers.
+/// - `f`             - a callback which will be invoked for each ascii character
+///                     which composes the string representation of this integer
+///
+/// # Panics
+///
+/// - Panics if `radix` < 2 or `radix` > 36.
+fn int_to_str_bytes_common<T, F>(num: T, radix: uint, sign: SignFormat, mut f: F) where
+    T: Int,
+    F: FnMut(u8),
+{
     assert!(2 <= radix && radix <= 36);
 
     let _0: T = Int::zero();
@@ -146,40 +146,41 @@ fn int_to_str_bytes_common<T: Int>(num: T, radix: uint, sign: SignFormat, f: |u8
     }
 }
 
-/**
- * Converts a number to its string representation as a byte vector.
- * This is meant to be a common base implementation for all numeric string
- * conversion functions like `to_string()` or `to_str_radix()`.
- *
- * # Arguments
- * - `num`           - The number to convert. Accepts any number that
- *                     implements the numeric traits.
- * - `radix`         - Base to use. Accepts only the values 2-36. If the exponential notation
- *                     is used, then this base is only used for the significand. The exponent
- *                     itself always printed using a base of 10.
- * - `negative_zero` - Whether to treat the special value `-0` as
- *                     `-0` or as `+0`.
- * - `sign`          - How to emit the sign. See `SignFormat`.
- * - `digits`        - The amount of digits to use for emitting the fractional
- *                     part, if any. See `SignificantDigits`.
- * - `exp_format`   - Whether or not to use the exponential (scientific) notation.
- *                    See `ExponentFormat`.
- * - `exp_capital`   - Whether or not to use a capital letter for the exponent sign, if
- *                     exponential notation is desired.
- *
- * # Return value
- * A tuple containing the byte vector, and a boolean flag indicating
- * whether it represents a special value like `inf`, `-inf`, `NaN` or not.
- * It returns a tuple because there can be ambiguity between a special value
- * and a number representation at higher bases.
- *
- * # Panics
- * - Panics if `radix` < 2 or `radix` > 36.
- * - Panics if `radix` > 14 and `exp_format` is `ExpDec` due to conflict
- *   between digit and exponent sign `'e'`.
- * - Panics if `radix` > 25 and `exp_format` is `ExpBin` due to conflict
- *   between digit and exponent sign `'p'`.
- */
+/// Converts a number to its string representation as a byte vector.
+/// This is meant to be a common base implementation for all numeric string
+/// conversion functions like `to_string()` or `to_str_radix()`.
+///
+/// # Arguments
+///
+/// - `num`           - The number to convert. Accepts any number that
+///                     implements the numeric traits.
+/// - `radix`         - Base to use. Accepts only the values 2-36. If the exponential notation
+///                     is used, then this base is only used for the significand. The exponent
+///                     itself always printed using a base of 10.
+/// - `negative_zero` - Whether to treat the special value `-0` as
+///                     `-0` or as `+0`.
+/// - `sign`          - How to emit the sign. See `SignFormat`.
+/// - `digits`        - The amount of digits to use for emitting the fractional
+///                     part, if any. See `SignificantDigits`.
+/// - `exp_format`   - Whether or not to use the exponential (scientific) notation.
+///                    See `ExponentFormat`.
+/// - `exp_capital`   - Whether or not to use a capital letter for the exponent sign, if
+///                     exponential notation is desired.
+///
+/// # Return value
+///
+/// A tuple containing the byte vector, and a boolean flag indicating
+/// whether it represents a special value like `inf`, `-inf`, `NaN` or not.
+/// It returns a tuple because there can be ambiguity between a special value
+/// and a number representation at higher bases.
+///
+/// # Panics
+///
+/// - Panics if `radix` < 2 or `radix` > 36.
+/// - Panics if `radix` > 14 and `exp_format` is `ExpDec` due to conflict
+///   between digit and exponent sign `'e'`.
+/// - Panics if `radix` > 25 and `exp_format` is `ExpBin` due to conflict
+///   between digit and exponent sign `'p'`.
 pub fn float_to_str_bytes_common<T: Float>(
         num: T, radix: uint, negative_zero: bool,
         sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_upper: bool
@@ -199,14 +200,14 @@ pub fn float_to_str_bytes_common<T: Float>(
     let _1: T = Float::one();
 
     match num.classify() {
-        FPNaN => { return (b"NaN".to_vec(), true); }
-        FPInfinite if num > _0 => {
+        Fp::Nan => { return (b"NaN".to_vec(), true); }
+        Fp::Infinite if num > _0 => {
             return match sign {
                 SignAll => (b"+inf".to_vec(), true),
                 _       => (b"inf".to_vec(), true)
             };
         }
-        FPInfinite if num < _0 => {
+        Fp::Infinite if num < _0 => {
             return match sign {
                 SignNone => (b"inf".to_vec(), true),
                 _        => (b"-inf".to_vec(), true),
@@ -407,10 +408,8 @@ pub fn float_to_str_bytes_common<T: Float>(
     (buf, false)
 }
 
-/**
- * Converts a number to its string representation. This is a wrapper for
- * `to_str_bytes_common()`, for details see there.
- */
+/// Converts a number to its string representation. This is a wrapper for
+/// `to_str_bytes_common()`, for details see there.
 #[inline]
 pub fn float_to_str_common<T: Float>(
         num: T, radix: uint, negative_zero: bool,
@@ -433,28 +432,28 @@ mod tests {
     #[test]
     fn test_int_to_str_overflow() {
         let mut i8_val: i8 = 127_i8;
-        assert_eq!(i8_val.to_string(), "127".to_string());
+        assert_eq!(i8_val.to_string(), "127");
 
         i8_val += 1 as i8;
-        assert_eq!(i8_val.to_string(), "-128".to_string());
+        assert_eq!(i8_val.to_string(), "-128");
 
         let mut i16_val: i16 = 32_767_i16;
-        assert_eq!(i16_val.to_string(), "32767".to_string());
+        assert_eq!(i16_val.to_string(), "32767");
 
         i16_val += 1 as i16;
-        assert_eq!(i16_val.to_string(), "-32768".to_string());
+        assert_eq!(i16_val.to_string(), "-32768");
 
         let mut i32_val: i32 = 2_147_483_647_i32;
-        assert_eq!(i32_val.to_string(), "2147483647".to_string());
+        assert_eq!(i32_val.to_string(), "2147483647");
 
         i32_val += 1 as i32;
-        assert_eq!(i32_val.to_string(), "-2147483648".to_string());
+        assert_eq!(i32_val.to_string(), "-2147483648");
 
         let mut i64_val: i64 = 9_223_372_036_854_775_807_i64;
-        assert_eq!(i64_val.to_string(), "9223372036854775807".to_string());
+        assert_eq!(i64_val.to_string(), "9223372036854775807");
 
         i64_val += 1 as i64;
-        assert_eq!(i64_val.to_string(), "-9223372036854775808".to_string());
+        assert_eq!(i64_val.to_string(), "-9223372036854775808");
     }
 }
 
diff --git a/src/libstd/num/u16.rs b/src/libstd/num/u16.rs
index a83a66c23a5..46699b78599 100644
--- a/src/libstd/num/u16.rs
+++ b/src/libstd/num/u16.rs
@@ -15,4 +15,6 @@
 
 pub use core::u16::{BITS, BYTES, MIN, MAX};
 
-uint_module!(u16)
+use ops::FnOnce;
+
+uint_module! { u16 }
diff --git a/src/libstd/num/u32.rs b/src/libstd/num/u32.rs
index 7271203b23b..45ee9251d2f 100644
--- a/src/libstd/num/u32.rs
+++ b/src/libstd/num/u32.rs
@@ -15,4 +15,6 @@
 
 pub use core::u32::{BITS, BYTES, MIN, MAX};
 
-uint_module!(u32)
+use ops::FnOnce;
+
+uint_module! { u32 }
diff --git a/src/libstd/num/u64.rs b/src/libstd/num/u64.rs
index 25de2f3b255..1d8ff77dac8 100644
--- a/src/libstd/num/u64.rs
+++ b/src/libstd/num/u64.rs
@@ -15,4 +15,6 @@
 
 pub use core::u64::{BITS, BYTES, MIN, MAX};
 
-uint_module!(u64)
+use ops::FnOnce;
+
+uint_module! { u64 }
diff --git a/src/libstd/num/u8.rs b/src/libstd/num/u8.rs
index 22dedeecf3b..0663ace2e5b 100644
--- a/src/libstd/num/u8.rs
+++ b/src/libstd/num/u8.rs
@@ -15,4 +15,6 @@
 
 pub use core::u8::{BITS, BYTES, MIN, MAX};
 
-uint_module!(u8)
+use ops::FnOnce;
+
+uint_module! { u8 }
diff --git a/src/libstd/num/uint.rs b/src/libstd/num/uint.rs
index a425aab3aa1..cd000b3098b 100644
--- a/src/libstd/num/uint.rs
+++ b/src/libstd/num/uint.rs
@@ -10,9 +10,11 @@
 
 //! Operations and constants for architecture-sized unsigned integers (`uint` type)
 
-#![unstable]
+#![stable]
 #![doc(primitive = "uint")]
 
 pub use core::uint::{BITS, BYTES, MIN, MAX};
 
-uint_module!(uint)
+use ops::FnOnce;
+
+uint_module! { uint }
diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs
index 7b79e535201..c42b7eebfdd 100644
--- a/src/libstd/num/uint_macros.rs
+++ b/src/libstd/num/uint_macros.rs
@@ -13,7 +13,7 @@
 #![doc(hidden)]
 #![allow(unsigned_negation)]
 
-macro_rules! uint_module (($T:ty) => (
+macro_rules! uint_module { ($T:ty) => (
 
 // String conversion functions and impl num -> str
 
@@ -32,7 +32,9 @@ macro_rules! uint_module (($T:ty) => (
 /// ```
 #[inline]
 #[deprecated = "just use .to_string(), or a BufWriter with write! if you mustn't allocate"]
-pub fn to_str_bytes<U>(n: $T, radix: uint, f: |v: &[u8]| -> U) -> U {
+pub fn to_str_bytes<U, F>(n: $T, radix: uint, f: F) -> U where
+    F: FnOnce(&[u8]) -> U,
+{
     use io::{Writer, Seek};
     // The radix can be as low as 2, so we need at least 64 characters for a
     // base 2 number, and then we need another for a possible '-' character.
@@ -79,28 +81,28 @@ mod tests {
     #[test]
     fn test_uint_to_str_overflow() {
         let mut u8_val: u8 = 255_u8;
-        assert_eq!(u8_val.to_string(), "255".to_string());
+        assert_eq!(u8_val.to_string(), "255");
 
         u8_val += 1 as u8;
-        assert_eq!(u8_val.to_string(), "0".to_string());
+        assert_eq!(u8_val.to_string(), "0");
 
         let mut u16_val: u16 = 65_535_u16;
-        assert_eq!(u16_val.to_string(), "65535".to_string());
+        assert_eq!(u16_val.to_string(), "65535");
 
         u16_val += 1 as u16;
-        assert_eq!(u16_val.to_string(), "0".to_string());
+        assert_eq!(u16_val.to_string(), "0");
 
         let mut u32_val: u32 = 4_294_967_295_u32;
-        assert_eq!(u32_val.to_string(), "4294967295".to_string());
+        assert_eq!(u32_val.to_string(), "4294967295");
 
         u32_val += 1 as u32;
-        assert_eq!(u32_val.to_string(), "0".to_string());
+        assert_eq!(u32_val.to_string(), "0");
 
         let mut u64_val: u64 = 18_446_744_073_709_551_615_u64;
-        assert_eq!(u64_val.to_string(), "18446744073709551615".to_string());
+        assert_eq!(u64_val.to_string(), "18446744073709551615");
 
         u64_val += 1 as u64;
-        assert_eq!(u64_val.to_string(), "0".to_string());
+        assert_eq!(u64_val.to_string(), "0");
     }
 
     #[test]
@@ -139,4 +141,4 @@ mod tests {
     }
 }
 
-))
+) }
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index d7ba4877086..ceb9a4102f6 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -8,59 +8,61 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/*!
- * Higher-level interfaces to libc::* functions and operating system services.
- *
- * In general these take and return rust types, use rust idioms (enums,
- * closures, vectors) rather than C idioms, and do more extensive safety
- * checks.
- *
- * This module is not meant to only contain 1:1 mappings to libc entries; any
- * os-interface code that is reasonably useful and broadly applicable can go
- * here. Including utility routines that merely build on other os code.
- *
- * We assume the general case is that users do not care, and do not want to
- * be made to care, which operating system they are on. While they may want
- * to special case various special cases -- and so we will not _hide_ the
- * facts of which OS the user is on -- they should be given the opportunity
- * to write OS-ignorant code by default.
- */
+//! Higher-level interfaces to libc::* functions and operating system services.
+//!
+//! In general these take and return rust types, use rust idioms (enums, closures, vectors) rather
+//! than C idioms, and do more extensive safety checks.
+//!
+//! This module is not meant to only contain 1:1 mappings to libc entries; any os-interface code
+//! that is reasonably useful and broadly applicable can go here. Including utility routines that
+//! merely build on other os code.
+//!
+//! We assume the general case is that users do not care, and do not want to be made to care, which
+//! operating system they are on. While they may want to special case various special cases -- and
+//! so we will not _hide_ the facts of which OS the user is on -- they should be given the
+//! opportunity to write OS-ignorant code by default.
 
 #![experimental]
 
 #![allow(missing_docs)]
 #![allow(non_snake_case)]
+#![allow(unused_imports)]
 
-pub use self::MemoryMapKind::*;
-pub use self::MapOption::*;
-pub use self::MapError::*;
+use self::MemoryMapKind::*;
+use self::MapOption::*;
+use self::MapError::*;
 
 use clone::Clone;
 use error::{FromError, Error};
 use fmt;
 use io::{IoResult, IoError};
-use iter::Iterator;
-use libc::{c_void, c_int};
+use iter::{Iterator, IteratorExt};
+use kinds::Copy;
+use libc::{c_void, c_int, c_char};
 use libc;
 use boxed::Box;
-use ops::Drop;
-use option::{Some, None, Option};
-use os;
+use ops::{Drop, FnOnce};
+use option::Option;
+use option::Option::{Some, None};
 use path::{Path, GenericPath, BytesContainer};
 use sys;
-use sys::os as os_imp;
 use ptr::RawPtr;
 use ptr;
-use result::{Err, Ok, Result};
-use slice::{AsSlice, SlicePrelude, PartialEqSlicePrelude};
-use slice::CloneSliceAllocPrelude;
-use str::{Str, StrPrelude, StrAllocating};
+use result::Result;
+use result::Result::{Err, Ok};
+use slice::{AsSlice, SliceExt};
+use slice::CloneSliceExt;
+use str::{Str, StrExt};
 use string::{String, ToString};
 use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst};
 use vec::Vec;
 
 #[cfg(unix)] use c_str::ToCStr;
-#[cfg(unix)] use libc::c_char;
+
+#[cfg(unix)]
+pub use sys::ext as unix;
+#[cfg(windows)]
+pub use sys::ext as windows;
 
 /// Get the number of cores available
 pub fn num_cpus() -> uint {
@@ -74,42 +76,6 @@ pub fn num_cpus() -> uint {
 }
 
 pub const TMPBUF_SZ : uint = 1000u;
-const BUF_BYTES : uint = 2048u;
-
-/// Returns the current working directory as a `Path`.
-///
-/// # Errors
-///
-/// Returns an `Err` if the current working directory value is invalid.
-/// Possible cases:
-///
-/// * Current directory does not exist.
-/// * There are insufficient permissions to access the current directory.
-/// * The internal buffer is not large enough to hold the path.
-///
-/// # Example
-///
-/// ```rust
-/// use std::os;
-///
-/// // We assume that we are in a valid directory like "/home".
-/// let current_working_directory = os::getcwd().unwrap();
-/// println!("The current directory is {}", current_working_directory.display());
-/// // /home
-/// ```
-#[cfg(unix)]
-pub fn getcwd() -> IoResult<Path> {
-    use c_str::CString;
-
-    let mut buf = [0 as c_char, ..BUF_BYTES];
-    unsafe {
-        if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() {
-            Err(IoError::last_error())
-        } else {
-            Ok(Path::new(CString::new(buf.as_ptr(), false)))
-        }
-    }
-}
 
 /// Returns the current working directory as a `Path`.
 ///
@@ -127,95 +93,27 @@ pub fn getcwd() -> IoResult<Path> {
 /// ```rust
 /// use std::os;
 ///
-/// // We assume that we are in a valid directory like "C:\\Windows".
+/// // We assume that we are in a valid directory.
 /// let current_working_directory = os::getcwd().unwrap();
 /// println!("The current directory is {}", current_working_directory.display());
-/// // C:\\Windows
 /// ```
-#[cfg(windows)]
 pub fn getcwd() -> IoResult<Path> {
-    use libc::DWORD;
-    use libc::GetCurrentDirectoryW;
-    use io::OtherIoError;
-
-    let mut buf = [0 as u16, ..BUF_BYTES];
-    unsafe {
-        if libc::GetCurrentDirectoryW(buf.len() as DWORD, buf.as_mut_ptr()) == 0 as DWORD {
-            return Err(IoError::last_error());
-        }
-    }
-
-    match String::from_utf16(::str::truncate_utf16_at_nul(&buf)) {
-        Some(ref cwd) => Ok(Path::new(cwd)),
-        None => Err(IoError {
-            kind: OtherIoError,
-            desc: "GetCurrentDirectoryW returned invalid UTF-16",
-            detail: None,
-        }),
-    }
-}
-
-#[cfg(windows)]
-pub mod windows {
-    use libc::types::os::arch::extra::DWORD;
-    use libc;
-    use option::{None, Option};
-    use option;
-    use os::TMPBUF_SZ;
-    use slice::{SlicePrelude};
-    use string::String;
-    use str::StrPrelude;
-    use vec::Vec;
-
-    pub fn fill_utf16_buf_and_decode(f: |*mut u16, DWORD| -> DWORD)
-        -> Option<String> {
-
-        unsafe {
-            let mut n = TMPBUF_SZ as DWORD;
-            let mut res = None;
-            let mut done = false;
-            while !done {
-                let mut buf = Vec::from_elem(n as uint, 0u16);
-                let k = f(buf.as_mut_ptr(), n);
-                if k == (0 as DWORD) {
-                    done = true;
-                } else if k == n &&
-                          libc::GetLastError() ==
-                          libc::ERROR_INSUFFICIENT_BUFFER as DWORD {
-                    n *= 2 as DWORD;
-                } else if k >= n {
-                    n = k;
-                } else {
-                    done = true;
-                }
-                if k != 0 && done {
-                    let sub = buf.slice(0, k as uint);
-                    // We want to explicitly catch the case when the
-                    // closure returned invalid UTF-16, rather than
-                    // set `res` to None and continue.
-                    let s = String::from_utf16(sub)
-                        .expect("fill_utf16_buf_and_decode: closure created invalid UTF-16");
-                    res = option::Some(s)
-                }
-            }
-            return res;
-        }
-    }
+    sys::os::getcwd()
 }
 
 /*
 Accessing environment variables is not generally threadsafe.
 Serialize access through a global lock.
 */
-fn with_env_lock<T>(f: || -> T) -> T {
-    use rustrt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
+fn with_env_lock<T, F>(f: F) -> T where
+    F: FnOnce() -> T,
+{
+    use sync::{StaticMutex, MUTEX_INIT};
 
-    static LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
+    static LOCK: StaticMutex = MUTEX_INIT;
 
-    unsafe {
-        let _guard = LOCK.lock();
-        f()
-    }
+    let _guard = LOCK.lock();
+    f()
 }
 
 /// Returns a vector of (variable, value) pairs, for all the environment
@@ -236,8 +134,8 @@ fn with_env_lock<T>(f: || -> T) -> T {
 /// ```
 pub fn env() -> Vec<(String,String)> {
     env_as_bytes().into_iter().map(|(k,v)| {
-        let k = String::from_utf8_lossy(k.as_slice()).into_string();
-        let v = String::from_utf8_lossy(v.as_slice()).into_string();
+        let k = String::from_utf8_lossy(k.as_slice()).into_owned();
+        let v = String::from_utf8_lossy(v.as_slice()).into_owned();
         (k,v)
     }).collect()
 }
@@ -246,75 +144,10 @@ pub fn env() -> Vec<(String,String)> {
 /// environment variables of the current process.
 pub fn env_as_bytes() -> Vec<(Vec<u8>,Vec<u8>)> {
     unsafe {
-        #[cfg(windows)]
-        unsafe fn get_env_pairs() -> Vec<Vec<u8>> {
-            use slice::raw;
-
-            use libc::funcs::extra::kernel32::{
-                GetEnvironmentStringsW,
-                FreeEnvironmentStringsW
-            };
-            let ch = GetEnvironmentStringsW();
-            if ch as uint == 0 {
-                panic!("os::env() failure getting env string from OS: {}",
-                       os::last_os_error());
-            }
-            // Here, we lossily decode the string as UTF16.
-            //
-            // The docs suggest that the result should be in Unicode, but
-            // Windows doesn't guarantee it's actually UTF16 -- it doesn't
-            // validate the environment string passed to CreateProcess nor
-            // SetEnvironmentVariable.  Yet, it's unlikely that returning a
-            // raw u16 buffer would be of practical use since the result would
-            // be inherently platform-dependent and introduce additional
-            // complexity to this code.
-            //
-            // Using the non-Unicode version of GetEnvironmentStrings is even
-            // worse since the result is in an OEM code page.  Characters that
-            // can't be encoded in the code page would be turned into question
-            // marks.
-            let mut result = Vec::new();
-            let mut i = 0;
-            while *ch.offset(i) != 0 {
-                let p = &*ch.offset(i);
-                let mut len = 0;
-                while *(p as *const _).offset(len) != 0 {
-                    len += 1;
-                }
-                raw::buf_as_slice(p, len as uint, |s| {
-                    result.push(String::from_utf16_lossy(s).into_bytes());
-                });
-                i += len as int + 1;
-            }
-            FreeEnvironmentStringsW(ch);
-            result
-        }
-        #[cfg(unix)]
-        unsafe fn get_env_pairs() -> Vec<Vec<u8>> {
-            use c_str::CString;
-
-            extern {
-                fn rust_env_pairs() -> *const *const c_char;
-            }
-            let mut environ = rust_env_pairs();
-            if environ as uint == 0 {
-                panic!("os::env() failure getting env string from OS: {}",
-                       os::last_os_error());
-            }
-            let mut result = Vec::new();
-            while *environ != 0 as *const _ {
-                let env_pair =
-                    CString::new(*environ, false).as_bytes_no_nul().to_vec();
-                result.push(env_pair);
-                environ = environ.offset(1);
-            }
-            result
-        }
-
         fn env_convert(input: Vec<Vec<u8>>) -> Vec<(Vec<u8>, Vec<u8>)> {
             let mut pairs = Vec::new();
             for p in input.iter() {
-                let mut it = p.as_slice().splitn(1, |b| *b == b'=');
+                let mut it = p.splitn(1, |b| *b == b'=');
                 let key = it.next().unwrap().to_vec();
                 let default: &[u8] = &[];
                 let val = it.next().unwrap_or(default).to_vec();
@@ -323,7 +156,7 @@ pub fn env_as_bytes() -> Vec<(Vec<u8>,Vec<u8>)> {
             pairs
         }
         with_env_lock(|| {
-            let unparsed_environ = get_env_pairs();
+            let unparsed_environ = sys::os::get_env_pairs();
             env_convert(unparsed_environ)
         })
     }
@@ -352,7 +185,7 @@ pub fn env_as_bytes() -> Vec<(Vec<u8>,Vec<u8>)> {
 /// }
 /// ```
 pub fn getenv(n: &str) -> Option<String> {
-    getenv_as_bytes(n).map(|v| String::from_utf8_lossy(v.as_slice()).into_string())
+    getenv_as_bytes(n).map(|v| String::from_utf8_lossy(v.as_slice()).into_owned())
 }
 
 #[cfg(unix)]
@@ -371,7 +204,7 @@ pub fn getenv_as_bytes(n: &str) -> Option<Vec<u8>> {
             if s.is_null() {
                 None
             } else {
-                Some(CString::new(s as *const i8, false).as_bytes_no_nul().to_vec())
+                Some(CString::new(s as *const libc::c_char, false).as_bytes_no_nul().to_vec())
             }
         })
     }
@@ -383,7 +216,7 @@ pub fn getenv_as_bytes(n: &str) -> Option<Vec<u8>> {
 pub fn getenv(n: &str) -> Option<String> {
     unsafe {
         with_env_lock(|| {
-            use os::windows::{fill_utf16_buf_and_decode};
+            use sys::os::fill_utf16_buf_and_decode;
             let mut n: Vec<u16> = n.utf16_units().collect();
             n.push(0);
             fill_utf16_buf_and_decode(|buf, sz| {
@@ -499,52 +332,7 @@ pub fn unsetenv(n: &str) {
 /// }
 /// ```
 pub fn split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
-    #[cfg(unix)]
-    fn _split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
-        unparsed.container_as_bytes()
-                .split(|b| *b == b':')
-                .map(Path::new)
-                .collect()
-    }
-
-    #[cfg(windows)]
-    fn _split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
-        // On Windows, the PATH environment variable is semicolon separated.  Double
-        // quotes are used as a way of introducing literal semicolons (since
-        // c:\some;dir is a valid Windows path). Double quotes are not themselves
-        // permitted in path names, so there is no way to escape a double quote.
-        // Quoted regions can appear in arbitrary locations, so
-        //
-        //   c:\foo;c:\som"e;di"r;c:\bar
-        //
-        // Should parse as [c:\foo, c:\some;dir, c:\bar].
-        //
-        // (The above is based on testing; there is no clear reference available
-        // for the grammar.)
-
-        let mut parsed = Vec::new();
-        let mut in_progress = Vec::new();
-        let mut in_quote = false;
-
-        for b in unparsed.container_as_bytes().iter() {
-            match *b {
-                b';' if !in_quote => {
-                    parsed.push(Path::new(in_progress.as_slice()));
-                    in_progress.truncate(0)
-                }
-                b'"' => {
-                    in_quote = !in_quote;
-                }
-                _  => {
-                    in_progress.push(*b);
-                }
-            }
-        }
-        parsed.push(Path::new(in_progress));
-        parsed
-    }
-
-    _split_paths(unparsed)
+    sys::os::split_paths(unparsed.container_as_bytes())
 }
 
 /// Joins a collection of `Path`s appropriately for the `PATH`
@@ -569,45 +357,11 @@ pub fn split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
 /// os::setenv(key, os::join_paths(paths.as_slice()).unwrap());
 /// ```
 pub fn join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
-    #[cfg(windows)]
-    fn _join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
-        let mut joined = Vec::new();
-        let sep = b';';
-
-        for (i, path) in paths.iter().map(|p| p.container_as_bytes()).enumerate() {
-            if i > 0 { joined.push(sep) }
-            if path.contains(&b'"') {
-                return Err("path segment contains `\"`");
-            } else if path.contains(&sep) {
-                joined.push(b'"');
-                joined.push_all(path);
-                joined.push(b'"');
-            } else {
-                joined.push_all(path);
-            }
-        }
-
-        Ok(joined)
-    }
-
-    #[cfg(unix)]
-    fn _join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
-        let mut joined = Vec::new();
-        let sep = b':';
-
-        for (i, path) in paths.iter().map(|p| p.container_as_bytes()).enumerate() {
-            if i > 0 { joined.push(sep) }
-            if path.contains(&sep) { return Err("path segment contains separator `:`") }
-            joined.push_all(path);
-        }
-
-        Ok(joined)
-    }
-
-    _join_paths(paths)
+    sys::os::join_paths(paths)
 }
 
 /// A low-level OS in-memory pipe.
+#[deriving(Copy)]
 pub struct Pipe {
     /// A file descriptor representing the reading end of the pipe. Data written
     /// on the `out` file descriptor can be read from this file descriptor.
@@ -655,69 +409,7 @@ pub fn dll_filename(base: &str) -> String {
 /// };
 /// ```
 pub fn self_exe_name() -> Option<Path> {
-
-    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-    fn load_self() -> Option<Vec<u8>> {
-        unsafe {
-            use libc::funcs::bsd44::*;
-            use libc::consts::os::extra::*;
-            let mut mib = vec![CTL_KERN as c_int,
-                               KERN_PROC as c_int,
-                               KERN_PROC_PATHNAME as c_int,
-                               -1 as c_int];
-            let mut sz: libc::size_t = 0;
-            let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
-                             ptr::null_mut(), &mut sz, ptr::null_mut(),
-                             0u as libc::size_t);
-            if err != 0 { return None; }
-            if sz == 0 { return None; }
-            let mut v: Vec<u8> = Vec::with_capacity(sz as uint);
-            let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
-                             v.as_mut_ptr() as *mut c_void, &mut sz,
-                             ptr::null_mut(), 0u as libc::size_t);
-            if err != 0 { return None; }
-            if sz == 0 { return None; }
-            v.set_len(sz as uint - 1); // chop off trailing NUL
-            Some(v)
-        }
-    }
-
-    #[cfg(any(target_os = "linux", target_os = "android"))]
-    fn load_self() -> Option<Vec<u8>> {
-        use std::io;
-
-        match io::fs::readlink(&Path::new("/proc/self/exe")) {
-            Ok(path) => Some(path.into_vec()),
-            Err(..) => None
-        }
-    }
-
-    #[cfg(any(target_os = "macos", target_os = "ios"))]
-    fn load_self() -> Option<Vec<u8>> {
-        unsafe {
-            use libc::funcs::extra::_NSGetExecutablePath;
-            let mut sz: u32 = 0;
-            _NSGetExecutablePath(ptr::null_mut(), &mut sz);
-            if sz == 0 { return None; }
-            let mut v: Vec<u8> = Vec::with_capacity(sz as uint);
-            let err = _NSGetExecutablePath(v.as_mut_ptr() as *mut i8, &mut sz);
-            if err != 0 { return None; }
-            v.set_len(sz as uint - 1); // chop off trailing NUL
-            Some(v)
-        }
-    }
-
-    #[cfg(windows)]
-    fn load_self() -> Option<Vec<u8>> {
-        unsafe {
-            use os::windows::fill_utf16_buf_and_decode;
-            fill_utf16_buf_and_decode(|buf, sz| {
-                libc::GetModuleFileNameW(0u as libc::DWORD, buf, sz)
-            }).map(|s| s.into_string().into_bytes())
-        }
-    }
-
-    load_self().and_then(Path::new_opt)
+    sys::os::load_self().and_then(Path::new_opt)
 }
 
 /// Optionally returns the filesystem path to the current executable which is
@@ -788,18 +480,16 @@ pub fn homedir() -> Option<Path> {
     _homedir()
 }
 
-/**
- * Returns the path to a temporary directory.
- *
- * On Unix, returns the value of the 'TMPDIR' environment variable if it is
- * set, otherwise for non-Android it returns '/tmp'. If Android, since there
- * is no global temporary folder (it is usually allocated per-app), we return
- * '/data/local/tmp'.
- *
- * On Windows, returns the value of, in order, the 'TMP', 'TEMP',
- * 'USERPROFILE' environment variable  if any are set and not the empty
- * string. Otherwise, tmpdir returns the path to the Windows directory.
- */
+/// Returns the path to a temporary directory.
+///
+/// On Unix, returns the value of the 'TMPDIR' environment variable if it is
+/// set, otherwise for non-Android it returns '/tmp'. If Android, since there
+/// is no global temporary folder (it is usually allocated per-app), we return
+/// '/data/local/tmp'.
+///
+/// On Windows, returns the value of, in order, the 'TMP', 'TEMP',
+/// 'USERPROFILE' environment variable  if any are set and not the empty
+/// string. Otherwise, tmpdir returns the path to the Windows directory.
 pub fn tmpdir() -> Path {
     return lookup();
 
@@ -835,7 +525,6 @@ pub fn tmpdir() -> Path {
     }
 }
 
-///
 /// Convert a relative path to an absolute path
 ///
 /// If the given path is relative, return it prepended with the current working
@@ -880,37 +569,12 @@ pub fn make_absolute(p: &Path) -> IoResult<Path> {
 /// println!("Successfully changed working directory to {}!", root.display());
 /// ```
 pub fn change_dir(p: &Path) -> IoResult<()> {
-    return chdir(p);
-
-    #[cfg(windows)]
-    fn chdir(p: &Path) -> IoResult<()> {
-        let mut p = p.as_str().unwrap().utf16_units().collect::<Vec<u16>>();
-        p.push(0);
-
-        unsafe {
-            match libc::SetCurrentDirectoryW(p.as_ptr()) != (0 as libc::BOOL) {
-                true => Ok(()),
-                false => Err(IoError::last_error()),
-            }
-        }
-    }
-
-    #[cfg(unix)]
-    fn chdir(p: &Path) -> IoResult<()> {
-        p.with_c_str(|buf| {
-            unsafe {
-                match libc::chdir(buf) == (0 as c_int) {
-                    true => Ok(()),
-                    false => Err(IoError::last_error()),
-                }
-            }
-        })
-    }
+    return sys::os::chdir(p);
 }
 
 /// Returns the platform-specific value of errno
 pub fn errno() -> uint {
-    os_imp::errno() as uint
+    sys::os::errno() as uint
 }
 
 /// Return the string corresponding to an `errno()` value of `errnum`.
@@ -923,7 +587,7 @@ pub fn errno() -> uint {
 /// println!("{}", os::error_string(os::errno() as uint));
 /// ```
 pub fn error_string(errnum: uint) -> String {
-    return os_imp::error_string(errnum as i32);
+    return sys::os::error_string(errnum as i32);
 }
 
 /// Get a string representing the platform-dependent last error
@@ -933,16 +597,14 @@ pub fn last_os_error() -> String {
 
 static EXIT_STATUS: AtomicInt = INIT_ATOMIC_INT;
 
-/**
- * Sets the process exit code
- *
- * Sets the exit code returned by the process if all supervised tasks
- * terminate successfully (without panicking). If the current root task panics
- * and is supervised by the scheduler then any user-specified exit status is
- * ignored and the process exits with the default panic status.
- *
- * Note that this is not synchronized against modifications of other threads.
- */
+/// Sets the process exit code
+///
+/// Sets the exit code returned by the process if all supervised tasks
+/// terminate successfully (without panicking). If the current root task panics
+/// and is supervised by the scheduler then any user-specified exit status is
+/// ignored and the process exits with the default panic status.
+///
+/// Note that this is not synchronized against modifications of other threads.
 pub fn set_exit_status(code: int) {
     EXIT_STATUS.store(code, SeqCst)
 }
@@ -963,11 +625,9 @@ unsafe fn load_argc_and_argv(argc: int,
     })
 }
 
-/**
- * Returns the command line arguments
- *
- * Returns a list of the command line arguments.
- */
+/// Returns the command line arguments
+///
+/// Returns a list of the command line arguments.
 #[cfg(target_os = "macos")]
 fn real_args_as_bytes() -> Vec<Vec<u8>> {
     unsafe {
@@ -1039,19 +699,15 @@ fn real_args_as_bytes() -> Vec<Vec<u8>> {
           target_os = "freebsd",
           target_os = "dragonfly"))]
 fn real_args_as_bytes() -> Vec<Vec<u8>> {
-    use rustrt;
-
-    match rustrt::args::clone() {
-        Some(args) => args,
-        None => panic!("process arguments not initialized")
-    }
+    use rt;
+    rt::args::clone().unwrap_or_else(|| vec![])
 }
 
 #[cfg(not(windows))]
 fn real_args() -> Vec<String> {
     real_args_as_bytes().into_iter()
                         .map(|v| {
-                            String::from_utf8_lossy(v.as_slice()).into_string()
+                            String::from_utf8_lossy(v.as_slice()).into_owned()
                         }).collect()
 }
 
@@ -1071,9 +727,9 @@ fn real_args() -> Vec<String> {
         while *ptr.offset(len as int) != 0 { len += 1; }
 
         // Push it onto the list.
-        let opt_s = slice::raw::buf_as_slice(ptr as *const _, len, |buf| {
-            String::from_utf16(::str::truncate_utf16_at_nul(buf))
-        });
+        let ptr = ptr as *const u16;
+        let buf = slice::from_raw_buf(&ptr, len);
+        let opt_s = String::from_utf16(sys::os::truncate_utf16_at_nul(buf));
         opt_s.expect("CommandLineToArgvW returned invalid UTF-16")
     });
 
@@ -1110,7 +766,7 @@ extern "system" {
 ///
 /// The first element is traditionally the path to the executable, but it can be
 /// set to arbitrary text, and it may not even exist, so this property should not
-//  be relied upon for security purposes.
+/// be relied upon for security purposes.
 ///
 /// The arguments are interpreted as utf-8, with invalid bytes replaced with \uFFFD.
 /// See `String::from_utf8_lossy` for details.
@@ -1141,38 +797,9 @@ extern {
     pub fn _NSGetArgv() -> *mut *mut *mut c_char;
 }
 
-// Round up `from` to be divisible by `to`
-fn round_up(from: uint, to: uint) -> uint {
-    let r = if from % to == 0 {
-        from
-    } else {
-        from + to - (from % to)
-    };
-    if r == 0 {
-        to
-    } else {
-        r
-    }
-}
-
 /// Returns the page size of the current architecture in bytes.
-#[cfg(unix)]
 pub fn page_size() -> uint {
-    unsafe {
-        libc::sysconf(libc::_SC_PAGESIZE) as uint
-    }
-}
-
-/// Returns the page size of the current architecture in bytes.
-#[cfg(windows)]
-pub fn page_size() -> uint {
-    use mem;
-    unsafe {
-        let mut info = mem::zeroed();
-        libc::GetSystemInfo(&mut info);
-
-        return info.dwPageSize as uint;
-    }
+    sys::os::page_size()
 }
 
 /// A memory mapped file or chunk of memory. This is a very system-specific
@@ -1183,6 +810,7 @@ pub fn page_size() -> uint {
 ///
 /// The memory map is released (unmapped) when the destructor is run, so don't
 /// let it leave scope by accident if you want it to stick around.
+#[allow(missing_copy_implementations)]
 pub struct MemoryMap {
     data: *mut u8,
     len: uint,
@@ -1200,6 +828,8 @@ pub enum MemoryMapKind {
     MapVirtual
 }
 
+impl Copy for MemoryMapKind {}
+
 /// Options the memory map is created with
 pub enum MapOption {
     /// The memory should be readable
@@ -1211,7 +841,11 @@ pub enum MapOption {
     /// Create a map for a specific address range. Corresponds to `MAP_FIXED` on
     /// POSIX.
     MapAddr(*const u8),
+    /// Create a memory mapping for a file with a given HANDLE.
+    #[cfg(windows)]
+    MapFd(libc::HANDLE),
     /// Create a memory mapping for a file with a given fd.
+    #[cfg(not(windows))]
     MapFd(c_int),
     /// When using `MapFd`, the start of the map is `uint` bytes from the start
     /// of the file.
@@ -1223,9 +857,12 @@ pub enum MapOption {
     MapNonStandardFlags(c_int),
 }
 
+impl Copy for MapOption {}
+
 /// Possible errors when creating a map.
+#[deriving(Copy)]
 pub enum MapError {
-    /// ## The following are POSIX-specific
+    /// # The following are POSIX-specific
     ///
     /// fd was not open for reading or, if using `MapWritable`, was not open for
     /// writing.
@@ -1247,7 +884,7 @@ pub enum MapError {
     ErrZeroLength,
     /// Unrecognized error. The inner value is the unrecognized errno.
     ErrUnknown(int),
-    /// ## The following are Windows-specific
+    /// # The following are Windows-specific
     ///
     /// Unsupported combination of protection flags
     /// (`MapReadable`/`MapWritable`/`MapExecutable`).
@@ -1311,6 +948,20 @@ impl FromError<MapError> for Box<Error> {
     }
 }
 
+// Round up `from` to be divisible by `to`
+fn round_up(from: uint, to: uint) -> uint {
+    let r = if from % to == 0 {
+        from
+    } else {
+        from + to - (from % to)
+    };
+    if r == 0 {
+        to
+    } else {
+        r
+    }
+}
+
 #[cfg(unix)]
 impl MemoryMap {
     /// Create a new mapping with the given `options`, at least `min_len` bytes
@@ -1405,7 +1056,7 @@ impl MemoryMap {
         let mut readable = false;
         let mut writable = false;
         let mut executable = false;
-        let mut fd: c_int = -1;
+        let mut handle: HANDLE = libc::INVALID_HANDLE_VALUE;
         let mut offset: uint = 0;
         let len = round_up(min_len, page_size());
 
@@ -1415,23 +1066,23 @@ impl MemoryMap {
                 MapWritable => { writable = true; },
                 MapExecutable => { executable = true; }
                 MapAddr(addr_) => { lpAddress = addr_ as LPVOID; },
-                MapFd(fd_) => { fd = fd_; },
+                MapFd(handle_) => { handle = handle_; },
                 MapOffset(offset_) => { offset = offset_; },
                 MapNonStandardFlags(..) => {}
             }
         }
 
         let flProtect = match (executable, readable, writable) {
-            (false, false, false) if fd == -1 => libc::PAGE_NOACCESS,
+            (false, false, false) if handle == libc::INVALID_HANDLE_VALUE => libc::PAGE_NOACCESS,
             (false, true, false) => libc::PAGE_READONLY,
             (false, true, true) => libc::PAGE_READWRITE,
-            (true, false, false) if fd == -1 => libc::PAGE_EXECUTE,
+            (true, false, false) if handle == libc::INVALID_HANDLE_VALUE => libc::PAGE_EXECUTE,
             (true, true, false) => libc::PAGE_EXECUTE_READ,
             (true, true, true) => libc::PAGE_EXECUTE_READWRITE,
             _ => return Err(ErrUnsupProt)
         };
 
-        if fd == -1 {
+        if handle == libc::INVALID_HANDLE_VALUE {
             if offset != 0 {
                 return Err(ErrUnsupOffset);
             }
@@ -1459,7 +1110,7 @@ impl MemoryMap {
                                               // we should never get here.
             };
             unsafe {
-                let hFile = libc::get_osfhandle(fd) as HANDLE;
+                let hFile = handle;
                 let mapping = libc::CreateFileMappingW(hFile,
                                                        ptr::null_mut(),
                                                        flProtect,
@@ -1774,7 +1425,6 @@ mod arch_consts {
 #[cfg(test)]
 mod tests {
     use prelude::*;
-    use c_str::ToCStr;
     use option;
     use os::{env, getcwd, getenv, make_absolute};
     use os::{split_paths, join_paths, setenv, unsetenv};
@@ -1804,7 +1454,7 @@ mod tests {
     fn test_setenv() {
         let n = make_rand_name();
         setenv(n.as_slice(), "VALUE");
-        assert_eq!(getenv(n.as_slice()), option::Some("VALUE".to_string()));
+        assert_eq!(getenv(n.as_slice()), option::Option::Some("VALUE".to_string()));
     }
 
     #[test]
@@ -1812,7 +1462,7 @@ mod tests {
         let n = make_rand_name();
         setenv(n.as_slice(), "VALUE");
         unsetenv(n.as_slice());
-        assert_eq!(getenv(n.as_slice()), option::None);
+        assert_eq!(getenv(n.as_slice()), option::Option::None);
     }
 
     #[test]
@@ -1821,9 +1471,9 @@ mod tests {
         let n = make_rand_name();
         setenv(n.as_slice(), "1");
         setenv(n.as_slice(), "2");
-        assert_eq!(getenv(n.as_slice()), option::Some("2".to_string()));
+        assert_eq!(getenv(n.as_slice()), option::Option::Some("2".to_string()));
         setenv(n.as_slice(), "");
-        assert_eq!(getenv(n.as_slice()), option::Some("".to_string()));
+        assert_eq!(getenv(n.as_slice()), option::Option::Some("".to_string()));
     }
 
     // Windows GetEnvironmentVariable requires some extra work to make sure
@@ -1840,7 +1490,7 @@ mod tests {
         let n = make_rand_name();
         setenv(n.as_slice(), s.as_slice());
         debug!("{}", s.clone());
-        assert_eq!(getenv(n.as_slice()), option::Some(s));
+        assert_eq!(getenv(n.as_slice()), option::Option::Some(s));
     }
 
     #[test]
@@ -1877,7 +1527,7 @@ mod tests {
             // MingW seems to set some funky environment variables like
             // "=C:=C:\MinGW\msys\1.0\bin" and "!::=::\" that are returned
             // from env() but not visible from getenv().
-            assert!(v2.is_none() || v2 == option::Some(v));
+            assert!(v2.is_none() || v2 == option::Option::Some(v));
         }
     }
 
@@ -1964,11 +1614,11 @@ mod tests {
 
     #[test]
     fn memory_map_rw() {
-        use result::{Ok, Err};
+        use result::Result::{Ok, Err};
 
         let chunk = match os::MemoryMap::new(16, &[
-            os::MapReadable,
-            os::MapWritable
+            os::MapOption::MapReadable,
+            os::MapOption::MapWritable
         ]) {
             Ok(chunk) => chunk,
             Err(msg) => panic!("{}", msg)
@@ -1983,55 +1633,47 @@ mod tests {
 
     #[test]
     fn memory_map_file() {
-        use result::{Ok, Err};
+        use libc;
         use os::*;
-        use libc::*;
-        use io::fs;
-
-        #[cfg(unix)]
-        fn lseek_(fd: c_int, size: uint) {
-            unsafe {
-                assert!(lseek(fd, size as off_t, SEEK_SET) == size as off_t);
-            }
+        use io::fs::{File, unlink};
+        use io::SeekStyle::SeekSet;
+        use io::FileMode::Open;
+        use io::FileAccess::ReadWrite;
+
+        #[cfg(not(windows))]
+        fn get_fd(file: &File) -> libc::c_int {
+            use os::unix::AsRawFd;
+            file.as_raw_fd()
         }
+
         #[cfg(windows)]
-        fn lseek_(fd: c_int, size: uint) {
-           unsafe {
-               assert!(lseek(fd, size as c_long, SEEK_SET) == size as c_long);
-           }
+        fn get_fd(file: &File) -> libc::HANDLE {
+            use os::windows::AsRawHandle;
+            file.as_raw_handle()
         }
 
         let mut path = tmpdir();
         path.push("mmap_file.tmp");
         let size = MemoryMap::granularity() * 2;
-
-        let fd = unsafe {
-            let fd = path.with_c_str(|path| {
-                open(path, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR)
-            });
-            lseek_(fd, size);
-            "x".with_c_str(|x| assert!(write(fd, x as *const c_void, 1) == 1));
-            fd
-        };
-        let chunk = match MemoryMap::new(size / 2, &[
-            MapReadable,
-            MapWritable,
-            MapFd(fd),
-            MapOffset(size / 2)
-        ]) {
-            Ok(chunk) => chunk,
-            Err(msg) => panic!("{}", msg)
-        };
+        let mut file = File::open_mode(&path, Open, ReadWrite).unwrap();
+        file.seek(size as i64, SeekSet);
+        file.write_u8(0);
+
+        let chunk = MemoryMap::new(size / 2, &[
+            MapOption::MapReadable,
+            MapOption::MapWritable,
+            MapOption::MapFd(get_fd(&file)),
+            MapOption::MapOffset(size / 2)
+        ]).unwrap();
         assert!(chunk.len > 0);
 
         unsafe {
             *chunk.data = 0xbe;
             assert!(*chunk.data == 0xbe);
-            close(fd);
         }
         drop(chunk);
 
-        fs::unlink(&path).unwrap();
+        unlink(&path).unwrap();
     }
 
     #[test]
@@ -2039,7 +1681,7 @@ mod tests {
     fn split_paths_windows() {
         fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
             split_paths(unparsed) ==
-                parsed.iter().map(|s| Path::new(*s)).collect()
+                parsed.iter().map(|s| Path::new(*s)).collect::<Vec<_>>()
         }
 
         assert!(check_parse("", &mut [""]));
@@ -2059,7 +1701,7 @@ mod tests {
     fn split_paths_unix() {
         fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
             split_paths(unparsed) ==
-                parsed.iter().map(|s| Path::new(*s)).collect()
+                parsed.iter().map(|s| Path::new(*s)).collect::<Vec<_>>()
         }
 
         assert!(check_parse("", &mut [""]));
@@ -2073,7 +1715,7 @@ mod tests {
     #[cfg(unix)]
     fn join_paths_unix() {
         fn test_eq(input: &[&str], output: &str) -> bool {
-            join_paths(input).unwrap().as_slice() == output.as_bytes()
+            join_paths(input).unwrap() == output.as_bytes()
         }
 
         assert!(test_eq(&[], ""));
@@ -2088,7 +1730,7 @@ mod tests {
     #[cfg(windows)]
     fn join_paths_windows() {
         fn test_eq(input: &[&str], output: &str) -> bool {
-            join_paths(input).unwrap().as_slice() == output.as_bytes()
+            join_paths(input).unwrap() == output.as_bytes()
         }
 
         assert!(test_eq(&[], ""));
diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs
index a185a29a700..30f3f56bc1c 100644
--- a/src/libstd/path/mod.rs
+++ b/src/libstd/path/mod.rs
@@ -8,62 +8,56 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/*!
-
-Cross-platform path support
-
-This module implements support for two flavors of paths. `PosixPath` represents
-a path on any unix-like system, whereas `WindowsPath` represents a path on
-Windows. This module also exposes a typedef `Path` which is equal to the
-appropriate platform-specific path variant.
-
-Both `PosixPath` and `WindowsPath` implement a trait `GenericPath`, which
-contains the set of methods that behave the same for both paths. They each also
-implement some methods that could not be expressed in `GenericPath`, yet behave
-identically for both path flavors, such as `.components()`.
-
-The three main design goals of this module are 1) to avoid unnecessary
-allocation, 2) to behave the same regardless of which flavor of path is being
-used, and 3) to support paths that cannot be represented in UTF-8 (as Linux has
-no restriction on paths beyond disallowing NUL).
-
-## Usage
-
-Usage of this module is fairly straightforward. Unless writing platform-specific
-code, `Path` should be used to refer to the platform-native path.
-
-Creation of a path is typically done with either `Path::new(some_str)` or
-`Path::new(some_vec)`. This path can be modified with `.push()` and
-`.pop()` (and other setters). The resulting Path can either be passed to another
-API that expects a path, or can be turned into a `&[u8]` with `.as_vec()` or a
-`Option<&str>` with `.as_str()`. Similarly, attributes of the path can be queried
-with methods such as `.filename()`. There are also methods that return a new
-path instead of modifying the receiver, such as `.join()` or `.dir_path()`.
-
-Paths are always kept in normalized form. This means that creating the path
-`Path::new("a/b/../c")` will return the path `a/c`. Similarly any attempt
-to mutate the path will always leave it in normalized form.
-
-When rendering a path to some form of output, there is a method `.display()`
-which is compatible with the `format!()` parameter `{}`. This will render the
-path as a string, replacing all non-utf8 sequences with the Replacement
-Character (U+FFFD). As such it is not suitable for passing to any API that
-actually operates on the path; it is only intended for display.
-
-## Example
-
-```rust
-use std::io::fs::PathExtensions;
-
-let mut path = Path::new("/tmp/path");
-println!("path: {}", path.display());
-path.set_filename("foo");
-path.push("bar");
-println!("new path: {}", path.display());
-println!("path exists: {}", path.exists());
-```
-
-*/
+//! Cross-platform path support
+//!
+//! This module implements support for two flavors of paths. `PosixPath` represents a path on any
+//! unix-like system, whereas `WindowsPath` represents a path on Windows. This module also exposes
+//! a typedef `Path` which is equal to the appropriate platform-specific path variant.
+//!
+//! Both `PosixPath` and `WindowsPath` implement a trait `GenericPath`, which contains the set of
+//! methods that behave the same for both paths. They each also implement some methods that could
+//! not be expressed in `GenericPath`, yet behave identically for both path flavors, such as
+//! `.components()`.
+//!
+//! The three main design goals of this module are 1) to avoid unnecessary allocation, 2) to behave
+//! the same regardless of which flavor of path is being used, and 3) to support paths that cannot
+//! be represented in UTF-8 (as Linux has no restriction on paths beyond disallowing NUL).
+//!
+//! ## Usage
+//!
+//! Usage of this module is fairly straightforward. Unless writing platform-specific code, `Path`
+//! should be used to refer to the platform-native path.
+//!
+//! Creation of a path is typically done with either `Path::new(some_str)` or
+//! `Path::new(some_vec)`. This path can be modified with `.push()` and `.pop()` (and other
+//! setters). The resulting Path can either be passed to another API that expects a path, or can be
+//! turned into a `&[u8]` with `.as_vec()` or a `Option<&str>` with `.as_str()`. Similarly,
+//! attributes of the path can be queried with methods such as `.filename()`. There are also
+//! methods that return a new path instead of modifying the receiver, such as `.join()` or
+//! `.dir_path()`.
+//!
+//! Paths are always kept in normalized form. This means that creating the path
+//! `Path::new("a/b/../c")` will return the path `a/c`. Similarly any attempt to mutate the path
+//! will always leave it in normalized form.
+//!
+//! When rendering a path to some form of output, there is a method `.display()` which is
+//! compatible with the `format!()` parameter `{}`. This will render the path as a string,
+//! replacing all non-utf8 sequences with the Replacement Character (U+FFFD). As such it is not
+//! suitable for passing to any API that actually operates on the path; it is only intended for
+//! display.
+//!
+//! ## Example
+//!
+//! ```rust
+//! use std::io::fs::PathExtensions;
+//!
+//! let mut path = Path::new("/tmp/path");
+//! println!("path: {}", path.display());
+//! path.set_filename("foo");
+//! path.push("bar");
+//! println!("new path: {}", path.display());
+//! println!("path exists: {}", path.exists());
+//! ```
 
 #![experimental]
 
@@ -71,13 +65,14 @@ use core::kinds::Sized;
 use c_str::CString;
 use clone::Clone;
 use fmt;
-use iter::Iterator;
-use option::{Option, None, Some};
+use iter::IteratorExt;
+use option::Option;
+use option::Option::{None, Some};
 use str;
-use str::{MaybeOwned, Str, StrPrelude};
+use str::{CowString, MaybeOwned, Str, StrExt};
 use string::String;
-use slice::{AsSlice, CloneSliceAllocPrelude};
-use slice::{PartialEqSlicePrelude, SlicePrelude};
+use slice::{AsSlice, CloneSliceExt};
+use slice::{PartialEqSliceExt, SliceExt};
 use vec::Vec;
 
 /// Typedef for POSIX file paths.
@@ -202,7 +197,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
     /// ```
     #[inline]
     fn as_str<'a>(&'a self) -> Option<&'a str> {
-        str::from_utf8(self.as_vec())
+        str::from_utf8(self.as_vec()).ok()
     }
 
     /// Returns the path as a byte vector
@@ -298,7 +293,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
     /// ```
     #[inline]
     fn dirname_str<'a>(&'a self) -> Option<&'a str> {
-        str::from_utf8(self.dirname())
+        str::from_utf8(self.dirname()).ok()
     }
 
     /// Returns the file component of `self`, as a byte vector.
@@ -332,7 +327,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
     /// ```
     #[inline]
     fn filename_str<'a>(&'a self) -> Option<&'a str> {
-        self.filename().and_then(str::from_utf8)
+        self.filename().and_then(|s| str::from_utf8(s).ok())
     }
 
     /// Returns the stem of the filename of `self`, as a byte vector.
@@ -378,7 +373,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
     /// ```
     #[inline]
     fn filestem_str<'a>(&'a self) -> Option<&'a str> {
-        self.filestem().and_then(str::from_utf8)
+        self.filestem().and_then(|s| str::from_utf8(s).ok())
     }
 
     /// Returns the extension of the filename of `self`, as an optional byte vector.
@@ -425,7 +420,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
     /// ```
     #[inline]
     fn extension_str<'a>(&'a self) -> Option<&'a str> {
-        self.extension().and_then(str::from_utf8)
+        self.extension().and_then(|s| str::from_utf8(s).ok())
     }
 
     /// Replaces the filename portion of the path with the given byte vector or string.
@@ -798,7 +793,7 @@ pub trait BytesContainer for Sized? {
     /// Returns the receiver interpreted as a utf-8 string, if possible
     #[inline]
     fn container_as_str<'a>(&'a self) -> Option<&'a str> {
-        str::from_utf8(self.container_as_bytes())
+        str::from_utf8(self.container_as_bytes()).ok()
     }
     /// Returns whether .container_as_str() is guaranteed to not fail
     // FIXME (#8888): Remove unused arg once ::<for T> works
@@ -830,7 +825,7 @@ pub struct Display<'a, P:'a> {
 
 impl<'a, P: GenericPath> fmt::Show for Display<'a, P> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.as_maybe_owned().as_slice().fmt(f)
+        self.as_cow().fmt(f)
     }
 }
 
@@ -840,7 +835,7 @@ impl<'a, P: GenericPath> Display<'a, P> {
     /// If the path is not UTF-8, invalid sequences will be replaced with the
     /// Unicode replacement char. This involves allocation.
     #[inline]
-    pub fn as_maybe_owned(&self) -> MaybeOwned<'a> {
+    pub fn as_cow(&self) -> CowString<'a> {
         String::from_utf8_lossy(if self.filename {
             match self.path.filename() {
                 None => {
@@ -875,7 +870,7 @@ impl BytesContainer for String {
     }
     #[inline]
     fn container_as_str(&self) -> Option<&str> {
-        Some(self.as_slice())
+        Some(self[])
     }
     #[inline]
     fn is_str(_: Option<&String>) -> bool { true }
@@ -891,7 +886,7 @@ impl BytesContainer for [u8] {
 impl BytesContainer for Vec<u8> {
     #[inline]
     fn container_as_bytes(&self) -> &[u8] {
-        self.as_slice()
+        self[]
     }
 }
 
@@ -902,6 +897,7 @@ impl BytesContainer for CString {
     }
 }
 
+#[allow(deprecated)]
 impl<'a> BytesContainer for str::MaybeOwned<'a> {
     #[inline]
     fn container_as_bytes<'b>(&'b self) -> &'b [u8] {
@@ -936,8 +932,6 @@ fn contains_nul<T: BytesContainer>(v: &T) -> bool {
 #[cfg(test)]
 mod tests {
     use prelude::*;
-    use super::{GenericPath, PosixPath, WindowsPath};
-    use c_str::ToCStr;
 
     #[test]
     fn test_cstring() {
@@ -947,6 +941,6 @@ mod tests {
 
         let input = r"\foo\bar\baz";
         let path: WindowsPath = WindowsPath::new(input.to_c_str());
-        assert_eq!(path.as_str().unwrap(), input.as_slice());
+        assert_eq!(path.as_str().unwrap(), input);
     }
 }
diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs
index 2b444fdc32b..f0a00b421c3 100644
--- a/src/libstd/path/posix.rs
+++ b/src/libstd/path/posix.rs
@@ -15,23 +15,25 @@ use clone::Clone;
 use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
 use hash;
 use io::Writer;
-use iter::{DoubleEndedIterator, AdditiveIterator, Extend, Iterator, Map};
+use iter::{DoubleEndedIteratorExt, AdditiveIterator, Extend};
+use iter::{Iterator, IteratorExt, Map};
+use option::Option;
+use option::Option::{None, Some};
 use kinds::Sized;
-use option::{Option, None, Some};
 use str::{FromStr, Str};
 use str;
-use slice::{CloneSliceAllocPrelude, Splits, AsSlice, VectorVector,
-            PartialEqSlicePrelude, SlicePrelude};
+use slice::{CloneSliceExt, Splits, AsSlice, VectorVector,
+            PartialEqSliceExt, SliceExt};
 use vec::Vec;
 
 use super::{BytesContainer, GenericPath, GenericPathUnsafe};
 
 /// Iterator that yields successive components of a Path as &[u8]
-pub type Components<'a> = Splits<'a, u8>;
+pub type Components<'a> = Splits<'a, u8, fn(&u8) -> bool>;
 
 /// Iterator that yields successive components of a Path as Option<&str>
-pub type StrComponents<'a> = Map<'a, &'a [u8], Option<&'a str>,
-                                       Components<'a>>;
+pub type StrComponents<'a> =
+    Map<&'a [u8], Option<&'a str>, Components<'a>, fn(&[u8]) -> Option<&str>>;
 
 /// Represents a POSIX file path
 #[deriving(Clone)]
@@ -130,7 +132,7 @@ impl GenericPathUnsafe for Path {
     unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T) {
         let filename = filename.container_as_bytes();
         match self.sepidx {
-            None if b".." == self.repr.as_slice() => {
+            None if b".." == self.repr => {
                 let mut v = Vec::with_capacity(3 + filename.len());
                 v.push_all(dot_dot_static);
                 v.push(SEP_BYTE);
@@ -157,7 +159,7 @@ impl GenericPathUnsafe for Path {
                 self.repr = Path::normalize(v.as_slice());
             }
         }
-        self.sepidx = self.repr.as_slice().rposition_elem(&SEP_BYTE);
+        self.sepidx = self.repr.rposition_elem(&SEP_BYTE);
     }
 
     unsafe fn push_unchecked<T: BytesContainer>(&mut self, path: T) {
@@ -173,7 +175,7 @@ impl GenericPathUnsafe for Path {
                 // FIXME: this is slow
                 self.repr = Path::normalize(v.as_slice());
             }
-            self.sepidx = self.repr.as_slice().rposition_elem(&SEP_BYTE);
+            self.sepidx = self.repr.rposition_elem(&SEP_BYTE);
         }
     }
 }
@@ -190,7 +192,7 @@ impl GenericPath for Path {
 
     fn dirname<'a>(&'a self) -> &'a [u8] {
         match self.sepidx {
-            None if b".." == self.repr.as_slice() => self.repr.as_slice(),
+            None if b".." == self.repr => self.repr.as_slice(),
             None => dot_static,
             Some(0) => self.repr[..1],
             Some(idx) if self.repr[idx+1..] == b".." => self.repr.as_slice(),
@@ -200,8 +202,8 @@ impl GenericPath for Path {
 
     fn filename<'a>(&'a self) -> Option<&'a [u8]> {
         match self.sepidx {
-            None if b"." == self.repr.as_slice() ||
-                b".." == self.repr.as_slice() => None,
+            None if b"." == self.repr ||
+                b".." == self.repr => None,
             None => Some(self.repr.as_slice()),
             Some(idx) if self.repr[idx+1..] == b".." => None,
             Some(0) if self.repr[1..].is_empty() => None,
@@ -211,20 +213,20 @@ impl GenericPath for Path {
 
     fn pop(&mut self) -> bool {
         match self.sepidx {
-            None if b"." == self.repr.as_slice() => false,
+            None if b"." == self.repr => false,
             None => {
                 self.repr = vec![b'.'];
                 self.sepidx = None;
                 true
             }
-            Some(0) if b"/" == self.repr.as_slice() => false,
+            Some(0) if b"/" == self.repr => false,
             Some(idx) => {
                 if idx == 0 {
                     self.repr.truncate(idx+1);
                 } else {
                     self.repr.truncate(idx);
                 }
-                self.sepidx = self.repr.as_slice().rposition_elem(&SEP_BYTE);
+                self.sepidx = self.repr.rposition_elem(&SEP_BYTE);
                 true
             }
         }
@@ -249,7 +251,7 @@ impl GenericPath for Path {
         } else {
             let mut ita = self.components();
             let mut itb = other.components();
-            if b"." == self.repr.as_slice() {
+            if b"." == self.repr {
                 return match itb.next() {
                     None => true,
                     Some(b) => b != b".."
@@ -304,7 +306,7 @@ impl GenericPath for Path {
                     }
                 }
             }
-            Some(Path::new(comps.as_slice().connect_vec(&SEP_BYTE)))
+            Some(Path::new(comps.connect_vec(&SEP_BYTE)))
         }
     }
 
@@ -388,6 +390,7 @@ impl Path {
         let v = if self.repr[0] == SEP_BYTE {
             self.repr[1..]
         } else { self.repr.as_slice() };
+        let is_sep_byte: fn(&u8) -> bool = is_sep_byte; // coerce to fn ptr
         let mut ret = v.split(is_sep_byte);
         if v.is_empty() {
             // consume the empty "" component
@@ -399,13 +402,17 @@ impl Path {
     /// Returns an iterator that yields each component of the path as Option<&str>.
     /// See components() for details.
     pub fn str_components<'a>(&'a self) -> StrComponents<'a> {
-        self.components().map(str::from_utf8)
+        fn from_utf8(s: &[u8]) -> Option<&str> {
+            str::from_utf8(s).ok()
+        }
+        let f: fn(&[u8]) -> Option<&str> = from_utf8; // coerce to fn ptr
+        self.components().map(f)
     }
 }
 
 // None result means the byte vector didn't need normalizing
 fn normalize_helper<'a>(v: &'a [u8], is_abs: bool) -> Option<Vec<&'a [u8]>> {
-    if is_abs && v.as_slice().is_empty() {
+    if is_abs && v.is_empty() {
         return None;
     }
     let mut comps: Vec<&'a [u8]> = vec![];
@@ -442,11 +449,9 @@ static dot_dot_static: &'static [u8] = b"..";
 mod tests {
     use prelude::*;
     use super::*;
-    use mem;
     use str;
-    use str::StrPrelude;
 
-    macro_rules! t(
+    macro_rules! t {
         (s: $path:expr, $exp:expr) => (
             {
                 let path = $path;
@@ -459,7 +464,7 @@ mod tests {
                 assert!(path.as_vec() == $exp);
             }
         )
-    )
+    }
 
     #[test]
     fn test_paths() {
@@ -495,8 +500,8 @@ mod tests {
         t!(s: Path::new("foo/../../.."), "../..");
         t!(s: Path::new("foo/../../bar"), "../bar");
 
-        assert_eq!(Path::new(b"foo/bar").into_vec().as_slice(), b"foo/bar");
-        assert_eq!(Path::new(b"/foo/../../bar").into_vec().as_slice(),
+        assert_eq!(Path::new(b"foo/bar").into_vec(), b"foo/bar");
+        assert_eq!(Path::new(b"/foo/../../bar").into_vec(),
                    b"/bar");
 
         let p = Path::new(b"foo/bar\x80");
@@ -513,62 +518,62 @@ mod tests {
 
     #[test]
     fn test_null_byte() {
-        use task;
-        let result = task::try(proc() {
+        use thread::Thread;
+        let result = Thread::spawn(move|| {
             Path::new(b"foo/bar\0")
-        });
+        }).join();
         assert!(result.is_err());
 
-        let result = task::try(proc() {
+        let result = Thread::spawn(move|| {
             Path::new("test").set_filename(b"f\0o")
-        });
+        }).join();
         assert!(result.is_err());
 
-        let result = task::try(proc() {
+        let result = Thread::spawn(move|| {
             Path::new("test").push(b"f\0o");
-        });
+        }).join();
         assert!(result.is_err());
     }
 
     #[test]
     fn test_display_str() {
-        macro_rules! t(
+        macro_rules! t {
             ($path:expr, $disp:ident, $exp:expr) => (
                 {
                     let path = Path::new($path);
-                    assert!(path.$disp().to_string().as_slice() == $exp);
+                    assert!(path.$disp().to_string() == $exp);
                 }
             )
-        )
+        }
         t!("foo", display, "foo");
-        t!(b"foo\x80", display, "foo\uFFFD");
-        t!(b"foo\xFFbar", display, "foo\uFFFDbar");
+        t!(b"foo\x80", display, "foo\u{FFFD}");
+        t!(b"foo\xFFbar", display, "foo\u{FFFD}bar");
         t!(b"foo\xFF/bar", filename_display, "bar");
-        t!(b"foo/\xFFbar", filename_display, "\uFFFDbar");
+        t!(b"foo/\xFFbar", filename_display, "\u{FFFD}bar");
         t!(b"/", filename_display, "");
 
         macro_rules! t(
             ($path:expr, $exp:expr) => (
                 {
                     let path = Path::new($path);
-                    let mo = path.display().as_maybe_owned();
+                    let mo = path.display().as_cow();
                     assert!(mo.as_slice() == $exp);
                 }
             );
             ($path:expr, $exp:expr, filename) => (
                 {
                     let path = Path::new($path);
-                    let mo = path.filename_display().as_maybe_owned();
+                    let mo = path.filename_display().as_cow();
                     assert!(mo.as_slice() == $exp);
                 }
             )
-        )
+        );
 
         t!("foo", "foo");
-        t!(b"foo\x80", "foo\uFFFD");
-        t!(b"foo\xFFbar", "foo\uFFFDbar");
+        t!(b"foo\x80", "foo\u{FFFD}");
+        t!(b"foo\xFFbar", "foo\u{FFFD}bar");
         t!(b"foo\xFF/bar", "bar", filename);
-        t!(b"foo/\xFFbar", "\uFFFDbar", filename);
+        t!(b"foo/\xFFbar", "\u{FFFD}bar", filename);
         t!(b"/", "", filename);
     }
 
@@ -579,20 +584,20 @@ mod tests {
                 {
                     let path = Path::new($path);
                     let f = format!("{}", path.display());
-                    assert!(f.as_slice() == $exp);
+                    assert!(f == $exp);
                     let f = format!("{}", path.filename_display());
-                    assert!(f.as_slice() == $expf);
+                    assert!(f == $expf);
                 }
             )
-        )
+        );
 
         t!(b"foo", "foo", "foo");
         t!(b"foo/bar", "foo/bar", "bar");
         t!(b"/", "/", "");
-        t!(b"foo\xFF", "foo\uFFFD", "foo\uFFFD");
-        t!(b"foo\xFF/bar", "foo\uFFFD/bar", "bar");
-        t!(b"foo/\xFFbar", "foo/\uFFFDbar", "\uFFFDbar");
-        t!(b"\xFFfoo/bar\xFF", "\uFFFDfoo/bar\uFFFD", "bar\uFFFD");
+        t!(b"foo\xFF", "foo\u{FFFD}", "foo\u{FFFD}");
+        t!(b"foo\xFF/bar", "foo\u{FFFD}/bar", "bar");
+        t!(b"foo/\xFFbar", "foo/\u{FFFD}bar", "\u{FFFD}bar");
+        t!(b"\xFFfoo/bar\xFF", "\u{FFFD}foo/bar\u{FFFD}", "bar\u{FFFD}");
     }
 
     #[test]
@@ -600,10 +605,8 @@ mod tests {
         macro_rules! t(
             (s: $path:expr, $op:ident, $exp:expr) => (
                 {
-                    unsafe {
-                        let path = Path::new($path);
-                        assert!(path.$op() == mem::transmute(($exp).as_bytes()));
-                    }
+                    let path = Path::new($path);
+                    assert!(path.$op() == ($exp).as_bytes());
                 }
             );
             (s: $path:expr, $op:ident, $exp:expr, opt) => (
@@ -615,14 +618,12 @@ mod tests {
             );
             (v: $path:expr, $op:ident, $exp:expr) => (
                 {
-                    unsafe {
-                        let arg = $path;
-                        let path = Path::new(arg);
-                        assert!(path.$op() == mem::transmute($exp));
-                    }
+                    let arg = $path;
+                    let path = Path::new(arg);
+                    assert!(path.$op() == $exp);
                 }
             );
-        )
+        );
 
         t!(v: b"a/b/c", filename, Some(b"c"));
         t!(v: b"a/b/c\xFF", filename, Some(b"c\xFF"));
@@ -667,9 +668,8 @@ mod tests {
         t!(v: b"hi/there.txt", extension, Some(b"txt"));
         t!(v: b"hi/there\x80.txt", extension, Some(b"txt"));
         t!(v: b"hi/there.t\x80xt", extension, Some(b"t\x80xt"));
-        let no: Option<&'static [u8]> = None;
-        t!(v: b"hi/there", extension, no);
-        t!(v: b"hi/there\x80", extension, no);
+        t!(v: b"hi/there", extension, None);
+        t!(v: b"hi/there\x80", extension, None);
         t!(s: "hi/there.txt", extension, Some("txt"), opt);
         t!(s: "hi/there", extension, None, opt);
         t!(s: "there.txt", extension, Some("txt"), opt);
@@ -697,7 +697,7 @@ mod tests {
                     assert!(p1 == p2.join(join));
                 }
             )
-        )
+        );
 
         t!(s: "a/b/c", "..");
         t!(s: "/a/b/c", "d");
@@ -716,7 +716,7 @@ mod tests {
                     assert!(p.as_str() == Some($exp));
                 }
             )
-        )
+        );
 
         t!(s: "a/b/c", "d", "a/b/c/d");
         t!(s: "/a/b/c", "d", "/a/b/c/d");
@@ -743,7 +743,7 @@ mod tests {
                     assert!(p.as_vec() == $exp);
                 }
             )
-        )
+        );
 
         t!(s: "a/b/c", ["d", "e"], "a/b/c/d/e");
         t!(s: "a/b/c", ["d", "/e"], "/e");
@@ -773,7 +773,7 @@ mod tests {
                     assert!(result == $right);
                 }
             )
-        )
+        );
 
         t!(b: b"a/b/c", b"a/b", true);
         t!(b: b"a", b".", true);
@@ -821,7 +821,7 @@ mod tests {
                     assert!(res.as_str() == Some($exp));
                 }
             )
-        )
+        );
 
         t!(s: "a/b/c", "..", "a/b");
         t!(s: "/a/b/c", "d", "/a/b/c/d");
@@ -848,7 +848,7 @@ mod tests {
                     assert!(res.as_vec() == $exp);
                 }
             )
-        )
+        );
 
         t!(s: "a/b/c", ["d", "e"], "a/b/c/d/e");
         t!(s: "a/b/c", ["..", "d"], "a/b/d");
@@ -932,7 +932,7 @@ mod tests {
                     assert!(p1 == p2.$with(arg));
                 }
             )
-        )
+        );
 
         t!(v: b"a/b/c", set_filename, with_filename, b"d");
         t!(v: b"/", set_filename, with_filename, b"foo");
@@ -958,62 +958,57 @@ mod tests {
         macro_rules! t(
             (s: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
                 {
-                    unsafe {
-                        let path = $path;
-                        let filename = $filename;
-                        assert!(path.filename_str() == filename,
-                                "{}.filename_str(): Expected `{}`, found {}",
-                                path.as_str().unwrap(), filename, path.filename_str());
-                        let dirname = $dirname;
-                        assert!(path.dirname_str() == dirname,
-                                "`{}`.dirname_str(): Expected `{}`, found `{}`",
-                                path.as_str().unwrap(), dirname, path.dirname_str());
-                        let filestem = $filestem;
-                        assert!(path.filestem_str() == filestem,
-                                "`{}`.filestem_str(): Expected `{}`, found `{}`",
-                                path.as_str().unwrap(), filestem, path.filestem_str());
-                        let ext = $ext;
-                        assert!(path.extension_str() == mem::transmute(ext),
-                                "`{}`.extension_str(): Expected `{}`, found `{}`",
-                                path.as_str().unwrap(), ext, path.extension_str());
-                    }
+                    let path = $path;
+                    let filename = $filename;
+                    assert!(path.filename_str() == filename,
+                            "{}.filename_str(): Expected `{}`, found {}",
+                            path.as_str().unwrap(), filename, path.filename_str());
+                    let dirname = $dirname;
+                    assert!(path.dirname_str() == dirname,
+                            "`{}`.dirname_str(): Expected `{}`, found `{}`",
+                            path.as_str().unwrap(), dirname, path.dirname_str());
+                    let filestem = $filestem;
+                    assert!(path.filestem_str() == filestem,
+                            "`{}`.filestem_str(): Expected `{}`, found `{}`",
+                            path.as_str().unwrap(), filestem, path.filestem_str());
+                    let ext = $ext;
+                    assert!(path.extension_str() == ext,
+                            "`{}`.extension_str(): Expected `{}`, found `{}`",
+                            path.as_str().unwrap(), ext, path.extension_str());
                 }
             );
             (v: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
                 {
-                    unsafe {
-                        let path = $path;
-                        assert!(path.filename() == mem::transmute($filename));
-                        assert!(path.dirname() == mem::transmute($dirname));
-                        assert!(path.filestem() == mem::transmute($filestem));
-                        assert!(path.extension() == mem::transmute($ext));
-                    }
+                    let path = $path;
+                    assert!(path.filename() == $filename);
+                    assert!(path.dirname() == $dirname);
+                    assert!(path.filestem() == $filestem);
+                    assert!(path.extension() == $ext);
                 }
             )
-        )
+        );
 
-        let no: Option<&'static str> = None;
-        t!(v: Path::new(b"a/b/c"), Some(b"c"), b"a/b", Some(b"c"), no);
-        t!(v: Path::new(b"a/b/\xFF"), Some(b"\xFF"), b"a/b", Some(b"\xFF"), no);
+        t!(v: Path::new(b"a/b/c"), Some(b"c"), b"a/b", Some(b"c"), None);
+        t!(v: Path::new(b"a/b/\xFF"), Some(b"\xFF"), b"a/b", Some(b"\xFF"), None);
         t!(v: Path::new(b"hi/there.\xFF"), Some(b"there.\xFF"), b"hi",
               Some(b"there"), Some(b"\xFF"));
-        t!(s: Path::new("a/b/c"), Some("c"), Some("a/b"), Some("c"), no);
-        t!(s: Path::new("."), None, Some("."), None, no);
-        t!(s: Path::new("/"), None, Some("/"), None, no);
-        t!(s: Path::new(".."), None, Some(".."), None, no);
-        t!(s: Path::new("../.."), None, Some("../.."), None, no);
+        t!(s: Path::new("a/b/c"), Some("c"), Some("a/b"), Some("c"), None);
+        t!(s: Path::new("."), None, Some("."), None, None);
+        t!(s: Path::new("/"), None, Some("/"), None, None);
+        t!(s: Path::new(".."), None, Some(".."), None, None);
+        t!(s: Path::new("../.."), None, Some("../.."), None, None);
         t!(s: Path::new("hi/there.txt"), Some("there.txt"), Some("hi"),
               Some("there"), Some("txt"));
-        t!(s: Path::new("hi/there"), Some("there"), Some("hi"), Some("there"), no);
+        t!(s: Path::new("hi/there"), Some("there"), Some("hi"), Some("there"), None);
         t!(s: Path::new("hi/there."), Some("there."), Some("hi"),
               Some("there"), Some(""));
-        t!(s: Path::new("hi/.there"), Some(".there"), Some("hi"), Some(".there"), no);
+        t!(s: Path::new("hi/.there"), Some(".there"), Some("hi"), Some(".there"), None);
         t!(s: Path::new("hi/..there"), Some("..there"), Some("hi"),
               Some("."), Some("there"));
-        t!(s: Path::new(b"a/b/\xFF"), None, Some("a/b"), None, no);
+        t!(s: Path::new(b"a/b/\xFF"), None, Some("a/b"), None, None);
         t!(s: Path::new(b"a/b/\xFF.txt"), None, Some("a/b"), None, Some("txt"));
-        t!(s: Path::new(b"a/b/c.\x80"), None, Some("a/b"), Some("c"), no);
-        t!(s: Path::new(b"\xFF/b"), Some("b"), None, Some("b"), no);
+        t!(s: Path::new(b"a/b/c.\x80"), None, Some("a/b"), Some("c"), None);
+        t!(s: Path::new(b"\xFF/b"), Some("b"), None, Some("b"), None);
     }
 
     #[test]
@@ -1038,7 +1033,7 @@ mod tests {
                     assert_eq!(path.is_relative(), $rel);
                 }
             )
-        )
+        );
         t!(s: "a/b/c", false, true);
         t!(s: "/a/b/c", true, false);
         t!(s: "a", false, true);
@@ -1059,7 +1054,7 @@ mod tests {
                     assert_eq!(path.is_ancestor_of(&dest), $exp);
                 }
             )
-        )
+        );
 
         t!(s: "a/b/c", "a/b/c/d", true);
         t!(s: "a/b/c", "a/b/c", true);
@@ -1100,7 +1095,7 @@ mod tests {
                     assert_eq!(path.ends_with_path(&child), $exp);
                 }
             )
-        )
+        );
 
         t!(s: "a/b/c", "c", true);
         t!(s: "a/b/c", "d", false);
@@ -1133,7 +1128,7 @@ mod tests {
                     assert_eq!(res.as_ref().and_then(|x| x.as_str()), $exp);
                 }
             )
-        )
+        );
 
         t!(s: "a/b/c", "a/b", Some("c"));
         t!(s: "a/b/c", "a/b/d", Some("../c"));
@@ -1189,13 +1184,13 @@ mod tests {
                     let path = Path::new($arg);
                     let comps = path.components().collect::<Vec<&[u8]>>();
                     let exp: &[&[u8]] = &[$($exp),*];
-                    assert_eq!(comps.as_slice(), exp);
+                    assert_eq!(comps, exp);
                     let comps = path.components().rev().collect::<Vec<&[u8]>>();
                     let exp = exp.iter().rev().map(|&x|x).collect::<Vec<&[u8]>>();
                     assert_eq!(comps, exp)
                 }
             )
-        )
+        );
 
         t!(b: b"a/b/c", [b"a", b"b", b"c"]);
         t!(b: b"/\xFF/a/\x80", [b"\xFF", b"a", b"\x80"]);
@@ -1221,13 +1216,13 @@ mod tests {
                     let path = Path::new($arg);
                     let comps = path.str_components().collect::<Vec<Option<&str>>>();
                     let exp: &[Option<&str>] = &$exp;
-                    assert_eq!(comps.as_slice(), exp);
+                    assert_eq!(comps, exp);
                     let comps = path.str_components().rev().collect::<Vec<Option<&str>>>();
                     let exp = exp.iter().rev().map(|&x|x).collect::<Vec<Option<&str>>>();
                     assert_eq!(comps, exp);
                 }
             )
-        )
+        );
 
         t!(b: b"a/b/c", [Some("a"), Some("b"), Some("c")]);
         t!(b: b"/\xFF/a/\x80", [None, Some("a"), None]);
diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs
index f31ffdab17b..7d10188c437 100644
--- a/src/libstd/path/windows.rs
+++ b/src/libstd/path/windows.rs
@@ -12,7 +12,7 @@
 
 //! Windows file path handling
 
-pub use self::PathPrefix::*;
+use self::PathPrefix::*;
 
 use ascii::AsciiCast;
 use c_str::{CString, ToCStr};
@@ -20,12 +20,14 @@ use clone::Clone;
 use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
 use hash;
 use io::Writer;
-use iter::{AdditiveIterator, DoubleEndedIterator, Extend, Iterator, Map};
+use iter::{AdditiveIterator, DoubleEndedIteratorExt, Extend};
+use iter::{Iterator, IteratorExt, Map};
 use mem;
-use option::{Option, Some, None};
-use slice::{AsSlice, SlicePrelude};
-use str::{CharSplits, FromStr, Str, StrAllocating, StrVector, StrPrelude};
-use string::String;
+use option::Option;
+use option::Option::{Some, None};
+use slice::SliceExt;
+use str::{CharSplits, FromStr, StrVector, StrExt};
+use string::{String, ToString};
 use unicode::char::UnicodeChar;
 use vec::Vec;
 
@@ -35,12 +37,12 @@ use super::{contains_nul, BytesContainer, GenericPath, GenericPathUnsafe};
 ///
 /// Each component is yielded as Option<&str> for compatibility with PosixPath, but
 /// every component in WindowsPath is guaranteed to be Some.
-pub type StrComponents<'a> = Map<'a, &'a str, Option<&'a str>,
-                                       CharSplits<'a, char>>;
+pub type StrComponents<'a> =
+    Map<&'a str, Option<&'a str>, CharSplits<'a, char>, fn(&'a str) -> Option<&'a str>>;
 
 /// Iterator that yields successive components of a Path as &[u8]
-pub type Components<'a> = Map<'a, Option<&'a str>, &'a [u8],
-                                    StrComponents<'a>>;
+pub type Components<'a> =
+    Map<Option<&'a str>, &'a [u8], StrComponents<'a>, fn(Option<&str>) -> &[u8]>;
 
 /// Represents a Windows path
 // Notes for Windows path impl:
@@ -180,35 +182,35 @@ impl GenericPathUnsafe for Path {
     unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T) {
         let filename = filename.container_as_str().unwrap();
         match self.sepidx_or_prefix_len() {
-            None if ".." == self.repr.as_slice() => {
+            None if ".." == self.repr => {
                 let mut s = String::with_capacity(3 + filename.len());
                 s.push_str("..");
                 s.push(SEP);
                 s.push_str(filename);
-                self.update_normalized(s);
+                self.update_normalized(s[]);
             }
             None => {
                 self.update_normalized(filename);
             }
-            Some((_,idxa,end)) if self.repr.as_slice().slice(idxa,end) == ".." => {
+            Some((_,idxa,end)) if self.repr[idxa..end] == ".." => {
                 let mut s = String::with_capacity(end + 1 + filename.len());
-                s.push_str(self.repr.as_slice().slice_to(end));
+                s.push_str(self.repr[0..end]);
                 s.push(SEP);
                 s.push_str(filename);
-                self.update_normalized(s);
+                self.update_normalized(s[]);
             }
             Some((idxb,idxa,_)) if self.prefix == Some(DiskPrefix) && idxa == self.prefix_len() => {
                 let mut s = String::with_capacity(idxb + filename.len());
-                s.push_str(self.repr.as_slice().slice_to(idxb));
+                s.push_str(self.repr[0..idxb]);
                 s.push_str(filename);
-                self.update_normalized(s);
+                self.update_normalized(s[]);
             }
             Some((idxb,_,_)) => {
                 let mut s = String::with_capacity(idxb + 1 + filename.len());
-                s.push_str(self.repr.as_slice().slice_to(idxb));
+                s.push_str(self.repr[0..idxb]);
                 s.push(SEP);
                 s.push_str(filename);
-                self.update_normalized(s);
+                self.update_normalized(s[]);
             }
         }
     }
@@ -227,18 +229,18 @@ impl GenericPathUnsafe for Path {
         let path = path.container_as_str().unwrap();
         fn is_vol_abs(path: &str, prefix: Option<PathPrefix>) -> bool {
             // assume prefix is Some(DiskPrefix)
-            let rest = path.slice_from(prefix_len(prefix));
+            let rest = path[prefix_len(prefix)..];
             !rest.is_empty() && rest.as_bytes()[0].is_ascii() && is_sep(rest.as_bytes()[0] as char)
         }
         fn shares_volume(me: &Path, path: &str) -> bool {
             // path is assumed to have a prefix of Some(DiskPrefix)
-            let repr = me.repr.as_slice();
+            let repr = me.repr[];
             match me.prefix {
                 Some(DiskPrefix) => {
-                    repr.as_bytes()[0] == path.as_bytes()[0].to_ascii().to_uppercase().to_byte()
+                    repr.as_bytes()[0] == path.as_bytes()[0].to_ascii().to_uppercase().as_byte()
                 }
                 Some(VerbatimDiskPrefix) => {
-                    repr.as_bytes()[4] == path.as_bytes()[0].to_ascii().to_uppercase().to_byte()
+                    repr.as_bytes()[4] == path.as_bytes()[0].to_ascii().to_uppercase().as_byte()
                 }
                 _ => false
             }
@@ -264,7 +266,7 @@ impl GenericPathUnsafe for Path {
                         else { None };
             let pathlen = path_.as_ref().map_or(path.len(), |p| p.len());
             let mut s = String::with_capacity(me.repr.len() + 1 + pathlen);
-            s.push_str(me.repr.as_slice());
+            s.push_str(me.repr[]);
             let plen = me.prefix_len();
             // if me is "C:" we don't want to add a path separator
             match me.prefix {
@@ -276,9 +278,9 @@ impl GenericPathUnsafe for Path {
             }
             match path_ {
                 None => s.push_str(path),
-                Some(p) => s.push_str(p.as_slice())
+                Some(p) => s.push_str(p[]),
             };
-            me.update_normalized(s)
+            me.update_normalized(s[])
         }
 
         if !path.is_empty() {
@@ -286,7 +288,7 @@ impl GenericPathUnsafe for Path {
             match prefix {
                 Some(DiskPrefix) if !is_vol_abs(path, prefix) && shares_volume(self, path) => {
                     // cwd-relative path, self is on the same volume
-                    append_path(self, path.slice_from(prefix_len(prefix)));
+                    append_path(self, path[prefix_len(prefix)..]);
                 }
                 Some(_) => {
                     // absolute path, or cwd-relative and self is not same volume
@@ -332,7 +334,7 @@ impl GenericPath for Path {
     /// Always returns a `Some` value.
     #[inline]
     fn as_str<'a>(&'a self) -> Option<&'a str> {
-        Some(self.repr.as_slice())
+        Some(self.repr[])
     }
 
     #[inline]
@@ -354,21 +356,17 @@ impl GenericPath for Path {
     /// Always returns a `Some` value.
     fn dirname_str<'a>(&'a self) -> Option<&'a str> {
         Some(match self.sepidx_or_prefix_len() {
-            None if ".." == self.repr.as_slice() => self.repr.as_slice(),
+            None if ".." == self.repr => self.repr[],
             None => ".",
-            Some((_,idxa,end)) if self.repr.as_slice().slice(idxa, end) == ".." => {
-                self.repr.as_slice()
-            }
-            Some((idxb,_,end)) if self.repr.as_slice().slice(idxb, end) == "\\" => {
-                self.repr.as_slice()
-            }
-            Some((0,idxa,_)) => self.repr.as_slice().slice_to(idxa),
+            Some((_,idxa,end)) if self.repr[idxa..end] == ".." => self.repr[],
+            Some((idxb,_,end)) if self.repr[idxb..end] == "\\" => self.repr[],
+            Some((0,idxa,_)) => self.repr[0..idxa],
             Some((idxb,idxa,_)) => {
                 match self.prefix {
                     Some(DiskPrefix) | Some(VerbatimDiskPrefix) if idxb == self.prefix_len() => {
-                        self.repr.as_slice().slice_to(idxa)
+                        self.repr[0..idxa]
                     }
-                    _ => self.repr.as_slice().slice_to(idxb)
+                    _ => self.repr[0..idxb]
                 }
             }
         })
@@ -382,13 +380,13 @@ impl GenericPath for Path {
     /// See `GenericPath::filename_str` for info.
     /// Always returns a `Some` value if `filename` returns a `Some` value.
     fn filename_str<'a>(&'a self) -> Option<&'a str> {
-        let repr = self.repr.as_slice();
+        let repr = self.repr[];
         match self.sepidx_or_prefix_len() {
             None if "." == repr || ".." == repr => None,
             None => Some(repr),
-            Some((_,idxa,end)) if repr.slice(idxa, end) == ".." => None,
+            Some((_,idxa,end)) if repr[idxa..end] == ".." => None,
             Some((_,idxa,end)) if idxa == end => None,
-            Some((_,idxa,end)) => Some(repr.slice(idxa, end))
+            Some((_,idxa,end)) => Some(repr[idxa..end])
         }
     }
 
@@ -413,14 +411,14 @@ impl GenericPath for Path {
     #[inline]
     fn pop(&mut self) -> bool {
         match self.sepidx_or_prefix_len() {
-            None if "." == self.repr.as_slice() => false,
+            None if "." == self.repr => false,
             None => {
                 self.repr = String::from_str(".");
                 self.sepidx = None;
                 true
             }
             Some((idxb,idxa,end)) if idxb == idxa && idxb == end => false,
-            Some((idxb,_,end)) if self.repr.as_slice().slice(idxb, end) == "\\" => false,
+            Some((idxb,_,end)) if self.repr[idxb..end] == "\\" => false,
             Some((idxb,idxa,_)) => {
                 let trunc = match self.prefix {
                     Some(DiskPrefix) | Some(VerbatimDiskPrefix) | None => {
@@ -440,15 +438,15 @@ impl GenericPath for Path {
         if self.prefix.is_some() {
             Some(Path::new(match self.prefix {
                 Some(DiskPrefix) if self.is_absolute() => {
-                    self.repr.as_slice().slice_to(self.prefix_len()+1)
+                    self.repr[0..self.prefix_len()+1]
                 }
                 Some(VerbatimDiskPrefix) => {
-                    self.repr.as_slice().slice_to(self.prefix_len()+1)
+                    self.repr[0..self.prefix_len()+1]
                 }
-                _ => self.repr.as_slice().slice_to(self.prefix_len())
+                _ => self.repr[0..self.prefix_len()]
             }))
         } else if is_vol_relative(self) {
-            Some(Path::new(self.repr.as_slice().slice_to(1)))
+            Some(Path::new(self.repr[0..1]))
         } else {
             None
         }
@@ -467,7 +465,7 @@ impl GenericPath for Path {
     fn is_absolute(&self) -> bool {
         match self.prefix {
             Some(DiskPrefix) => {
-                let rest = self.repr.as_slice().slice_from(self.prefix_len());
+                let rest = self.repr[self.prefix_len()..];
                 rest.len() > 0 && rest.as_bytes()[0] == SEP_BYTE
             }
             Some(_) => true,
@@ -489,7 +487,7 @@ impl GenericPath for Path {
         } else {
             let mut ita = self.str_components().map(|x|x.unwrap());
             let mut itb = other.str_components().map(|x|x.unwrap());
-            if "." == self.repr.as_slice() {
+            if "." == self.repr {
                 return itb.next() != Some("..");
             }
             loop {
@@ -642,18 +640,19 @@ impl Path {
     /// Does not distinguish between absolute and cwd-relative paths, e.g.
     /// C:\foo and C:foo.
     pub fn str_components<'a>(&'a self) -> StrComponents<'a> {
-        let repr = self.repr.as_slice();
+        let repr = self.repr[];
         let s = match self.prefix {
             Some(_) => {
                 let plen = self.prefix_len();
                 if repr.len() > plen && repr.as_bytes()[plen] == SEP_BYTE {
-                    repr.slice_from(plen+1)
-                } else { repr.slice_from(plen) }
+                    repr[plen+1..]
+                } else { repr[plen..] }
             }
-            None if repr.as_bytes()[0] == SEP_BYTE => repr.slice_from(1),
+            None if repr.as_bytes()[0] == SEP_BYTE => repr[1..],
             None => repr
         };
-        let ret = s.split_terminator(SEP).map(Some);
+        let some: fn(&'a str) -> Option<&'a str> = Some; // coerce to fn ptr
+        let ret = s.split_terminator(SEP).map(some);
         ret
     }
 
@@ -664,47 +663,51 @@ impl Path {
             #![inline]
             x.unwrap().as_bytes()
         }
+        let convert: for<'b> fn(Option<&'b str>) -> &'b [u8] = convert; // coerce to fn ptr
         self.str_components().map(convert)
     }
 
     fn equiv_prefix(&self, other: &Path) -> bool {
-        let s_repr = self.repr.as_slice();
-        let o_repr = other.repr.as_slice();
+        let s_repr = self.repr[];
+        let o_repr = other.repr[];
         match (self.prefix, other.prefix) {
             (Some(DiskPrefix), Some(VerbatimDiskPrefix)) => {
                 self.is_absolute() &&
-                    s_repr.as_bytes()[0].to_ascii().eq_ignore_case(o_repr.as_bytes()[4].to_ascii())
+                    s_repr.as_bytes()[0].to_ascii().to_lowercase() ==
+                        o_repr.as_bytes()[4].to_ascii().to_lowercase()
             }
             (Some(VerbatimDiskPrefix), Some(DiskPrefix)) => {
                 other.is_absolute() &&
-                    s_repr.as_bytes()[4].to_ascii().eq_ignore_case(o_repr.as_bytes()[0].to_ascii())
+                    s_repr.as_bytes()[4].to_ascii().to_lowercase() ==
+                        o_repr.as_bytes()[0].to_ascii().to_lowercase()
             }
             (Some(VerbatimDiskPrefix), Some(VerbatimDiskPrefix)) => {
-                s_repr.as_bytes()[4].to_ascii().eq_ignore_case(o_repr.as_bytes()[4].to_ascii())
+                s_repr.as_bytes()[4].to_ascii().to_lowercase() ==
+                    o_repr.as_bytes()[4].to_ascii().to_lowercase()
             }
             (Some(UNCPrefix(_,_)), Some(VerbatimUNCPrefix(_,_))) => {
-                s_repr.slice(2, self.prefix_len()) == o_repr.slice(8, other.prefix_len())
+                s_repr[2..self.prefix_len()] == o_repr[8..other.prefix_len()]
             }
             (Some(VerbatimUNCPrefix(_,_)), Some(UNCPrefix(_,_))) => {
-                s_repr.slice(8, self.prefix_len()) == o_repr.slice(2, other.prefix_len())
+                s_repr[8..self.prefix_len()] == o_repr[2..other.prefix_len()]
             }
             (None, None) => true,
             (a, b) if a == b => {
-                s_repr.slice_to(self.prefix_len()) == o_repr.slice_to(other.prefix_len())
+                s_repr[0..self.prefix_len()] == o_repr[0..other.prefix_len()]
             }
             _ => false
         }
     }
 
-    fn normalize_<S: StrAllocating>(s: S) -> (Option<PathPrefix>, String) {
+    fn normalize_(s: &str) -> (Option<PathPrefix>, String) {
         // make borrowck happy
         let (prefix, val) = {
-            let prefix = parse_prefix(s.as_slice());
-            let path = Path::normalize__(s.as_slice(), prefix);
+            let prefix = parse_prefix(s);
+            let path = Path::normalize__(s, prefix);
             (prefix, path)
         };
         (prefix, match val {
-            None => s.into_string(),
+            None => s.to_string(),
             Some(val) => val
         })
     }
@@ -744,13 +747,10 @@ impl Path {
                         match prefix.unwrap() {
                             DiskPrefix => {
                                 let len = prefix_len(prefix) + is_abs as uint;
-                                let mut s = String::from_str(s.slice_to(len));
+                                let mut s = String::from_str(s[0..len]);
                                 unsafe {
                                     let v = s.as_mut_vec();
-                                    v[0] = (*v)[0]
-                                                     .to_ascii()
-                                                     .to_uppercase()
-                                                     .to_byte();
+                                    v[0] = (*v)[0].to_ascii().to_uppercase().as_byte();
                                 }
                                 if is_abs {
                                     // normalize C:/ to C:\
@@ -762,24 +762,24 @@ impl Path {
                             }
                             VerbatimDiskPrefix => {
                                 let len = prefix_len(prefix) + is_abs as uint;
-                                let mut s = String::from_str(s.slice_to(len));
+                                let mut s = String::from_str(s[0..len]);
                                 unsafe {
                                     let v = s.as_mut_vec();
-                                    v[4] = (*v)[4].to_ascii().to_uppercase().to_byte();
+                                    v[4] = (*v)[4].to_ascii().to_uppercase().as_byte();
                                 }
                                 Some(s)
                             }
                             _ => {
                                 let plen = prefix_len(prefix);
                                 if s.len() > plen {
-                                    Some(String::from_str(s.slice_to(plen)))
+                                    Some(String::from_str(s[0..plen]))
                                 } else { None }
                             }
                         }
                     } else if is_abs && comps.is_empty() {
                         Some(String::from_char(1, SEP))
                     } else {
-                        let prefix_ = s.slice_to(prefix_len(prefix));
+                        let prefix_ = s[0..prefix_len(prefix)];
                         let n = prefix_.len() +
                                 if is_abs { comps.len() } else { comps.len() - 1} +
                                 comps.iter().map(|v| v.len()).sum();
@@ -787,20 +787,20 @@ impl Path {
                         match prefix {
                             Some(DiskPrefix) => {
                                 s.push(prefix_.as_bytes()[0].to_ascii()
-                                                   .to_uppercase().to_char());
+                                                   .to_uppercase().as_char());
                                 s.push(':');
                             }
                             Some(VerbatimDiskPrefix) => {
-                                s.push_str(prefix_.slice_to(4));
+                                s.push_str(prefix_[0..4]);
                                 s.push(prefix_.as_bytes()[4].to_ascii()
-                                                   .to_uppercase().to_char());
-                                s.push_str(prefix_.slice_from(5));
+                                                   .to_uppercase().as_char());
+                                s.push_str(prefix_[5..]);
                             }
                             Some(UNCPrefix(a,b)) => {
                                 s.push_str("\\\\");
-                                s.push_str(prefix_.slice(2, a+2));
+                                s.push_str(prefix_[2..a+2]);
                                 s.push(SEP);
-                                s.push_str(prefix_.slice(3+a, 3+a+b));
+                                s.push_str(prefix_[3+a..3+a+b]);
                             }
                             Some(_) => s.push_str(prefix_),
                             None => ()
@@ -825,10 +825,14 @@ impl Path {
 
     fn update_sepidx(&mut self) {
         let s = if self.has_nonsemantic_trailing_slash() {
-                    self.repr.as_slice().slice_to(self.repr.len()-1)
-                } else { self.repr.as_slice() };
-        let idx = s.rfind(if !prefix_is_verbatim(self.prefix) { is_sep }
-                          else { is_sep_verbatim });
+                    self.repr[0..self.repr.len()-1]
+                } else { self.repr[] };
+        let sep_test: fn(char) -> bool = if !prefix_is_verbatim(self.prefix) {
+            is_sep
+        } else {
+            is_sep_verbatim
+        };
+        let idx = s.rfind(sep_test);
         let prefixlen = self.prefix_len();
         self.sepidx = idx.and_then(|x| if x < prefixlen { None } else { Some(x) });
     }
@@ -858,8 +862,8 @@ impl Path {
             self.repr.as_bytes()[self.repr.len()-1] == SEP_BYTE
     }
 
-    fn update_normalized<S: Str>(&mut self, s: S) {
-        let (prefix, path) = Path::normalize_(s.as_slice());
+    fn update_normalized(&mut self, s: &str) {
+        let (prefix, path) = Path::normalize_(s);
         self.repr = path;
         self.prefix = prefix;
         self.update_sepidx();
@@ -901,17 +905,17 @@ pub fn is_verbatim(path: &Path) -> bool {
 /// non-verbatim, the non-verbatim version is returned.
 /// Otherwise, None is returned.
 pub fn make_non_verbatim(path: &Path) -> Option<Path> {
-    let repr = path.repr.as_slice();
+    let repr = path.repr[];
     let new_path = match path.prefix {
         Some(VerbatimPrefix(_)) | Some(DeviceNSPrefix(_)) => return None,
         Some(UNCPrefix(_,_)) | Some(DiskPrefix) | None => return Some(path.clone()),
         Some(VerbatimDiskPrefix) => {
             // \\?\D:\
-            Path::new(repr.slice_from(4))
+            Path::new(repr[4..])
         }
         Some(VerbatimUNCPrefix(_,_)) => {
             // \\?\UNC\server\share
-            Path::new(format!(r"\{}", repr.slice_from(7)))
+            Path::new(format!(r"\{}", repr[7..]))
         }
     };
     if new_path.prefix.is_none() {
@@ -920,8 +924,8 @@ pub fn make_non_verbatim(path: &Path) -> Option<Path> {
         return None;
     }
     // now ensure normalization didn't change anything
-    if repr.slice_from(path.prefix_len()) ==
-        new_path.repr.as_slice().slice_from(new_path.prefix_len()) {
+    if repr[path.prefix_len()..] ==
+        new_path.repr[new_path.prefix_len()..] {
         Some(new_path)
     } else {
         None
@@ -967,7 +971,7 @@ pub fn is_sep_byte_verbatim(u: &u8) -> bool {
 }
 
 /// Prefix types for Path
-#[deriving(PartialEq, Clone, Show)]
+#[deriving(Copy, PartialEq, Clone, Show)]
 pub enum PathPrefix {
     /// Prefix `\\?\`, uint is the length of the following component
     VerbatimPrefix(uint),
@@ -986,13 +990,13 @@ pub enum PathPrefix {
 fn parse_prefix<'a>(mut path: &'a str) -> Option<PathPrefix> {
     if path.starts_with("\\\\") {
         // \\
-        path = path.slice_from(2);
+        path = path[2..];
         if path.starts_with("?\\") {
             // \\?\
-            path = path.slice_from(2);
+            path = path[2..];
             if path.starts_with("UNC\\") {
                 // \\?\UNC\server\share
-                path = path.slice_from(4);
+                path = path[4..];
                 let (idx_a, idx_b) = match parse_two_comps(path, is_sep_verbatim) {
                     Some(x) => x,
                     None => (path.len(), 0)
@@ -1013,7 +1017,7 @@ fn parse_prefix<'a>(mut path: &'a str) -> Option<PathPrefix> {
             }
         } else if path.starts_with(".\\") {
             // \\.\path
-            path = path.slice_from(2);
+            path = path[2..];
             let idx = path.find('\\').unwrap_or(path.len());
             return Some(DeviceNSPrefix(idx));
         }
@@ -1033,13 +1037,12 @@ fn parse_prefix<'a>(mut path: &'a str) -> Option<PathPrefix> {
     }
     return None;
 
-    fn parse_two_comps<'a>(mut path: &'a str, f: |char| -> bool)
-                       -> Option<(uint, uint)> {
-        let idx_a = match path.find(|x| f(x)) {
+    fn parse_two_comps(mut path: &str, f: fn(char) -> bool) -> Option<(uint, uint)> {
+        let idx_a = match path.find(f) {
             None => return None,
             Some(x) => x
         };
-        path = path.slice_from(idx_a+1);
+        path = path[idx_a+1..];
         let idx_b = path.find(f).unwrap_or(path.len());
         Some((idx_a, idx_b))
     }
@@ -1047,10 +1050,14 @@ fn parse_prefix<'a>(mut path: &'a str) -> Option<PathPrefix> {
 
 // None result means the string didn't need normalizing
 fn normalize_helper<'a>(s: &'a str, prefix: Option<PathPrefix>) -> (bool, Option<Vec<&'a str>>) {
-    let f = if !prefix_is_verbatim(prefix) { is_sep } else { is_sep_verbatim };
+    let f: fn(char) -> bool = if !prefix_is_verbatim(prefix) {
+        is_sep
+    } else {
+        is_sep_verbatim
+    };
     let is_abs = s.len() > prefix_len(prefix) && f(s.char_at(prefix_len(prefix)));
-    let s_ = s.slice_from(prefix_len(prefix));
-    let s_ = if is_abs { s_.slice_from(1) } else { s_ };
+    let s_ = s[prefix_len(prefix)..];
+    let s_ = if is_abs { s_[1..] } else { s_ };
 
     if is_abs && s_.is_empty() {
         return (is_abs, match prefix {
@@ -1114,12 +1121,12 @@ fn prefix_len(p: Option<PathPrefix>) -> uint {
 
 #[cfg(test)]
 mod tests {
-    use mem;
     use prelude::*;
     use super::*;
+    use super::PathPrefix::*;
     use super::parse_prefix;
 
-    macro_rules! t(
+    macro_rules! t {
         (s: $path:expr, $exp:expr) => (
             {
                 let path = $path;
@@ -1132,7 +1139,7 @@ mod tests {
                 assert!(path.as_vec() == $exp);
             }
         )
-    )
+    }
 
     #[test]
     fn test_parse_prefix() {
@@ -1146,7 +1153,7 @@ mod tests {
                             "parse_prefix(\"{}\"): expected {}, found {}", path, exp, res);
                 }
             )
-        )
+        );
 
         t!("\\\\SERVER\\share\\foo", Some(UNCPrefix(6,5)));
         t!("\\\\", None);
@@ -1232,8 +1239,8 @@ mod tests {
         t!(s: Path::new("foo\\..\\..\\.."), "..\\..");
         t!(s: Path::new("foo\\..\\..\\bar"), "..\\bar");
 
-        assert_eq!(Path::new(b"foo\\bar").into_vec().as_slice(), b"foo\\bar");
-        assert_eq!(Path::new(b"\\foo\\..\\..\\bar").into_vec().as_slice(), b"\\bar");
+        assert_eq!(Path::new(b"foo\\bar").into_vec(), b"foo\\bar");
+        assert_eq!(Path::new(b"\\foo\\..\\..\\bar").into_vec(), b"\\bar");
 
         t!(s: Path::new("\\\\a"), "\\a");
         t!(s: Path::new("\\\\a\\"), "\\a");
@@ -1295,20 +1302,20 @@ mod tests {
 
     #[test]
     fn test_null_byte() {
-        use task;
-        let result = task::try(proc() {
+        use thread::Thread;
+        let result = Thread::spawn(move|| {
             Path::new(b"foo/bar\0")
-        });
+        }).join();
         assert!(result.is_err());
 
-        let result = task::try(proc() {
+        let result = Thread::spawn(move|| {
             Path::new("test").set_filename(b"f\0o")
-        });
+        }).join();
         assert!(result.is_err());
 
-        let result = task::try(proc() {
+        let result = Thread::spawn(move || {
             Path::new("test").push(b"f\0o");
-        });
+        }).join();
         assert!(result.is_err());
     }
 
@@ -1321,15 +1328,15 @@ mod tests {
     #[test]
     fn test_display_str() {
         let path = Path::new("foo");
-        assert_eq!(path.display().to_string(), "foo".to_string());
+        assert_eq!(path.display().to_string(), "foo");
         let path = Path::new(b"\\");
-        assert_eq!(path.filename_display().to_string(), "".to_string());
+        assert_eq!(path.filename_display().to_string(), "");
 
         let path = Path::new("foo");
-        let mo = path.display().as_maybe_owned();
+        let mo = path.display().as_cow();
         assert_eq!(mo.as_slice(), "foo");
         let path = Path::new(b"\\");
-        let mo = path.filename_display().as_maybe_owned();
+        let mo = path.filename_display().as_cow();
         assert_eq!(mo.as_slice(), "");
     }
 
@@ -1340,12 +1347,12 @@ mod tests {
                 {
                     let path = Path::new($path);
                     let f = format!("{}", path.display());
-                    assert_eq!(f.as_slice(), $exp);
+                    assert_eq!(f, $exp);
                     let f = format!("{}", path.filename_display());
-                    assert_eq!(f.as_slice(), $expf);
+                    assert_eq!(f, $expf);
                 }
             )
-        )
+        );
 
         t!("foo", "foo", "foo");
         t!("foo\\bar", "foo\\bar", "bar");
@@ -1357,11 +1364,9 @@ mod tests {
         macro_rules! t(
             (s: $path:expr, $op:ident, $exp:expr) => (
                 {
-                    unsafe {
-                        let path = $path;
-                        let path = Path::new(path);
-                        assert!(path.$op() == Some(mem::transmute($exp)));
-                    }
+                    let path = $path;
+                    let path = Path::new(path);
+                    assert!(path.$op() == Some($exp));
                 }
             );
             (s: $path:expr, $op:ident, $exp:expr, opt) => (
@@ -1374,14 +1379,12 @@ mod tests {
             );
             (v: $path:expr, $op:ident, $exp:expr) => (
                 {
-                    unsafe {
-                        let path = $path;
-                        let path = Path::new(path);
-                        assert!(path.$op() == mem::transmute($exp));
-                    }
+                    let path = $path;
+                    let path = Path::new(path);
+                    assert!(path.$op() == $exp);
                 }
             )
-        )
+        );
 
         t!(v: b"a\\b\\c", filename, Some(b"c"));
         t!(s: "a\\b\\c", filename_str, "c");
@@ -1463,8 +1466,7 @@ mod tests {
         // filestem is based on filename, so we don't need the full set of prefix tests
 
         t!(v: b"hi\\there.txt", extension, Some(b"txt"));
-        let no: Option<&'static [u8]> = None;
-        t!(v: b"hi\\there", extension, no);
+        t!(v: b"hi\\there", extension, None);
         t!(s: "hi\\there.txt", extension_str, Some("txt"), opt);
         t!(s: "hi\\there", extension_str, None, opt);
         t!(s: "there.txt", extension_str, Some("txt"), opt);
@@ -1493,7 +1495,7 @@ mod tests {
                     assert!(p1 == p2.join(join));
                 }
             )
-        )
+        );
 
         t!(s: "a\\b\\c", "..");
         t!(s: "\\a\\b\\c", "d");
@@ -1526,7 +1528,7 @@ mod tests {
                     assert_eq!(p.as_str(), Some($exp));
                 }
             )
-        )
+        );
 
         t!(s: "a\\b\\c", "d", "a\\b\\c\\d");
         t!(s: "\\a\\b\\c", "d", "\\a\\b\\c\\d");
@@ -1584,7 +1586,7 @@ mod tests {
                     assert_eq!(p.as_vec(), $exp);
                 }
             )
-        )
+        );
 
         t!(s: "a\\b\\c", ["d", "e"], "a\\b\\c\\d\\e");
         t!(s: "a\\b\\c", ["d", "\\e"], "\\e");
@@ -1619,7 +1621,7 @@ mod tests {
                     assert!(result == $right);
                 }
             )
-        )
+        );
 
         t!(s: "a\\b\\c", "a\\b", true);
         t!(s: "a", ".", true);
@@ -1696,7 +1698,7 @@ mod tests {
                     assert_eq!(res.as_str(), Some($exp));
                 }
             )
-        )
+        );
 
         t!(s: "a\\b\\c", "..", "a\\b");
         t!(s: "\\a\\b\\c", "d", "\\a\\b\\c\\d");
@@ -1725,7 +1727,7 @@ mod tests {
                     assert_eq!(res.as_vec(), $exp);
                 }
             )
-        )
+        );
 
         t!(s: "a\\b\\c", ["d", "e"], "a\\b\\c\\d\\e");
         t!(s: "a\\b\\c", ["..", "d"], "a\\b\\d");
@@ -1751,7 +1753,7 @@ mod tests {
                             pstr, stringify!($op), arg, exp, res.as_str().unwrap());
                 }
             )
-        )
+        );
 
         t!(s: "a\\b\\c", with_filename, "d", "a\\b\\d");
         t!(s: ".", with_filename, "foo", "foo");
@@ -1844,7 +1846,7 @@ mod tests {
                     assert!(p1 == p2.$with(arg));
                 }
             )
-        )
+        );
 
         t!(v: b"a\\b\\c", set_filename, with_filename, b"d");
         t!(v: b"\\", set_filename, with_filename, b"foo");
@@ -1871,53 +1873,48 @@ mod tests {
         macro_rules! t(
             (s: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
                 {
-                    unsafe {
-                        let path = $path;
-                        let filename = $filename;
-                        assert!(path.filename_str() == filename,
-                                "`{}`.filename_str(): Expected `{}`, found `{}`",
-                                path.as_str().unwrap(), filename, path.filename_str());
-                        let dirname = $dirname;
-                        assert!(path.dirname_str() == dirname,
-                                "`{}`.dirname_str(): Expected `{}`, found `{}`",
-                                path.as_str().unwrap(), dirname, path.dirname_str());
-                        let filestem = $filestem;
-                        assert!(path.filestem_str() == filestem,
-                                "`{}`.filestem_str(): Expected `{}`, found `{}`",
-                                path.as_str().unwrap(), filestem, path.filestem_str());
-                        let ext = $ext;
-                        assert!(path.extension_str() == mem::transmute(ext),
-                                "`{}`.extension_str(): Expected `{}`, found `{}`",
-                                path.as_str().unwrap(), ext, path.extension_str());
-                    }
+                    let path = $path;
+                    let filename = $filename;
+                    assert!(path.filename_str() == filename,
+                            "`{}`.filename_str(): Expected `{}`, found `{}`",
+                            path.as_str().unwrap(), filename, path.filename_str());
+                    let dirname = $dirname;
+                    assert!(path.dirname_str() == dirname,
+                            "`{}`.dirname_str(): Expected `{}`, found `{}`",
+                            path.as_str().unwrap(), dirname, path.dirname_str());
+                    let filestem = $filestem;
+                    assert!(path.filestem_str() == filestem,
+                            "`{}`.filestem_str(): Expected `{}`, found `{}`",
+                            path.as_str().unwrap(), filestem, path.filestem_str());
+                    let ext = $ext;
+                    assert!(path.extension_str() == ext,
+                            "`{}`.extension_str(): Expected `{}`, found `{}`",
+                            path.as_str().unwrap(), ext, path.extension_str());
                 }
             );
             (v: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
                 {
-                    unsafe {
-                        let path = $path;
-                        assert!(path.filename() == mem::transmute($filename));
-                        assert!(path.dirname() == mem::transmute($dirname));
-                        assert!(path.filestem() == mem::transmute($filestem));
-                        assert!(path.extension() == mem::transmute($ext));
-                    }
+                    let path = $path;
+                    assert!(path.filename() == $filename);
+                    assert!(path.dirname() == $dirname);
+                    assert!(path.filestem() == $filestem);
+                    assert!(path.extension() == $ext);
                 }
             )
-        )
+        );
 
-        let no: Option<&'static str> = None;
-        t!(v: Path::new(b"a\\b\\c"), Some(b"c"), b"a\\b", Some(b"c"), no);
-        t!(s: Path::new("a\\b\\c"), Some("c"), Some("a\\b"), Some("c"), no);
-        t!(s: Path::new("."), None, Some("."), None, no);
-        t!(s: Path::new("\\"), None, Some("\\"), None, no);
-        t!(s: Path::new(".."), None, Some(".."), None, no);
-        t!(s: Path::new("..\\.."), None, Some("..\\.."), None, no);
+        t!(v: Path::new(b"a\\b\\c"), Some(b"c"), b"a\\b", Some(b"c"), None);
+        t!(s: Path::new("a\\b\\c"), Some("c"), Some("a\\b"), Some("c"), None);
+        t!(s: Path::new("."), None, Some("."), None, None);
+        t!(s: Path::new("\\"), None, Some("\\"), None, None);
+        t!(s: Path::new(".."), None, Some(".."), None, None);
+        t!(s: Path::new("..\\.."), None, Some("..\\.."), None, None);
         t!(s: Path::new("hi\\there.txt"), Some("there.txt"), Some("hi"),
               Some("there"), Some("txt"));
-        t!(s: Path::new("hi\\there"), Some("there"), Some("hi"), Some("there"), no);
+        t!(s: Path::new("hi\\there"), Some("there"), Some("hi"), Some("there"), None);
         t!(s: Path::new("hi\\there."), Some("there."), Some("hi"),
               Some("there"), Some(""));
-        t!(s: Path::new("hi\\.there"), Some(".there"), Some("hi"), Some(".there"), no);
+        t!(s: Path::new("hi\\.there"), Some(".there"), Some("hi"), Some(".there"), None);
         t!(s: Path::new("hi\\..there"), Some("..there"), Some("hi"),
               Some("."), Some("there"));
 
@@ -1958,7 +1955,7 @@ mod tests {
                             path.as_str().unwrap(), rel, b);
                 }
             )
-        )
+        );
         t!("a\\b\\c", false, false, false, true);
         t!("\\a\\b\\c", false, true, false, false);
         t!("a", false, false, false, true);
@@ -1991,7 +1988,7 @@ mod tests {
                             path.as_str().unwrap(), dest.as_str().unwrap(), exp, res);
                 }
             )
-        )
+        );
 
         t!(s: "a\\b\\c", "a\\b\\c\\d", true);
         t!(s: "a\\b\\c", "a\\b\\c", true);
@@ -2090,7 +2087,7 @@ mod tests {
                     assert_eq!(path.ends_with_path(&child), $exp);
                 }
             );
-        )
+        );
 
         t!(s: "a\\b\\c", "c", true);
         t!(s: "a\\b\\c", "d", false);
@@ -2127,7 +2124,7 @@ mod tests {
                             res.as_ref().and_then(|x| x.as_str()));
                 }
             )
-        )
+        );
 
         t!(s: "a\\b\\c", "a\\b", Some("c"));
         t!(s: "a\\b\\c", "a\\b\\d", Some("..\\c"));
@@ -2255,14 +2252,14 @@ mod tests {
                     let comps = path.str_components().map(|x|x.unwrap())
                                 .collect::<Vec<&str>>();
                     let exp: &[&str] = &$exp;
-                    assert_eq!(comps.as_slice(), exp);
+                    assert_eq!(comps, exp);
                     let comps = path.str_components().rev().map(|x|x.unwrap())
                                 .collect::<Vec<&str>>();
                     let exp = exp.iter().rev().map(|&x|x).collect::<Vec<&str>>();
                     assert_eq!(comps, exp);
                 }
             );
-        )
+        );
 
         t!(s: b"a\\b\\c", ["a", "b", "c"]);
         t!(s: "a\\b\\c", ["a", "b", "c"]);
@@ -2312,13 +2309,13 @@ mod tests {
                     let path = Path::new($path);
                     let comps = path.components().collect::<Vec<&[u8]>>();
                     let exp: &[&[u8]] = &$exp;
-                    assert_eq!(comps.as_slice(), exp);
+                    assert_eq!(comps, exp);
                     let comps = path.components().rev().collect::<Vec<&[u8]>>();
                     let exp = exp.iter().rev().map(|&x|x).collect::<Vec<&[u8]>>();
                     assert_eq!(comps, exp);
                 }
             )
-        )
+        );
 
         t!(s: "a\\b\\c", [b"a", b"b", b"c"]);
         t!(s: ".", [b"."]);
@@ -2336,7 +2333,7 @@ mod tests {
                     assert!(make_non_verbatim(&path) == exp);
                 }
             )
-        )
+        );
 
         t!(r"\a\b\c", Some(r"\a\b\c"));
         t!(r"a\b\c", Some(r"a\b\c"));
diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs
index 65f45c3f97e..49b888d17f4 100644
--- a/src/libstd/prelude.rs
+++ b/src/libstd/prelude.rs
@@ -50,7 +50,7 @@
 #[doc(no_inline)] pub use ops::{Fn, FnMut, FnOnce};
 
 // Reexported functions
-#[doc(no_inline)] pub use iter::{range, repeat};
+#[doc(no_inline)] pub use iter::range;
 #[doc(no_inline)] pub use mem::drop;
 #[doc(no_inline)] pub use str::from_str;
 
@@ -58,16 +58,18 @@
 
 #[doc(no_inline)] pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr};
 #[doc(no_inline)] pub use ascii::IntoBytes;
+#[doc(no_inline)] pub use borrow::IntoCow;
 #[doc(no_inline)] pub use c_str::ToCStr;
 #[doc(no_inline)] pub use char::{Char, UnicodeChar};
 #[doc(no_inline)] pub use clone::Clone;
 #[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
 #[doc(no_inline)] pub use cmp::{Ordering, Equiv};
 #[doc(no_inline)] pub use cmp::Ordering::{Less, Equal, Greater};
-#[doc(no_inline)] pub use iter::{FromIterator, Extend, ExactSize};
-#[doc(no_inline)] pub use iter::{Iterator, DoubleEndedIterator};
-#[doc(no_inline)] pub use iter::{RandomAccessIterator, CloneableIterator};
-#[doc(no_inline)] pub use iter::{OrdIterator, MutableDoubleEndedIterator};
+#[doc(no_inline)] pub use iter::{FromIterator, Extend, ExactSizeIterator};
+#[doc(no_inline)] pub use iter::{Iterator, IteratorExt, DoubleEndedIterator};
+#[doc(no_inline)] pub use iter::{DoubleEndedIteratorExt, CloneIteratorExt};
+#[doc(no_inline)] pub use iter::{RandomAccessIterator, IteratorCloneExt};
+#[doc(no_inline)] pub use iter::{IteratorOrdExt, MutableDoubleEndedIterator};
 #[doc(no_inline)] pub use num::{ToPrimitive, FromPrimitive};
 #[doc(no_inline)] pub use boxed::Box;
 #[doc(no_inline)] pub use option::Option;
@@ -77,14 +79,15 @@
 #[doc(no_inline)] pub use result::Result;
 #[doc(no_inline)] pub use result::Result::{Ok, Err};
 #[doc(no_inline)] pub use io::{Buffer, Writer, Reader, Seek, BufferPrelude};
-#[doc(no_inline)] pub use str::{Str, StrVector, StrPrelude};
-#[doc(no_inline)] pub use str::{IntoMaybeOwned, StrAllocating, UnicodeStrPrelude};
-#[doc(no_inline)] pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4};
-#[doc(no_inline)] pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
-#[doc(no_inline)] pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12};
-#[doc(no_inline)] pub use slice::{SlicePrelude, AsSlice, CloneSlicePrelude};
-#[doc(no_inline)] pub use slice::{VectorVector, PartialEqSlicePrelude, OrdSlicePrelude};
-#[doc(no_inline)] pub use slice::{CloneSliceAllocPrelude, OrdSliceAllocPrelude, SliceAllocPrelude};
+#[doc(no_inline)] pub use core::prelude::{Tuple1, Tuple2, Tuple3, Tuple4};
+#[doc(no_inline)] pub use core::prelude::{Tuple5, Tuple6, Tuple7, Tuple8};
+#[doc(no_inline)] pub use core::prelude::{Tuple9, Tuple10, Tuple11, Tuple12};
+#[doc(no_inline)] pub use str::{Str, StrVector};
+#[doc(no_inline)] pub use str::StrExt;
+#[doc(no_inline)] pub use slice::AsSlice;
+#[doc(no_inline)] pub use slice::{VectorVector, PartialEqSliceExt};
+#[doc(no_inline)] pub use slice::{CloneSliceExt, OrdSliceExt, SliceExt};
+#[doc(no_inline)] pub use slice::{BoxedSliceExt};
 #[doc(no_inline)] pub use string::{IntoString, String, ToString};
 #[doc(no_inline)] pub use vec::Vec;
 
diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs
index 08eb7350bcf..c590c0f575e 100644
--- a/src/libstd/rand/mod.rs
+++ b/src/libstd/rand/mod.rs
@@ -45,7 +45,7 @@
 //!     so the "quality" of `/dev/random` is not better than `/dev/urandom` in most cases.
 //!     However, this means that `/dev/urandom` can yield somewhat predictable randomness
 //!     if the entropy pool is very small, such as immediately after first booting.
-//!     Linux 3,17 added `getrandom(2)` system call which solves the issue: it blocks if entropy
+//!     Linux 3.17 added the `getrandom(2)` system call which solves the issue: it blocks if entropy
 //!     pool is not initialized yet, but it does not block once initialized.
 //!     `OsRng` tries to use `getrandom(2)` if available, and use `/dev/urandom` fallback if not.
 //!     If an application does not have `getrandom` and likely to be run soon after first booting,
@@ -80,7 +80,7 @@
 //! circle, both centered at the origin. Since the area of a unit circle is π,
 //! we have:
 //!
-//! ```notrust
+//! ```text
 //!     (area of unit circle) / (area of square) = π / 4
 //! ```
 //!
@@ -126,7 +126,7 @@
 //! > Is it to your advantage to switch your choice?
 //!
 //! The rather unintuitive answer is that you will have a 2/3 chance of winning if
-//! you switch and a 1/3 chance of winning of you don't, so it's better to switch.
+//! you switch and a 1/3 chance of winning if you don't, so it's better to switch.
 //!
 //! This program will simulate the game show and with large enough simulation steps
 //! it will indeed confirm that it is better to switch.
@@ -224,11 +224,10 @@
 use cell::RefCell;
 use clone::Clone;
 use io::IoResult;
-use iter::Iterator;
+use iter::{Iterator, IteratorExt};
 use mem;
-use option::{Some, None};
 use rc::Rc;
-use result::{Ok, Err};
+use result::Result::{Ok, Err};
 use vec::Vec;
 
 #[cfg(not(target_word_size="64"))]
@@ -246,7 +245,10 @@ pub mod reader;
 
 /// The standard RNG. This is designed to be efficient on the current
 /// platform.
-pub struct StdRng { rng: IsaacWordRng }
+#[deriving(Copy)]
+pub struct StdRng {
+    rng: IsaacWordRng,
+}
 
 impl StdRng {
     /// Create a randomly seeded instance of `StdRng`.
@@ -337,24 +339,18 @@ pub struct TaskRng {
 /// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`.
 pub fn task_rng() -> TaskRng {
     // used to make space in TLS for a random number generator
-    local_data_key!(TASK_RNG_KEY: Rc<RefCell<TaskRngInner>>)
-
-    match TASK_RNG_KEY.get() {
-        None => {
-            let r = match StdRng::new() {
-                Ok(r) => r,
-                Err(e) => panic!("could not initialize task_rng: {}", e)
-            };
-            let rng = reseeding::ReseedingRng::new(r,
-                                                   TASK_RNG_RESEED_THRESHOLD,
-                                                   TaskRngReseeder);
-            let rng = Rc::new(RefCell::new(rng));
-            TASK_RNG_KEY.replace(Some(rng.clone()));
-
-            TaskRng { rng: rng }
-        }
-        Some(rng) => TaskRng { rng: rng.clone() }
-    }
+    thread_local!(static TASK_RNG_KEY: Rc<RefCell<TaskRngInner>> = {
+        let r = match StdRng::new() {
+            Ok(r) => r,
+            Err(e) => panic!("could not initialize task_rng: {}", e)
+        };
+        let rng = reseeding::ReseedingRng::new(r,
+                                               TASK_RNG_RESEED_THRESHOLD,
+                                               TaskRngReseeder);
+        Rc::new(RefCell::new(rng))
+    });
+
+    TaskRng { rng: TASK_RNG_KEY.with(|t| t.clone()) }
 }
 
 impl Rng for TaskRng {
@@ -536,7 +532,7 @@ mod test {
         let mut one = [1i];
         r.shuffle(&mut one);
         let b: &[_] = &[1];
-        assert_eq!(one.as_slice(), b);
+        assert_eq!(one, b);
 
         let mut two = [1i, 2];
         r.shuffle(&mut two);
@@ -545,7 +541,7 @@ mod test {
         let mut x = [1i, 1, 1];
         r.shuffle(&mut x);
         let b: &[_] = &[1, 1, 1];
-        assert_eq!(x.as_slice(), b);
+        assert_eq!(x, b);
     }
 
     #[test]
@@ -555,7 +551,7 @@ mod test {
         let mut v = [1i, 1, 1];
         r.shuffle(&mut v);
         let b: &[_] = &[1, 1, 1];
-        assert_eq!(v.as_slice(), b);
+        assert_eq!(v, b);
         assert_eq!(r.gen_range(0u, 1u), 0u);
     }
 
diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs
index 2a4d8347c30..68c99b12758 100644
--- a/src/libstd/rand/os.rs
+++ b/src/libstd/rand/os.rs
@@ -23,8 +23,8 @@ mod imp {
     use path::Path;
     use rand::Rng;
     use rand::reader::ReaderRng;
-    use result::{Ok, Err};
-    use slice::SlicePrelude;
+    use result::Result::{Ok, Err};
+    use slice::SliceExt;
     use mem;
     use os::errno;
 
@@ -117,7 +117,8 @@ mod imp {
     ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
     /// - Windows: calls `CryptGenRandom`, using the default cryptographic
     ///   service provider with the `PROV_RSA_FULL` type.
-    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
+    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
+    ///
     /// This does not block.
     pub struct OsRng {
         inner: OsRngInner,
@@ -169,13 +170,12 @@ mod imp {
     extern crate libc;
 
     use io::{IoResult};
-    use kinds::marker;
     use mem;
     use os;
     use rand::Rng;
-    use result::{Ok};
+    use result::Result::{Ok};
     use self::libc::{c_int, size_t};
-    use slice::{SlicePrelude};
+    use slice::SliceExt;
 
     /// A random number generator that retrieves randomness straight from
     /// the operating system. Platform sources:
@@ -184,10 +184,13 @@ mod imp {
     ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
     /// - Windows: calls `CryptGenRandom`, using the default cryptographic
     ///   service provider with the `PROV_RSA_FULL` type.
-    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
+    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
+    ///
     /// This does not block.
+    #[allow(missing_copy_implementations)]
     pub struct OsRng {
-        marker: marker::NoCopy
+        // dummy field to ensure that this struct cannot be constructed outside of this module
+        _dummy: (),
     }
 
     #[repr(C)]
@@ -205,7 +208,7 @@ mod imp {
     impl OsRng {
         /// Create a new `OsRng`.
         pub fn new() -> IoResult<OsRng> {
-            Ok(OsRng {marker: marker::NoCopy} )
+            Ok(OsRng { _dummy: () })
         }
     }
 
@@ -240,10 +243,10 @@ mod imp {
     use ops::Drop;
     use os;
     use rand::Rng;
-    use result::{Ok, Err};
+    use result::Result::{Ok, Err};
     use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
     use self::libc::types::os::arch::extra::{LONG_PTR};
-    use slice::{SlicePrelude};
+    use slice::SliceExt;
 
     type HCRYPTPROV = LONG_PTR;
 
@@ -254,7 +257,8 @@ mod imp {
     ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
     /// - Windows: calls `CryptGenRandom`, using the default cryptographic
     ///   service provider with the `PROV_RSA_FULL` type.
-    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
+    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
+    ///
     /// This does not block.
     pub struct OsRng {
         hcryptprov: HCRYPTPROV
@@ -335,7 +339,7 @@ mod test {
 
     use super::OsRng;
     use rand::Rng;
-    use task;
+    use thread::Thread;
 
     #[test]
     fn test_os_rng() {
@@ -355,25 +359,26 @@ mod test {
         for _ in range(0u, 20) {
             let (tx, rx) = channel();
             txs.push(tx);
-            task::spawn(proc() {
+
+            Thread::spawn(move|| {
                 // wait until all the tasks are ready to go.
                 rx.recv();
 
                 // deschedule to attempt to interleave things as much
                 // as possible (XXX: is this a good test?)
                 let mut r = OsRng::new().unwrap();
-                task::deschedule();
+                Thread::yield_now();
                 let mut v = [0u8, .. 1000];
 
                 for _ in range(0u, 100) {
                     r.next_u32();
-                    task::deschedule();
+                    Thread::yield_now();
                     r.next_u64();
-                    task::deschedule();
+                    Thread::yield_now();
                     r.fill_bytes(&mut v);
-                    task::deschedule();
+                    Thread::yield_now();
                 }
-            })
+            }).detach();
         }
 
         // start all the tasks
diff --git a/src/libstd/rand/reader.rs b/src/libstd/rand/reader.rs
index 796bf7853f7..7298b2ef0ac 100644
--- a/src/libstd/rand/reader.rs
+++ b/src/libstd/rand/reader.rs
@@ -12,8 +12,8 @@
 
 use io::Reader;
 use rand::Rng;
-use result::{Ok, Err};
-use slice::SlicePrelude;
+use result::Result::{Ok, Err};
+use slice::SliceExt;
 
 /// An RNG that reads random bytes straight from a `Reader`. This will
 /// work best with an infinite reader, but this is not required.
diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs
new file mode 100644
index 00000000000..b1f268597c7
--- /dev/null
+++ b/src/libstd/rt/args.rs
@@ -0,0 +1,166 @@
+// Copyright 2012-2013 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.
+
+//! Global storage for command line arguments
+//!
+//! The current incarnation of the Rust runtime expects for
+//! the processes `argc` and `argv` arguments to be stored
+//! in a globally-accessible location for use by the `os` module.
+//!
+//! Only valid to call on Linux. Mac and Windows use syscalls to
+//! discover the command line arguments.
+//!
+//! FIXME #7756: Would be nice for this to not exist.
+
+use core::prelude::*;
+use vec::Vec;
+
+/// One-time global initialization.
+pub unsafe fn init(argc: int, argv: *const *const u8) { imp::init(argc, argv) }
+
+/// One-time global cleanup.
+pub unsafe fn cleanup() { imp::cleanup() }
+
+/// Take the global arguments from global storage.
+pub fn take() -> Option<Vec<Vec<u8>>> { imp::take() }
+
+/// Give the global arguments to global storage.
+///
+/// It is an error if the arguments already exist.
+pub fn put(args: Vec<Vec<u8>>) { imp::put(args) }
+
+/// Make a clone of the global arguments.
+pub fn clone() -> Option<Vec<Vec<u8>>> { imp::clone() }
+
+#[cfg(any(target_os = "linux",
+          target_os = "android",
+          target_os = "freebsd",
+          target_os = "dragonfly"))]
+mod imp {
+    use prelude::*;
+
+    use mem;
+    use slice;
+
+    use sync::{StaticMutex, MUTEX_INIT};
+
+    static mut GLOBAL_ARGS_PTR: uint = 0;
+    static LOCK: StaticMutex = MUTEX_INIT;
+
+    pub unsafe fn init(argc: int, argv: *const *const u8) {
+        let args = load_argc_and_argv(argc, argv);
+        put(args);
+    }
+
+    pub unsafe fn cleanup() {
+        take();
+        LOCK.destroy();
+    }
+
+    pub fn take() -> Option<Vec<Vec<u8>>> {
+        let _guard = LOCK.lock();
+        unsafe {
+            let ptr = get_global_ptr();
+            let val = mem::replace(&mut *ptr, None);
+            val.as_ref().map(|s: &Box<Vec<Vec<u8>>>| (**s).clone())
+        }
+    }
+
+    pub fn put(args: Vec<Vec<u8>>) {
+        let _guard = LOCK.lock();
+        unsafe {
+            let ptr = get_global_ptr();
+            rtassert!((*ptr).is_none());
+            (*ptr) = Some(box args.clone());
+        }
+    }
+
+    pub fn clone() -> Option<Vec<Vec<u8>>> {
+        let _guard = LOCK.lock();
+        unsafe {
+            let ptr = get_global_ptr();
+            (*ptr).as_ref().map(|s: &Box<Vec<Vec<u8>>>| (**s).clone())
+        }
+    }
+
+    fn get_global_ptr() -> *mut Option<Box<Vec<Vec<u8>>>> {
+        unsafe { mem::transmute(&GLOBAL_ARGS_PTR) }
+    }
+
+    unsafe fn load_argc_and_argv(argc: int, argv: *const *const u8) -> Vec<Vec<u8>> {
+        Vec::from_fn(argc as uint, |i| {
+            let arg = *argv.offset(i as int);
+            let mut len = 0u;
+            while *arg.offset(len as int) != 0 {
+                len += 1u;
+            }
+            slice::from_raw_buf(&arg, len).to_vec()
+        })
+    }
+
+    #[cfg(test)]
+    mod tests {
+        use prelude::*;
+        use finally::Finally;
+
+        use super::*;
+
+        #[test]
+        fn smoke_test() {
+            // Preserve the actual global state.
+            let saved_value = take();
+
+            let expected = vec![
+                b"happy".to_vec(),
+                b"today?".to_vec(),
+            ];
+
+            put(expected.clone());
+            assert!(clone() == Some(expected.clone()));
+            assert!(take() == Some(expected.clone()));
+            assert!(take() == None);
+
+            (|&mut:| {
+            }).finally(|| {
+                // Restore the actual global state.
+                match saved_value {
+                    Some(ref args) => put(args.clone()),
+                    None => ()
+                }
+            })
+        }
+    }
+}
+
+#[cfg(any(target_os = "macos",
+          target_os = "ios",
+          target_os = "windows"))]
+mod imp {
+    use core::prelude::*;
+    use vec::Vec;
+
+    pub unsafe fn init(_argc: int, _argv: *const *const u8) {
+    }
+
+    pub fn cleanup() {
+    }
+
+    pub fn take() -> Option<Vec<Vec<u8>>> {
+        panic!()
+    }
+
+    pub fn put(_args: Vec<Vec<u8>>) {
+        panic!()
+    }
+
+    pub fn clone() -> Option<Vec<Vec<u8>>> {
+        panic!()
+    }
+}
diff --git a/src/libstd/rt/at_exit_imp.rs b/src/libstd/rt/at_exit_imp.rs
new file mode 100644
index 00000000000..5823f8453d8
--- /dev/null
+++ b/src/libstd/rt/at_exit_imp.rs
@@ -0,0 +1,75 @@
+// Copyright 2013 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.
+
+//! Implementation of running at_exit routines
+//!
+//! Documentation can be found on the `rt::at_exit` function.
+
+use core::prelude::*;
+
+use boxed::Box;
+use vec::Vec;
+use mem;
+use thunk::Thunk;
+use sys_common::mutex::{Mutex, MUTEX_INIT};
+
+type Queue = Vec<Thunk>;
+
+// NB these are specifically not types from `std::sync` as they currently rely
+// on poisoning and this module needs to operate at a lower level than requiring
+// the thread infrastructure to be in place (useful on the borders of
+// initialization/destruction).
+static LOCK: Mutex = MUTEX_INIT;
+static mut QUEUE: *mut Queue = 0 as *mut Queue;
+
+unsafe fn init() {
+    if QUEUE.is_null() {
+        let state: Box<Queue> = box Vec::new();
+        QUEUE = mem::transmute(state);
+    } else {
+        // can't re-init after a cleanup
+        rtassert!(QUEUE as uint != 1);
+    }
+
+    // FIXME: switch this to use atexit as below. Currently this
+    // segfaults (the queue's memory is mysteriously gone), so
+    // instead the cleanup is tied to the `std::rt` entry point.
+    //
+    // ::libc::atexit(cleanup);
+}
+
+pub fn cleanup() {
+    unsafe {
+        LOCK.lock();
+        let queue = QUEUE;
+        QUEUE = 1 as *mut _;
+        LOCK.unlock();
+
+        // make sure we're not recursively cleaning up
+        rtassert!(queue as uint != 1);
+
+        // If we never called init, not need to cleanup!
+        if queue as uint != 0 {
+            let queue: Box<Queue> = mem::transmute(queue);
+            for to_run in queue.into_iter() {
+                to_run.invoke(());
+            }
+        }
+    }
+}
+
+pub fn push(f: Thunk) {
+    unsafe {
+        LOCK.lock();
+        init();
+        (*QUEUE).push(f);
+        LOCK.unlock();
+    }
+}
diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs
index 81022994387..775e9bb526f 100644
--- a/src/libstd/rt/backtrace.rs
+++ b/src/libstd/rt/backtrace.rs
@@ -12,16 +12,12 @@
 
 #![allow(non_camel_case_types)]
 
-use io::{IoResult, Writer};
-use iter::Iterator;
-use option::{Some, None};
+use prelude::*;
+
 use os;
-use result::{Ok, Err};
-use str::{StrPrelude, from_str};
 use sync::atomic;
-use unicode::char::UnicodeChar;
 
-pub use self::imp::write;
+pub use sys::backtrace::write;
 
 // For now logging is turned off by default, and this function checks to see
 // whether the magical environment variable is present to see if it's turned on.
@@ -41,979 +37,15 @@ pub fn log_enabled() -> bool {
     val == 2
 }
 
-#[cfg(target_word_size = "64")] const HEX_WIDTH: uint = 18;
-#[cfg(target_word_size = "32")] const HEX_WIDTH: uint = 10;
-
-// All rust symbols are in theory lists of "::"-separated identifiers. Some
-// assemblers, however, can't handle these characters in symbol names. To get
-// around this, we use C++-style mangling. The mangling method is:
-//
-// 1. Prefix the symbol with "_ZN"
-// 2. For each element of the path, emit the length plus the element
-// 3. End the path with "E"
-//
-// For example, "_ZN4testE" => "test" and "_ZN3foo3bar" => "foo::bar".
-//
-// We're the ones printing our backtraces, so we can't rely on anything else to
-// demangle our symbols. It's *much* nicer to look at demangled symbols, so
-// this function is implemented to give us nice pretty output.
-//
-// Note that this demangler isn't quite as fancy as it could be. We have lots
-// of other information in our symbols like hashes, version, type information,
-// etc. Additionally, this doesn't handle glue symbols at all.
-fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> {
-    // First validate the symbol. If it doesn't look like anything we're
-    // expecting, we just print it literally. Note that we must handle non-rust
-    // symbols because we could have any function in the backtrace.
-    let mut valid = true;
-    if s.len() > 4 && s.starts_with("_ZN") && s.ends_with("E") {
-        let mut chars = s.slice(3, s.len() - 1).chars();
-        while valid {
-            let mut i = 0;
-            for c in chars {
-                if c.is_numeric() {
-                    i = i * 10 + c as uint - '0' as uint;
-                } else {
-                    break
-                }
-            }
-            if i == 0 {
-                valid = chars.next().is_none();
-                break
-            } else if chars.by_ref().take(i - 1).count() != i - 1 {
-                valid = false;
-            }
-        }
-    } else {
-        valid = false;
-    }
-
-    // Alright, let's do this.
-    if !valid {
-        try!(writer.write_str(s));
-    } else {
-        let mut s = s.slice_from(3);
-        let mut first = true;
-        while s.len() > 1 {
-            if !first {
-                try!(writer.write_str("::"));
-            } else {
-                first = false;
-            }
-            let mut rest = s;
-            while rest.char_at(0).is_numeric() {
-                rest = rest.slice_from(1);
-            }
-            let i: uint = from_str(s.slice_to(s.len() - rest.len())).unwrap();
-            s = rest.slice_from(i);
-            rest = rest.slice_to(i);
-            while rest.len() > 0 {
-                if rest.starts_with("$") {
-                    macro_rules! demangle(
-                        ($($pat:expr => $demangled:expr),*) => ({
-                            $(if rest.starts_with($pat) {
-                                try!(writer.write_str($demangled));
-                                rest = rest.slice_from($pat.len());
-                              } else)*
-                            {
-                                try!(writer.write_str(rest));
-                                break;
-                            }
-
-                        })
-                    )
-                    // see src/librustc/back/link.rs for these mappings
-                    demangle! (
-                        "$SP$" => "@",
-                        "$UP$" => "Box",
-                        "$RP$" => "*",
-                        "$BP$" => "&",
-                        "$LT$" => "<",
-                        "$GT$" => ">",
-                        "$LP$" => "(",
-                        "$RP$" => ")",
-                        "$C$"  => ",",
-
-                        // in theory we can demangle any Unicode code point, but
-                        // for simplicity we just catch the common ones.
-                        "$x20" => " ",
-                        "$x27" => "'",
-                        "$x5b" => "[",
-                        "$x5d" => "]"
-                    )
-                } else {
-                    let idx = match rest.find('$') {
-                        None => rest.len(),
-                        Some(i) => i,
-                    };
-                    try!(writer.write_str(rest.slice_to(idx)));
-                    rest = rest.slice_from(idx);
-                }
-            }
-        }
-    }
-
-    Ok(())
-}
-
-/// Backtrace support built on libgcc with some extra OS-specific support
-///
-/// Some methods of getting a backtrace:
-///
-/// * The backtrace() functions on unix. It turns out this doesn't work very
-///   well for green threads on OSX, and the address to symbol portion of it
-///   suffers problems that are described below.
-///
-/// * Using libunwind. This is more difficult than it sounds because libunwind
-///   isn't installed everywhere by default. It's also a bit of a hefty library,
-///   so possibly not the best option. When testing, libunwind was excellent at
-///   getting both accurate backtraces and accurate symbols across platforms.
-///   This route was not chosen in favor of the next option, however.
-///
-/// * We're already using libgcc_s for exceptions in rust (triggering task
-///   unwinding and running destructors on the stack), and it turns out that it
-///   conveniently comes with a function that also gives us a backtrace. All of
-///   these functions look like _Unwind_*, but it's not quite the full
-///   repertoire of the libunwind API. Due to it already being in use, this was
-///   the chosen route of getting a backtrace.
-///
-/// After choosing libgcc_s for backtraces, the sad part is that it will only
-/// give us a stack trace of instruction pointers. Thankfully these instruction
-/// pointers are accurate (they work for green and native threads), but it's
-/// then up to us again to figure out how to translate these addresses to
-/// symbols. As with before, we have a few options. Before, that, a little bit
-/// of an interlude about symbols. This is my very limited knowledge about
-/// symbol tables, and this information is likely slightly wrong, but the
-/// general idea should be correct.
-///
-/// When talking about symbols, it's helpful to know a few things about where
-/// symbols are located. Some symbols are located in the dynamic symbol table
-/// of the executable which in theory means that they're available for dynamic
-/// linking and lookup. Other symbols end up only in the local symbol table of
-/// the file. This loosely corresponds to pub and priv functions in Rust.
-///
-/// Armed with this knowledge, we know that our solution for address to symbol
-/// translation will need to consult both the local and dynamic symbol tables.
-/// With that in mind, here's our options of translating an address to
-/// a symbol.
-///
-/// * Use dladdr(). The original backtrace()-based idea actually uses dladdr()
-///   behind the scenes to translate, and this is why backtrace() was not used.
-///   Conveniently, this method works fantastically on OSX. It appears dladdr()
-///   uses magic to consult the local symbol table, or we're putting everything
-///   in the dynamic symbol table anyway. Regardless, for OSX, this is the
-///   method used for translation. It's provided by the system and easy to do.o
-///
-///   Sadly, all other systems have a dladdr() implementation that does not
-///   consult the local symbol table. This means that most functions are blank
-///   because they don't have symbols. This means that we need another solution.
-///
-/// * Use unw_get_proc_name(). This is part of the libunwind api (not the
-///   libgcc_s version of the libunwind api), but involves taking a dependency
-///   to libunwind. We may pursue this route in the future if we bundle
-///   libunwind, but libunwind was unwieldy enough that it was not chosen at
-///   this time to provide this functionality.
-///
-/// * Shell out to a utility like `readelf`. Crazy though it may sound, it's a
-///   semi-reasonable solution. The stdlib already knows how to spawn processes,
-///   so in theory it could invoke readelf, parse the output, and consult the
-///   local/dynamic symbol tables from there. This ended up not getting chosen
-///   due to the craziness of the idea plus the advent of the next option.
-///
-/// * Use `libbacktrace`. It turns out that this is a small library bundled in
-///   the gcc repository which provides backtrace and symbol translation
-///   functionality. All we really need from it is the backtrace functionality,
-///   and we only really need this on everything that's not OSX, so this is the
-///   chosen route for now.
-///
-/// In summary, the current situation uses libgcc_s to get a trace of stack
-/// pointers, and we use dladdr() or libbacktrace to translate these addresses
-/// to symbols. This is a bit of a hokey implementation as-is, but it works for
-/// all unix platforms we support right now, so it at least gets the job done.
-#[cfg(unix)]
-mod imp {
-    use c_str::CString;
-    use io::{IoResult, Writer};
-    use libc;
-    use mem;
-    use option::{Some, None, Option};
-    use result::{Ok, Err};
-    use rustrt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
-
-    /// As always - iOS on arm uses SjLj exceptions and
-    /// _Unwind_Backtrace is even not available there. Still,
-    /// backtraces could be extracted using a backtrace function,
-    /// which thanks god is public
-    ///
-    /// As mentioned in a huge comment block above, backtrace doesn't
-    /// play well with green threads, so while it is extremely nice
-    /// and simple to use it should be used only on iOS devices as the
-    /// only viable option.
-    #[cfg(all(target_os = "ios", target_arch = "arm"))]
-    #[inline(never)]
-    pub fn write(w: &mut Writer) -> IoResult<()> {
-        use iter::{Iterator, range};
-        use result;
-        use slice::{SlicePrelude};
-
-        extern {
-            fn backtrace(buf: *mut *mut libc::c_void,
-                         sz: libc::c_int) -> libc::c_int;
-        }
-
-        // while it doesn't requires lock for work as everything is
-        // local, it still displays much nicer backtraces when a
-        // couple of tasks panic simultaneously
-        static LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
-        let _g = unsafe { LOCK.lock() };
-
-        try!(writeln!(w, "stack backtrace:"));
-        // 100 lines should be enough
-        const SIZE: uint = 100;
-        let mut buf: [*mut libc::c_void, ..SIZE] = unsafe {mem::zeroed()};
-        let cnt = unsafe { backtrace(buf.as_mut_ptr(), SIZE as libc::c_int) as uint};
-
-        // skipping the first one as it is write itself
-        let iter = range(1, cnt).map(|i| {
-            print(w, i as int, buf[i])
-        });
-        result::fold(iter, (), |_, _| ())
-    }
-
-    #[cfg(not(all(target_os = "ios", target_arch = "arm")))]
-    #[inline(never)] // if we know this is a function call, we can skip it when
-                     // tracing
-    pub fn write(w: &mut Writer) -> IoResult<()> {
-        use io::IoError;
-
-        struct Context<'a> {
-            idx: int,
-            writer: &'a mut Writer+'a,
-            last_error: Option<IoError>,
-        }
-
-        // When using libbacktrace, we use some necessary global state, so we
-        // need to prevent more than one thread from entering this block. This
-        // is semi-reasonable in terms of printing anyway, and we know that all
-        // I/O done here is blocking I/O, not green I/O, so we don't have to
-        // worry about this being a native vs green mutex.
-        static LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
-        let _g = unsafe { LOCK.lock() };
-
-        try!(writeln!(w, "stack backtrace:"));
-
-        let mut cx = Context { writer: w, last_error: None, idx: 0 };
-        return match unsafe {
-            uw::_Unwind_Backtrace(trace_fn,
-                                  &mut cx as *mut Context as *mut libc::c_void)
-        } {
-            uw::_URC_NO_REASON => {
-                match cx.last_error {
-                    Some(err) => Err(err),
-                    None => Ok(())
-                }
-            }
-            _ => Ok(()),
-        };
-
-        extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
-                           arg: *mut libc::c_void) -> uw::_Unwind_Reason_Code {
-            let cx: &mut Context = unsafe { mem::transmute(arg) };
-            let ip = unsafe { uw::_Unwind_GetIP(ctx) as *mut libc::c_void };
-            // dladdr() on osx gets whiny when we use FindEnclosingFunction, and
-            // it appears to work fine without it, so we only use
-            // FindEnclosingFunction on non-osx platforms. In doing so, we get a
-            // slightly more accurate stack trace in the process.
-            //
-            // This is often because panic involves the last instruction of a
-            // function being "call std::rt::begin_unwind", with no ret
-            // instructions after it. This means that the return instruction
-            // pointer points *outside* of the calling function, and by
-            // unwinding it we go back to the original function.
-            let ip = if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
-                ip
-            } else {
-                unsafe { uw::_Unwind_FindEnclosingFunction(ip) }
-            };
-
-            // Don't print out the first few frames (they're not user frames)
-            cx.idx += 1;
-            if cx.idx <= 0 { return uw::_URC_NO_REASON }
-            // Don't print ginormous backtraces
-            if cx.idx > 100 {
-                match write!(cx.writer, " ... <frames omitted>\n") {
-                    Ok(()) => {}
-                    Err(e) => { cx.last_error = Some(e); }
-                }
-                return uw::_URC_FAILURE
-            }
-
-            // Once we hit an error, stop trying to print more frames
-            if cx.last_error.is_some() { return uw::_URC_FAILURE }
-
-            match print(cx.writer, cx.idx, ip) {
-                Ok(()) => {}
-                Err(e) => { cx.last_error = Some(e); }
-            }
-
-            // keep going
-            return uw::_URC_NO_REASON
-        }
-    }
-
-    #[cfg(any(target_os = "macos", target_os = "ios"))]
-    fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
-        use intrinsics;
-        #[repr(C)]
-        struct Dl_info {
-            dli_fname: *const libc::c_char,
-            dli_fbase: *mut libc::c_void,
-            dli_sname: *const libc::c_char,
-            dli_saddr: *mut libc::c_void,
-        }
-        extern {
-            fn dladdr(addr: *const libc::c_void,
-                      info: *mut Dl_info) -> libc::c_int;
-        }
-
-        let mut info: Dl_info = unsafe { intrinsics::init() };
-        if unsafe { dladdr(addr as *const libc::c_void, &mut info) == 0 } {
-            output(w, idx,addr, None)
-        } else {
-            output(w, idx, addr, Some(unsafe {
-                CString::new(info.dli_sname, false)
-            }))
-        }
-    }
-
-    #[cfg(not(any(target_os = "macos", target_os = "ios")))]
-    fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
-        use iter::Iterator;
-        use os;
-        use path::GenericPath;
-        use ptr::RawPtr;
-        use ptr;
-        use slice::{SlicePrelude};
-
-        ////////////////////////////////////////////////////////////////////////
-        // libbacktrace.h API
-        ////////////////////////////////////////////////////////////////////////
-        type backtrace_syminfo_callback =
-            extern "C" fn(data: *mut libc::c_void,
-                          pc: libc::uintptr_t,
-                          symname: *const libc::c_char,
-                          symval: libc::uintptr_t,
-                          symsize: libc::uintptr_t);
-        type backtrace_error_callback =
-            extern "C" fn(data: *mut libc::c_void,
-                          msg: *const libc::c_char,
-                          errnum: libc::c_int);
-        enum backtrace_state {}
-        #[link(name = "backtrace", kind = "static")]
-        #[cfg(not(test))]
-        extern {}
-
-        extern {
-            fn backtrace_create_state(filename: *const libc::c_char,
-                                      threaded: libc::c_int,
-                                      error: backtrace_error_callback,
-                                      data: *mut libc::c_void)
-                                            -> *mut backtrace_state;
-            fn backtrace_syminfo(state: *mut backtrace_state,
-                                 addr: libc::uintptr_t,
-                                 cb: backtrace_syminfo_callback,
-                                 error: backtrace_error_callback,
-                                 data: *mut libc::c_void) -> libc::c_int;
-        }
-
-        ////////////////////////////////////////////////////////////////////////
-        // helper callbacks
-        ////////////////////////////////////////////////////////////////////////
-
-        extern fn error_cb(_data: *mut libc::c_void, _msg: *const libc::c_char,
-                           _errnum: libc::c_int) {
-            // do nothing for now
-        }
-        extern fn syminfo_cb(data: *mut libc::c_void,
-                             _pc: libc::uintptr_t,
-                             symname: *const libc::c_char,
-                             _symval: libc::uintptr_t,
-                             _symsize: libc::uintptr_t) {
-            let slot = data as *mut *const libc::c_char;
-            unsafe { *slot = symname; }
-        }
-
-        // The libbacktrace API supports creating a state, but it does not
-        // support destroying a state. I personally take this to mean that a
-        // state is meant to be created and then live forever.
-        //
-        // I would love to register an at_exit() handler which cleans up this
-        // state, but libbacktrace provides no way to do so.
-        //
-        // With these constraints, this function has a statically cached state
-        // that is calculated the first time this is requested. Remember that
-        // backtracing all happens serially (one global lock).
-        //
-        // An additionally oddity in this function is that we initialize the
-        // filename via self_exe_name() to pass to libbacktrace. It turns out
-        // that on Linux libbacktrace seamlessly gets the filename of the
-        // current executable, but this fails on freebsd. by always providing
-        // it, we make sure that libbacktrace never has a reason to not look up
-        // the symbols. The libbacktrace API also states that the filename must
-        // be in "permanent memory", so we copy it to a static and then use the
-        // static as the pointer.
-        //
-        // FIXME: We also call self_exe_name() on DragonFly BSD. I haven't
-        //        tested if this is required or not.
-        unsafe fn init_state() -> *mut backtrace_state {
-            static mut STATE: *mut backtrace_state = 0 as *mut backtrace_state;
-            static mut LAST_FILENAME: [libc::c_char, ..256] = [0, ..256];
-            if !STATE.is_null() { return STATE }
-            let selfname = if cfg!(target_os = "freebsd") ||
-                              cfg!(target_os = "dragonfly") {
-                os::self_exe_name()
-            } else {
-                None
-            };
-            let filename = match selfname {
-                Some(path) => {
-                    let bytes = path.as_vec();
-                    if bytes.len() < LAST_FILENAME.len() {
-                        let i = bytes.iter();
-                        for (slot, val) in LAST_FILENAME.iter_mut().zip(i) {
-                            *slot = *val as libc::c_char;
-                        }
-                        LAST_FILENAME.as_ptr()
-                    } else {
-                        ptr::null()
-                    }
-                }
-                None => ptr::null(),
-            };
-            STATE = backtrace_create_state(filename, 0, error_cb,
-                                           ptr::null_mut());
-            return STATE
-        }
-
-        ////////////////////////////////////////////////////////////////////////
-        // translation
-        ////////////////////////////////////////////////////////////////////////
-
-        // backtrace errors are currently swept under the rug, only I/O
-        // errors are reported
-        let state = unsafe { init_state() };
-        if state.is_null() {
-            return output(w, idx, addr, None)
-        }
-        let mut data = 0 as *const libc::c_char;
-        let data_addr = &mut data as *mut *const libc::c_char;
-        let ret = unsafe {
-            backtrace_syminfo(state, addr as libc::uintptr_t,
-                              syminfo_cb, error_cb,
-                              data_addr as *mut libc::c_void)
-        };
-        if ret == 0 || data.is_null() {
-            output(w, idx, addr, None)
-        } else {
-            output(w, idx, addr, Some(unsafe { CString::new(data, false) }))
-        }
-    }
-
-    // Finally, after all that work above, we can emit a symbol.
-    fn output(w: &mut Writer, idx: int, addr: *mut libc::c_void,
-              s: Option<CString>) -> IoResult<()> {
-        try!(write!(w, "  {:2}: {:2$} - ", idx, addr, super::HEX_WIDTH));
-        match s.as_ref().and_then(|c| c.as_str()) {
-            Some(string) => try!(super::demangle(w, string)),
-            None => try!(write!(w, "<unknown>")),
-        }
-        w.write(&['\n' as u8])
-    }
-
-    /// Unwind library interface used for backtraces
-    ///
-    /// Note that the native libraries come from librustrt, not this
-    /// module.
-    /// Note that dead code is allowed as here are just bindings
-    /// iOS doesn't use all of them it but adding more
-    /// platform-specific configs pollutes the code too much
-    #[allow(non_camel_case_types)]
-    #[allow(non_snake_case)]
-    #[allow(dead_code)]
-    mod uw {
-        pub use self::_Unwind_Reason_Code::*;
-
-        use libc;
-
-        #[repr(C)]
-        pub enum _Unwind_Reason_Code {
-            _URC_NO_REASON = 0,
-            _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
-            _URC_FATAL_PHASE2_ERROR = 2,
-            _URC_FATAL_PHASE1_ERROR = 3,
-            _URC_NORMAL_STOP = 4,
-            _URC_END_OF_STACK = 5,
-            _URC_HANDLER_FOUND = 6,
-            _URC_INSTALL_CONTEXT = 7,
-            _URC_CONTINUE_UNWIND = 8,
-            _URC_FAILURE = 9, // used only by ARM EABI
-        }
-
-        pub enum _Unwind_Context {}
-
-        pub type _Unwind_Trace_Fn =
-                extern fn(ctx: *mut _Unwind_Context,
-                          arg: *mut libc::c_void) -> _Unwind_Reason_Code;
-
-        extern {
-            // No native _Unwind_Backtrace on iOS
-            #[cfg(not(all(target_os = "ios", target_arch = "arm")))]
-            pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
-                                     trace_argument: *mut libc::c_void)
-                        -> _Unwind_Reason_Code;
-
-            #[cfg(all(not(target_os = "android"),
-                      not(all(target_os = "linux", target_arch = "arm"))))]
-            pub fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> libc::uintptr_t;
-
-            #[cfg(all(not(target_os = "android"),
-                      not(all(target_os = "linux", target_arch = "arm"))))]
-            pub fn _Unwind_FindEnclosingFunction(pc: *mut libc::c_void)
-                -> *mut libc::c_void;
-        }
-
-        // On android, the function _Unwind_GetIP is a macro, and this is the
-        // expansion of the macro. This is all copy/pasted directly from the
-        // header file with the definition of _Unwind_GetIP.
-        #[cfg(any(target_os = "android",
-                  all(target_os = "linux", target_arch = "arm")))]
-        pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> libc::uintptr_t {
-            #[repr(C)]
-            enum _Unwind_VRS_Result {
-                _UVRSR_OK = 0,
-                _UVRSR_NOT_IMPLEMENTED = 1,
-                _UVRSR_FAILED = 2,
-            }
-            #[repr(C)]
-            enum _Unwind_VRS_RegClass {
-                _UVRSC_CORE = 0,
-                _UVRSC_VFP = 1,
-                _UVRSC_FPA = 2,
-                _UVRSC_WMMXD = 3,
-                _UVRSC_WMMXC = 4,
-            }
-            #[repr(C)]
-            enum _Unwind_VRS_DataRepresentation {
-                _UVRSD_UINT32 = 0,
-                _UVRSD_VFPX = 1,
-                _UVRSD_FPAX = 2,
-                _UVRSD_UINT64 = 3,
-                _UVRSD_FLOAT = 4,
-                _UVRSD_DOUBLE = 5,
-            }
-
-            type _Unwind_Word = libc::c_uint;
-            extern {
-                fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context,
-                                   klass: _Unwind_VRS_RegClass,
-                                   word: _Unwind_Word,
-                                   repr: _Unwind_VRS_DataRepresentation,
-                                   data: *mut libc::c_void)
-                    -> _Unwind_VRS_Result;
-            }
-
-            let mut val: _Unwind_Word = 0;
-            let ptr = &mut val as *mut _Unwind_Word;
-            let _ = _Unwind_VRS_Get(ctx, _Unwind_VRS_RegClass::_UVRSC_CORE, 15,
-                                    _Unwind_VRS_DataRepresentation::_UVRSD_UINT32,
-                                    ptr as *mut libc::c_void);
-            (val & !1) as libc::uintptr_t
-        }
-
-        // This function also doesn't exist on Android or ARM/Linux, so make it
-        // a no-op
-        #[cfg(any(target_os = "android",
-                  all(target_os = "linux", target_arch = "arm")))]
-        pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut libc::c_void)
-            -> *mut libc::c_void
-        {
-            pc
-        }
-    }
-}
-
-/// As always, windows has something very different than unix, we mainly want
-/// to avoid having to depend too much on libunwind for windows.
-///
-/// If you google around, you'll find a fair bit of references to built-in
-/// functions to get backtraces on windows. It turns out that most of these are
-/// in an external library called dbghelp. I was unable to find this library
-/// via `-ldbghelp`, but it is apparently normal to do the `dlopen` equivalent
-/// of it.
-///
-/// You'll also find that there's a function called CaptureStackBackTrace
-/// mentioned frequently (which is also easy to use), but sadly I didn't have a
-/// copy of that function in my mingw install (maybe it was broken?). Instead,
-/// this takes the route of using StackWalk64 in order to walk the stack.
-#[cfg(windows)]
-#[allow(dead_code, non_snake_case)]
-mod imp {
-    use c_str::CString;
-    use intrinsics;
-    use io::{IoResult, Writer};
-    use libc;
-    use mem;
-    use ops::Drop;
-    use option::{Some, None};
-    use path::Path;
-    use result::{Ok, Err};
-    use rustrt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
-    use slice::SlicePrelude;
-    use str::StrPrelude;
-    use dynamic_lib::DynamicLibrary;
-
-    #[allow(non_snake_case)]
-    extern "system" {
-        fn GetCurrentProcess() -> libc::HANDLE;
-        fn GetCurrentThread() -> libc::HANDLE;
-        fn RtlCaptureContext(ctx: *mut arch::CONTEXT);
-    }
-
-    type SymFromAddrFn =
-        extern "system" fn(libc::HANDLE, u64, *mut u64,
-                           *mut SYMBOL_INFO) -> libc::BOOL;
-    type SymInitializeFn =
-        extern "system" fn(libc::HANDLE, *mut libc::c_void,
-                           libc::BOOL) -> libc::BOOL;
-    type SymCleanupFn =
-        extern "system" fn(libc::HANDLE) -> libc::BOOL;
-
-    type StackWalk64Fn =
-        extern "system" fn(libc::DWORD, libc::HANDLE, libc::HANDLE,
-                           *mut STACKFRAME64, *mut arch::CONTEXT,
-                           *mut libc::c_void, *mut libc::c_void,
-                           *mut libc::c_void, *mut libc::c_void) -> libc::BOOL;
-
-    const MAX_SYM_NAME: uint = 2000;
-    const IMAGE_FILE_MACHINE_I386: libc::DWORD = 0x014c;
-    const IMAGE_FILE_MACHINE_IA64: libc::DWORD = 0x0200;
-    const IMAGE_FILE_MACHINE_AMD64: libc::DWORD = 0x8664;
-
-    #[repr(C)]
-    struct SYMBOL_INFO {
-        SizeOfStruct: libc::c_ulong,
-        TypeIndex: libc::c_ulong,
-        Reserved: [u64, ..2],
-        Index: libc::c_ulong,
-        Size: libc::c_ulong,
-        ModBase: u64,
-        Flags: libc::c_ulong,
-        Value: u64,
-        Address: u64,
-        Register: libc::c_ulong,
-        Scope: libc::c_ulong,
-        Tag: libc::c_ulong,
-        NameLen: libc::c_ulong,
-        MaxNameLen: libc::c_ulong,
-        // note that windows has this as 1, but it basically just means that
-        // the name is inline at the end of the struct. For us, we just bump
-        // the struct size up to MAX_SYM_NAME.
-        Name: [libc::c_char, ..MAX_SYM_NAME],
-    }
-
-
-    #[repr(C)]
-    enum ADDRESS_MODE {
-        AddrMode1616,
-        AddrMode1632,
-        AddrModeReal,
-        AddrModeFlat,
-    }
-
-    struct ADDRESS64 {
-        Offset: u64,
-        Segment: u16,
-        Mode: ADDRESS_MODE,
-    }
-
-    struct STACKFRAME64 {
-        AddrPC: ADDRESS64,
-        AddrReturn: ADDRESS64,
-        AddrFrame: ADDRESS64,
-        AddrStack: ADDRESS64,
-        AddrBStore: ADDRESS64,
-        FuncTableEntry: *mut libc::c_void,
-        Params: [u64, ..4],
-        Far: libc::BOOL,
-        Virtual: libc::BOOL,
-        Reserved: [u64, ..3],
-        KdHelp: KDHELP64,
-    }
-
-    struct KDHELP64 {
-        Thread: u64,
-        ThCallbackStack: libc::DWORD,
-        ThCallbackBStore: libc::DWORD,
-        NextCallback: libc::DWORD,
-        FramePointer: libc::DWORD,
-        KiCallUserMode: u64,
-        KeUserCallbackDispatcher: u64,
-        SystemRangeStart: u64,
-        KiUserExceptionDispatcher: u64,
-        StackBase: u64,
-        StackLimit: u64,
-        Reserved: [u64, ..5],
-    }
-
-    #[cfg(target_arch = "x86")]
-    mod arch {
-        use libc;
-
-        const MAXIMUM_SUPPORTED_EXTENSION: uint = 512;
-
-        #[repr(C)]
-        pub struct CONTEXT {
-            ContextFlags: libc::DWORD,
-            Dr0: libc::DWORD,
-            Dr1: libc::DWORD,
-            Dr2: libc::DWORD,
-            Dr3: libc::DWORD,
-            Dr6: libc::DWORD,
-            Dr7: libc::DWORD,
-            FloatSave: FLOATING_SAVE_AREA,
-            SegGs: libc::DWORD,
-            SegFs: libc::DWORD,
-            SegEs: libc::DWORD,
-            SegDs: libc::DWORD,
-            Edi: libc::DWORD,
-            Esi: libc::DWORD,
-            Ebx: libc::DWORD,
-            Edx: libc::DWORD,
-            Ecx: libc::DWORD,
-            Eax: libc::DWORD,
-            Ebp: libc::DWORD,
-            Eip: libc::DWORD,
-            SegCs: libc::DWORD,
-            EFlags: libc::DWORD,
-            Esp: libc::DWORD,
-            SegSs: libc::DWORD,
-            ExtendedRegisters: [u8, ..MAXIMUM_SUPPORTED_EXTENSION],
-        }
-
-        #[repr(C)]
-        pub struct FLOATING_SAVE_AREA {
-            ControlWord: libc::DWORD,
-            StatusWord: libc::DWORD,
-            TagWord: libc::DWORD,
-            ErrorOffset: libc::DWORD,
-            ErrorSelector: libc::DWORD,
-            DataOffset: libc::DWORD,
-            DataSelector: libc::DWORD,
-            RegisterArea: [u8, ..80],
-            Cr0NpxState: libc::DWORD,
-        }
-
-        pub fn init_frame(frame: &mut super::STACKFRAME64,
-                          ctx: &CONTEXT) -> libc::DWORD {
-            frame.AddrPC.Offset = ctx.Eip as u64;
-            frame.AddrPC.Mode = super::ADDRESS_MODE::AddrModeFlat;
-            frame.AddrStack.Offset = ctx.Esp as u64;
-            frame.AddrStack.Mode = super::ADDRESS_MODE::AddrModeFlat;
-            frame.AddrFrame.Offset = ctx.Ebp as u64;
-            frame.AddrFrame.Mode = super::ADDRESS_MODE::AddrModeFlat;
-            super::IMAGE_FILE_MACHINE_I386
-        }
-    }
-
-    #[cfg(target_arch = "x86_64")]
-    mod arch {
-        use libc::{c_longlong, c_ulonglong};
-        use libc::types::os::arch::extra::{WORD, DWORD, DWORDLONG};
-        use simd;
-
-        #[repr(C)]
-        pub struct CONTEXT {
-            _align_hack: [simd::u64x2, ..0], // FIXME align on 16-byte
-            P1Home: DWORDLONG,
-            P2Home: DWORDLONG,
-            P3Home: DWORDLONG,
-            P4Home: DWORDLONG,
-            P5Home: DWORDLONG,
-            P6Home: DWORDLONG,
-
-            ContextFlags: DWORD,
-            MxCsr: DWORD,
-
-            SegCs: WORD,
-            SegDs: WORD,
-            SegEs: WORD,
-            SegFs: WORD,
-            SegGs: WORD,
-            SegSs: WORD,
-            EFlags: DWORD,
-
-            Dr0: DWORDLONG,
-            Dr1: DWORDLONG,
-            Dr2: DWORDLONG,
-            Dr3: DWORDLONG,
-            Dr6: DWORDLONG,
-            Dr7: DWORDLONG,
-
-            Rax: DWORDLONG,
-            Rcx: DWORDLONG,
-            Rdx: DWORDLONG,
-            Rbx: DWORDLONG,
-            Rsp: DWORDLONG,
-            Rbp: DWORDLONG,
-            Rsi: DWORDLONG,
-            Rdi: DWORDLONG,
-            R8:  DWORDLONG,
-            R9:  DWORDLONG,
-            R10: DWORDLONG,
-            R11: DWORDLONG,
-            R12: DWORDLONG,
-            R13: DWORDLONG,
-            R14: DWORDLONG,
-            R15: DWORDLONG,
-
-            Rip: DWORDLONG,
-
-            FltSave: FLOATING_SAVE_AREA,
-
-            VectorRegister: [M128A, .. 26],
-            VectorControl: DWORDLONG,
-
-            DebugControl: DWORDLONG,
-            LastBranchToRip: DWORDLONG,
-            LastBranchFromRip: DWORDLONG,
-            LastExceptionToRip: DWORDLONG,
-            LastExceptionFromRip: DWORDLONG,
-        }
-
-        #[repr(C)]
-        pub struct M128A {
-            _align_hack: [simd::u64x2, ..0], // FIXME align on 16-byte
-            Low:  c_ulonglong,
-            High: c_longlong
-        }
-
-        #[repr(C)]
-        pub struct FLOATING_SAVE_AREA {
-            _align_hack: [simd::u64x2, ..0], // FIXME align on 16-byte
-            _Dummy: [u8, ..512] // FIXME: Fill this out
-        }
-
-        pub fn init_frame(frame: &mut super::STACKFRAME64,
-                          ctx: &CONTEXT) -> DWORD {
-            frame.AddrPC.Offset = ctx.Rip as u64;
-            frame.AddrPC.Mode = super::ADDRESS_MODE::AddrModeFlat;
-            frame.AddrStack.Offset = ctx.Rsp as u64;
-            frame.AddrStack.Mode = super::ADDRESS_MODE::AddrModeFlat;
-            frame.AddrFrame.Offset = ctx.Rbp as u64;
-            frame.AddrFrame.Mode = super::ADDRESS_MODE::AddrModeFlat;
-            super::IMAGE_FILE_MACHINE_AMD64
-        }
-    }
-
-    #[repr(C)]
-    struct Cleanup {
-        handle: libc::HANDLE,
-        SymCleanup: SymCleanupFn,
-    }
-
-    impl Drop for Cleanup {
-        fn drop(&mut self) { (self.SymCleanup)(self.handle); }
-    }
-
-    pub fn write(w: &mut Writer) -> IoResult<()> {
-        // According to windows documentation, all dbghelp functions are
-        // single-threaded.
-        static LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
-        let _g = unsafe { LOCK.lock() };
-
-        // Open up dbghelp.dll, we don't link to it explicitly because it can't
-        // always be found. Additionally, it's nice having fewer dependencies.
-        let path = Path::new("dbghelp.dll");
-        let lib = match DynamicLibrary::open(Some(&path)) {
-            Ok(lib) => lib,
-            Err(..) => return Ok(()),
-        };
-
-        macro_rules! sym( ($e:expr, $t:ident) => (unsafe {
-            match lib.symbol($e) {
-                Ok(f) => mem::transmute::<*mut u8, $t>(f),
-                Err(..) => return Ok(())
-            }
-        }) )
-
-        // Fetch the symbols necessary from dbghelp.dll
-        let SymFromAddr = sym!("SymFromAddr", SymFromAddrFn);
-        let SymInitialize = sym!("SymInitialize", SymInitializeFn);
-        let SymCleanup = sym!("SymCleanup", SymCleanupFn);
-        let StackWalk64 = sym!("StackWalk64", StackWalk64Fn);
-
-        // Allocate necessary structures for doing the stack walk
-        let process = unsafe { GetCurrentProcess() };
-        let thread = unsafe { GetCurrentThread() };
-        let mut context: arch::CONTEXT = unsafe { intrinsics::init() };
-        unsafe { RtlCaptureContext(&mut context); }
-        let mut frame: STACKFRAME64 = unsafe { intrinsics::init() };
-        let image = arch::init_frame(&mut frame, &context);
-
-        // Initialize this process's symbols
-        let ret = SymInitialize(process, 0 as *mut libc::c_void, libc::TRUE);
-        if ret != libc::TRUE { return Ok(()) }
-        let _c = Cleanup { handle: process, SymCleanup: SymCleanup };
-
-        // And now that we're done with all the setup, do the stack walking!
-        let mut i = 0i;
-        try!(write!(w, "stack backtrace:\n"));
-        while StackWalk64(image, process, thread, &mut frame, &mut context,
-                          0 as *mut libc::c_void,
-                          0 as *mut libc::c_void,
-                          0 as *mut libc::c_void,
-                          0 as *mut libc::c_void) == libc::TRUE{
-            let addr = frame.AddrPC.Offset;
-            if addr == frame.AddrReturn.Offset || addr == 0 ||
-               frame.AddrReturn.Offset == 0 { break }
-
-            i += 1;
-            try!(write!(w, "  {:2}: {:#2$x}", i, addr, super::HEX_WIDTH));
-            let mut info: SYMBOL_INFO = unsafe { intrinsics::init() };
-            info.MaxNameLen = MAX_SYM_NAME as libc::c_ulong;
-            // the struct size in C.  the value is different to
-            // `size_of::<SYMBOL_INFO>() - MAX_SYM_NAME + 1` (== 81)
-            // due to struct alignment.
-            info.SizeOfStruct = 88;
-
-            let mut displacement = 0u64;
-            let ret = SymFromAddr(process, addr as u64, &mut displacement,
-                                  &mut info);
-
-            if ret == libc::TRUE {
-                try!(write!(w, " - "));
-                let cstr = unsafe { CString::new(info.Name.as_ptr(), false) };
-                let bytes = cstr.as_bytes();
-                match cstr.as_str() {
-                    Some(s) => try!(super::demangle(w, s)),
-                    None => try!(w.write(bytes[..bytes.len()-1])),
-                }
-            }
-            try!(w.write(&['\n' as u8]));
-        }
-
-        Ok(())
-    }
-}
-
 #[cfg(test)]
 mod test {
     use prelude::*;
-    macro_rules! t( ($a:expr, $b:expr) => ({
+    use sys_common;
+    macro_rules! t { ($a:expr, $b:expr) => ({
         let mut m = Vec::new();
-        super::demangle(&mut m, $a).unwrap();
-        assert_eq!(String::from_utf8(m).unwrap(), $b.to_string());
-    }) )
+        sys_common::backtrace::demangle(&mut m, $a).unwrap();
+        assert_eq!(String::from_utf8(m).unwrap(), $b);
+    }) }
 
     #[test]
     fn demangle() {
@@ -1036,4 +68,11 @@ mod test {
         t!("_ZN12test$x20test4foobE", "test test::foob");
         t!("_ZN12test$UP$test4foobE", "testBoxtest::foob");
     }
+
+    #[test]
+    fn demangle_windows() {
+        t!("ZN4testE", "test");
+        t!("ZN12test$x20test4foobE", "test test::foob");
+        t!("ZN12test$UP$test4foobE", "testBoxtest::foob");
+    }
 }
diff --git a/src/libstd/rt/exclusive.rs b/src/libstd/rt/exclusive.rs
new file mode 100644
index 00000000000..1d3082d1b4c
--- /dev/null
+++ b/src/libstd/rt/exclusive.rs
@@ -0,0 +1,115 @@
+// Copyright 2013 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.
+
+use core::prelude::*;
+
+use cell::UnsafeCell;
+use rt::mutex;
+
+/// An OS mutex over some data.
+///
+/// This is not a safe primitive to use, it is unaware of the libgreen
+/// scheduler, as well as being easily susceptible to misuse due to the usage of
+/// the inner NativeMutex.
+///
+/// > **Note**: This type is not recommended for general use. The mutex provided
+/// >           as part of `libsync` should almost always be favored.
+pub struct Exclusive<T> {
+    lock: mutex::NativeMutex,
+    data: UnsafeCell<T>,
+}
+
+/// An RAII guard returned via `lock`
+pub struct ExclusiveGuard<'a, T:'a> {
+    // FIXME #12808: strange name to try to avoid interfering with
+    // field accesses of the contained type via Deref
+    _data: &'a mut T,
+    _guard: mutex::LockGuard<'a>,
+}
+
+impl<T: Send> Exclusive<T> {
+    /// Creates a new `Exclusive` which will protect the data provided.
+    pub fn new(user_data: T) -> Exclusive<T> {
+        Exclusive {
+            lock: unsafe { mutex::NativeMutex::new() },
+            data: UnsafeCell::new(user_data),
+        }
+    }
+
+    /// Acquires this lock, returning a guard which the data is accessed through
+    /// and from which that lock will be unlocked.
+    ///
+    /// This method is unsafe due to many of the same reasons that the
+    /// NativeMutex itself is unsafe.
+    pub unsafe fn lock<'a>(&'a self) -> ExclusiveGuard<'a, T> {
+        let guard = self.lock.lock();
+        let data = &mut *self.data.get();
+
+        ExclusiveGuard {
+            _data: data,
+            _guard: guard,
+        }
+    }
+}
+
+impl<'a, T: Send> ExclusiveGuard<'a, T> {
+    // The unsafety here should be ok because our loan guarantees that the lock
+    // itself is not moving
+    pub fn signal(&self) {
+        unsafe { self._guard.signal() }
+    }
+    pub fn wait(&self) {
+        unsafe { self._guard.wait() }
+    }
+}
+
+impl<'a, T: Send> Deref<T> for ExclusiveGuard<'a, T> {
+    fn deref(&self) -> &T { &*self._data }
+}
+impl<'a, T: Send> DerefMut<T> for ExclusiveGuard<'a, T> {
+    fn deref_mut(&mut self) -> &mut T { &mut *self._data }
+}
+
+#[cfg(test)]
+mod tests {
+    use prelude::*;
+    use sync::Arc;
+    use super::Exclusive;
+    use task;
+
+    #[test]
+    fn exclusive_new_arc() {
+        unsafe {
+            let mut futures = Vec::new();
+
+            let num_tasks = 10;
+            let count = 10;
+
+            let total = Arc::new(Exclusive::new(box 0));
+
+            for _ in range(0u, num_tasks) {
+                let total = total.clone();
+                let (tx, rx) = channel();
+                futures.push(rx);
+
+                task::spawn(move || {
+                    for _ in range(0u, count) {
+                        **total.lock() += 1;
+                    }
+                    tx.send(());
+                });
+            };
+
+            for f in futures.iter_mut() { f.recv() }
+
+            assert_eq!(**total.lock(), num_tasks * count);
+        }
+    }
+}
diff --git a/src/libstd/rt/libunwind.rs b/src/libstd/rt/libunwind.rs
new file mode 100644
index 00000000000..2feea7fa0a4
--- /dev/null
+++ b/src/libstd/rt/libunwind.rs
@@ -0,0 +1,128 @@
+// 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.
+
+//! Unwind library interface
+
+#![allow(non_upper_case_globals)]
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+#![allow(dead_code)] // these are just bindings
+
+#[cfg(any(not(target_arch = "arm"), target_os = "ios"))]
+pub use self::_Unwind_Action::*;
+#[cfg(target_arch = "arm")]
+pub use self::_Unwind_State::*;
+pub use self::_Unwind_Reason_Code::*;
+
+use libc;
+
+#[cfg(any(not(target_arch = "arm"), target_os = "ios"))]
+#[repr(C)]
+#[deriving(Copy)]
+pub enum _Unwind_Action {
+    _UA_SEARCH_PHASE = 1,
+    _UA_CLEANUP_PHASE = 2,
+    _UA_HANDLER_FRAME = 4,
+    _UA_FORCE_UNWIND = 8,
+    _UA_END_OF_STACK = 16,
+}
+
+#[cfg(target_arch = "arm")]
+#[repr(C)]
+pub enum _Unwind_State {
+    _US_VIRTUAL_UNWIND_FRAME = 0,
+    _US_UNWIND_FRAME_STARTING = 1,
+    _US_UNWIND_FRAME_RESUME = 2,
+    _US_ACTION_MASK = 3,
+    _US_FORCE_UNWIND = 8,
+    _US_END_OF_STACK = 16
+}
+
+#[repr(C)]
+pub enum _Unwind_Reason_Code {
+    _URC_NO_REASON = 0,
+    _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
+    _URC_FATAL_PHASE2_ERROR = 2,
+    _URC_FATAL_PHASE1_ERROR = 3,
+    _URC_NORMAL_STOP = 4,
+    _URC_END_OF_STACK = 5,
+    _URC_HANDLER_FOUND = 6,
+    _URC_INSTALL_CONTEXT = 7,
+    _URC_CONTINUE_UNWIND = 8,
+    _URC_FAILURE = 9, // used only by ARM EABI
+}
+
+pub type _Unwind_Exception_Class = u64;
+
+pub type _Unwind_Word = libc::uintptr_t;
+
+#[cfg(target_arch = "x86")]
+pub const unwinder_private_data_size: uint = 5;
+
+#[cfg(target_arch = "x86_64")]
+pub const unwinder_private_data_size: uint = 6;
+
+#[cfg(all(target_arch = "arm", not(target_os = "ios")))]
+pub const unwinder_private_data_size: uint = 20;
+
+#[cfg(all(target_arch = "arm", target_os = "ios"))]
+pub const unwinder_private_data_size: uint = 5;
+
+#[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
+pub const unwinder_private_data_size: uint = 2;
+
+#[repr(C)]
+pub struct _Unwind_Exception {
+    pub exception_class: _Unwind_Exception_Class,
+    pub exception_cleanup: _Unwind_Exception_Cleanup_Fn,
+    pub private: [_Unwind_Word, ..unwinder_private_data_size],
+}
+
+pub enum _Unwind_Context {}
+
+pub type _Unwind_Exception_Cleanup_Fn =
+        extern "C" fn(unwind_code: _Unwind_Reason_Code,
+                      exception: *mut _Unwind_Exception);
+
+#[cfg(any(target_os = "linux", target_os = "freebsd"))]
+#[link(name = "gcc_s")]
+extern {}
+
+#[cfg(target_os = "android")]
+#[link(name = "gcc")]
+extern {}
+
+#[cfg(target_os = "dragonfly")]
+#[link(name = "gcc_pic")]
+extern {}
+
+extern "C" {
+    // iOS on armv7 uses SjLj exceptions and requires to link
+    // against corresponding routine (..._SjLj_...)
+    #[cfg(not(all(target_os = "ios", target_arch = "arm")))]
+    pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception)
+                                  -> _Unwind_Reason_Code;
+
+    #[cfg(all(target_os = "ios", target_arch = "arm"))]
+    fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception)
+                                   -> _Unwind_Reason_Code;
+
+    pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception);
+}
+
+// ... and now we just providing access to SjLj counterspart
+// through a standard name to hide those details from others
+// (see also comment above regarding _Unwind_RaiseException)
+#[cfg(all(target_os = "ios", target_arch = "arm"))]
+#[inline(always)]
+pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception)
+                                     -> _Unwind_Reason_Code {
+    _Unwind_SjLj_RaiseException(exc)
+}
diff --git a/src/libstd/rt/macros.rs b/src/libstd/rt/macros.rs
new file mode 100644
index 00000000000..bee8b5b82f4
--- /dev/null
+++ b/src/libstd/rt/macros.rs
@@ -0,0 +1,45 @@
+// Copyright 2012 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.
+
+//! Macros used by the runtime.
+//!
+//! These macros call functions which are only accessible in the `rt` module, so
+//! they aren't defined anywhere outside of the `rt` module.
+
+#![macro_escape]
+
+macro_rules! rterrln {
+    ($fmt:expr $($arg:tt)*) => ( {
+        format_args!(::rt::util::dumb_print, concat!($fmt, "\n") $($arg)*)
+    } )
+}
+
+// Some basic logging. Enabled by passing `--cfg rtdebug` to the libstd build.
+macro_rules! rtdebug {
+    ($($arg:tt)*) => ( {
+        if cfg!(rtdebug) {
+            rterrln!($($arg)*)
+        }
+    })
+}
+
+macro_rules! rtassert {
+    ( $arg:expr ) => ( {
+        if ::rt::util::ENFORCE_SANITY {
+            if !$arg {
+                rtabort!(" assertion failed: {}", stringify!($arg));
+            }
+        }
+    } )
+}
+
+macro_rules! rtabort {
+    ($($arg:tt)*) => (format_args!(::rt::util::abort, $($arg)*))
+}
diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs
index 21b4edb6375..d64336569c6 100644
--- a/src/libstd/rt/mod.rs
+++ b/src/libstd/rt/mod.rs
@@ -8,46 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/*! Runtime services, including the task scheduler and I/O dispatcher
-
-The `rt` module provides the private runtime infrastructure necessary
-to support core language features like the exchange and local heap,
-logging, local data and unwinding. It also implements the default task
-scheduler and task model. Initialization routines are provided for setting
-up runtime resources in common configurations, including that used by
-`rustc` when generating executables.
-
-It is intended that the features provided by `rt` can be factored in a
-way such that the core library can be built with different 'profiles'
-for different use cases, e.g. excluding the task scheduler. A number
-of runtime features though are critical to the functioning of the
-language and an implementation must be provided regardless of the
-execution environment.
-
-Of foremost importance is the global exchange heap, in the module
-`heap`. Very little practical Rust code can be written without
-access to the global heap. Unlike most of `rt` the global heap is
-truly a global resource and generally operates independently of the
-rest of the runtime.
-
-All other runtime features are task-local, including the local heap,
-local storage, logging and the stack unwinder.
-
-The relationship between `rt` and the rest of the core library is
-not entirely clear yet and some modules will be moving into or
-out of `rt` as development proceeds.
-
-Several modules in `core` are clients of `rt`:
-
-* `std::task` - The user-facing interface to the Rust task model.
-* `std::local_data` - The interface to local data.
-* `std::unstable::lang` - Miscellaneous lang items, some of which rely on `std::rt`.
-* `std::cleanup` - Local heap destruction.
-* `std::io` - In the future `std::io` will use an `rt` implementation.
-* `std::logging`
-* `std::comm`
-
-*/
+//! Runtime services
+//!
+//! The `rt` module provides a narrow set of runtime services,
+//! including the global heap (exported in `heap`) and unwinding and
+//! backtrace support. The APIs in this module are highly unstable,
+//! and should be considered as private implementation details for the
+//! time being.
 
 #![experimental]
 
@@ -56,64 +23,51 @@ Several modules in `core` are clients of `rt`:
 
 #![allow(dead_code)]
 
-use failure;
-use rustrt;
 use os;
+use thunk::Thunk;
+use kinds::Send;
+use thread::Thread;
+use ops::FnOnce;
+use sys;
+use sys_common;
+use sys_common::thread_info::{mod, NewThread};
 
 // Reexport some of our utilities which are expected by other crates.
 pub use self::util::{default_sched_threads, min_stack, running_on_valgrind};
+pub use self::unwind::{begin_unwind, begin_unwind_fmt};
 
-// Reexport functionality from librustrt and other crates underneath the
-// standard library which work together to create the entire runtime.
+// Reexport some functionality from liballoc.
 pub use alloc::heap;
-pub use rustrt::{begin_unwind, begin_unwind_fmt, at_exit};
 
 // Simple backtrace functionality (to print on panic)
 pub mod backtrace;
 
-// Just stuff
-mod util;
+// Internals
+mod macros;
 
-/// One-time runtime initialization.
-///
-/// Initializes global state, including frobbing
-/// the crate's logging flags, registering GC
-/// metadata, and storing the process arguments.
-#[allow(experimental)]
-pub fn init(argc: int, argv: *const *const u8) {
-    rustrt::init(argc, argv);
-    unsafe { rustrt::unwind::register(failure::on_fail); }
-}
+// These should be refactored/moved/made private over time
+pub mod util;
+pub mod unwind;
+pub mod args;
+
+mod at_exit_imp;
+mod libunwind;
+
+/// The default error code of the rust runtime if the main task panics instead
+/// of exiting cleanly.
+pub const DEFAULT_ERROR_CODE: int = 101;
 
 #[cfg(any(windows, android))]
-static OS_DEFAULT_STACK_ESTIMATE: uint = 1 << 20;
+const OS_DEFAULT_STACK_ESTIMATE: uint = 1 << 20;
 #[cfg(all(unix, not(android)))]
-static OS_DEFAULT_STACK_ESTIMATE: uint = 2 * (1 << 20);
+const OS_DEFAULT_STACK_ESTIMATE: uint = 2 * (1 << 20);
 
 #[cfg(not(test))]
 #[lang = "start"]
 fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int {
     use mem;
-    start(argc, argv, proc() {
-        let main: extern "Rust" fn() = unsafe { mem::transmute(main) };
-        main();
-    })
-}
-
-/// Executes the given procedure after initializing the runtime with the given
-/// argc/argv.
-///
-/// This procedure is guaranteed to run on the thread calling this function, but
-/// the stack bounds for this rust task will *not* be set. Care must be taken
-/// for this function to not overflow its stack.
-///
-/// This function will only return once *all* native threads in the system have
-/// exited.
-pub fn start(argc: int, argv: *const *const u8, main: proc()) -> int {
     use prelude::*;
     use rt;
-    use rustrt::task::Task;
-    use str;
 
     let something_around_the_top_of_the_stack = 1;
     let addr = &something_around_the_top_of_the_stack as *const int;
@@ -124,40 +78,76 @@ pub fn start(argc: int, argv: *const *const u8, main: proc()) -> int {
     // frames above our current position.
     let my_stack_bottom = my_stack_top + 20000 - OS_DEFAULT_STACK_ESTIMATE;
 
-    // When using libgreen, one of the first things that we do is to turn off
-    // the SIGPIPE signal (set it to ignore). By default, some platforms will
-    // send a *signal* when a EPIPE error would otherwise be delivered. This
-    // runtime doesn't install a SIGPIPE handler, causing it to kill the
-    // program, which isn't exactly what we want!
-    //
-    // Hence, we set SIGPIPE to ignore when the program starts up in order to
-    // prevent this problem.
-    #[cfg(windows)] fn ignore_sigpipe() {}
-    #[cfg(unix)] fn ignore_sigpipe() {
-        use libc;
-        use libc::funcs::posix01::signal::signal;
-        unsafe {
-            assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != -1);
+    let failed = unsafe {
+        // First, make sure we don't trigger any __morestack overflow checks,
+        // and next set up our stack to have a guard page and run through our
+        // own fault handlers if we hit it.
+        sys_common::stack::record_os_managed_stack_bounds(my_stack_bottom,
+                                                          my_stack_top);
+        sys::thread::guard::init();
+        sys::stack_overflow::init();
+
+        // Next, set up the current Thread with the guard information we just
+        // created. Note that this isn't necessary in general for new threads,
+        // but we just do this to name the main thread and to give it correct
+        // info about the stack bounds.
+        let thread: Thread = NewThread::new(Some("<main>".to_string()));
+        thread_info::set((my_stack_bottom, my_stack_top),
+                         sys::thread::guard::main(),
+                         thread);
+
+        // By default, some platforms will send a *signal* when a EPIPE error
+        // would otherwise be delivered. This runtime doesn't install a SIGPIPE
+        // handler, causing it to kill the program, which isn't exactly what we
+        // want!
+        //
+        // Hence, we set SIGPIPE to ignore when the program starts up in order
+        // to prevent this problem.
+        #[cfg(windows)] fn ignore_sigpipe() {}
+        #[cfg(unix)] fn ignore_sigpipe() {
+            use libc;
+            use libc::funcs::posix01::signal::signal;
+            unsafe {
+                assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != -1);
+            }
         }
+        ignore_sigpipe();
+
+        // Store our args if necessary in a squirreled away location
+        args::init(argc, argv);
+
+        // And finally, let's run some code!
+        let res = unwind::try(|| {
+            let main: fn() = mem::transmute(main);
+            main();
+        });
+        cleanup();
+        res.is_err()
+    };
+
+    // If the exit code wasn't set, then the try block must have panicked.
+    if failed {
+        rt::DEFAULT_ERROR_CODE
+    } else {
+        os::get_exit_status()
     }
-    ignore_sigpipe();
-
-    init(argc, argv);
-    let mut exit_code = None;
-    let mut main = Some(main);
-    let mut task = box Task::new(Some((my_stack_bottom, my_stack_top)),
-                                 Some(rustrt::thread::main_guard_page()));
-    task.name = Some(str::Slice("<main>"));
-    drop(task.run(|| {
-        unsafe {
-            rustrt::stack::record_os_managed_stack_bounds(my_stack_bottom, my_stack_top);
-        }
-        (main.take().unwrap())();
-        exit_code = Some(os::get_exit_status());
-    }).destroy());
-    unsafe { rt::cleanup(); }
-    // If the exit code wasn't set, then the task block must have panicked.
-    return exit_code.unwrap_or(rustrt::DEFAULT_ERROR_CODE);
+}
+
+/// Enqueues a procedure to run when the runtime is cleaned up
+///
+/// The procedure passed to this function will be executed as part of the
+/// runtime cleanup phase. For normal rust programs, this means that it will run
+/// after all other tasks have exited.
+///
+/// The procedure is *not* executed with a local `Task` available to it, so
+/// primitives like logging, I/O, channels, spawning, etc, are *not* available.
+/// This is meant for "bare bones" usage to clean up runtime details, this is
+/// not meant as a general-purpose "let's clean everything up" function.
+///
+/// It is forbidden for procedures to register more `at_exit` handlers when they
+/// are running, and doing so will lead to a process abort.
+pub fn at_exit<F:FnOnce()+Send>(f: F) {
+    at_exit_imp::push(Thunk::new(f));
 }
 
 /// One-time runtime cleanup.
@@ -170,5 +160,10 @@ pub fn start(argc: int, argv: *const *const u8, main: proc()) -> int {
 /// Invoking cleanup while portions of the runtime are still in use may cause
 /// undefined behavior.
 pub unsafe fn cleanup() {
-    rustrt::cleanup();
+    args::cleanup();
+    sys::stack_overflow::cleanup();
+    // FIXME: (#20012): the resources being cleaned up by at_exit
+    // currently are not prepared for cleanup to happen asynchronously
+    // with detached threads using the resources; for now, we leak.
+    // at_exit_imp::cleanup();
 }
diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs
new file mode 100644
index 00000000000..98940a2b381
--- /dev/null
+++ b/src/libstd/rt/task.rs
@@ -0,0 +1,554 @@
+// 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.
+
+//! Language-level runtime services that should reasonably expected
+//! to be available 'everywhere'. Unwinding, local storage, and logging.
+//! Even a 'freestanding' Rust would likely want to implement this.
+
+pub use self::BlockedTask::*;
+use self::TaskState::*;
+
+use any::Any;
+use boxed::Box;
+use sync::Arc;
+use sync::atomic::{AtomicUint, SeqCst};
+use iter::{IteratorExt, Take};
+use kinds::marker;
+use mem;
+use ops::FnMut;
+use core::prelude::{Clone, Drop, Err, Iterator, None, Ok, Option, Send, Some};
+use core::prelude::{drop};
+use str::SendStr;
+use thunk::Thunk;
+
+use rt;
+use rt::mutex::NativeMutex;
+use rt::local::Local;
+use rt::thread::{mod, Thread};
+use sys_common::stack;
+use rt::unwind;
+use rt::unwind::Unwinder;
+
+/// State associated with Rust tasks.
+///
+/// This structure is currently undergoing major changes, and is
+/// likely to be move/be merged with a `Thread` structure.
+pub struct Task {
+    pub unwinder: Unwinder,
+    pub death: Death,
+    pub name: Option<SendStr>,
+
+    state: TaskState,
+    lock: NativeMutex,       // native synchronization
+    awoken: bool,            // used to prevent spurious wakeups
+
+    // This field holds the known bounds of the stack in (lo, hi) form. Not all
+    // native tasks necessarily know their precise bounds, hence this is
+    // optional.
+    stack_bounds: (uint, uint),
+
+    stack_guard: uint
+}
+
+// Once a task has entered the `Armed` state it must be destroyed via `drop`,
+// and no other method. This state is used to track this transition.
+#[deriving(PartialEq)]
+enum TaskState {
+    New,
+    Armed,
+    Destroyed,
+}
+
+pub struct TaskOpts {
+    /// Invoke this procedure with the result of the task when it finishes.
+    pub on_exit: Option<Thunk<Result>>,
+    /// A name for the task-to-be, for identification in panic messages
+    pub name: Option<SendStr>,
+    /// The size of the stack for the spawned task
+    pub stack_size: Option<uint>,
+}
+
+/// Indicates the manner in which a task exited.
+///
+/// A task that completes without panicking is considered to exit successfully.
+///
+/// If you wish for this result's delivery to block until all
+/// children tasks complete, recommend using a result future.
+pub type Result = ::core::result::Result<(), Box<Any + Send>>;
+
+/// A handle to a blocked task. Usually this means having the Box<Task>
+/// pointer by ownership, but if the task is killable, a killer can steal it
+/// at any time.
+pub enum BlockedTask {
+    Owned(Box<Task>),
+    Shared(Arc<AtomicUint>),
+}
+
+/// Per-task state related to task death, killing, panic, etc.
+pub struct Death {
+    pub on_exit: Option<Thunk<Result>>,
+}
+
+pub struct BlockedTasks {
+    inner: Arc<AtomicUint>,
+}
+
+impl Task {
+    /// Creates a new uninitialized task.
+    pub fn new(stack_bounds: Option<(uint, uint)>, stack_guard: Option<uint>) -> Task {
+        Task {
+            unwinder: Unwinder::new(),
+            death: Death::new(),
+            state: New,
+            name: None,
+            lock: unsafe { NativeMutex::new() },
+            awoken: false,
+            // these *should* get overwritten
+            stack_bounds: stack_bounds.unwrap_or((0, 0)),
+            stack_guard: stack_guard.unwrap_or(0)
+        }
+    }
+
+    pub fn spawn<F>(opts: TaskOpts, f: F)
+        where F : FnOnce(), F : Send
+    {
+        Task::spawn_thunk(opts, Thunk::new(f))
+    }
+
+    fn spawn_thunk(opts: TaskOpts, f: Thunk) {
+        let TaskOpts { name, stack_size, on_exit } = opts;
+
+        let mut task = box Task::new(None, None);
+        task.name = name;
+        task.death.on_exit = on_exit;
+
+        let stack = stack_size.unwrap_or(rt::min_stack());
+
+        // Spawning a new OS thread guarantees that __morestack will never get
+        // triggered, but we must manually set up the actual stack bounds once
+        // this function starts executing. This raises the lower limit by a bit
+        // because by the time that this function is executing we've already
+        // consumed at least a little bit of stack (we don't know the exact byte
+        // address at which our stack started).
+        Thread::spawn_stack(stack, move|| {
+            let something_around_the_top_of_the_stack = 1;
+            let addr = &something_around_the_top_of_the_stack as *const int;
+            let my_stack = addr as uint;
+            unsafe {
+                stack::record_os_managed_stack_bounds(my_stack - stack + 1024,
+                                                      my_stack);
+            }
+            task.stack_guard = thread::current_guard_page();
+            task.stack_bounds = (my_stack - stack + 1024, my_stack);
+
+            let mut f = Some(f);
+            drop(task.run(|| { f.take().unwrap().invoke(()) }).destroy());
+        })
+    }
+
+    /// Consumes ownership of a task, runs some code, and returns the task back.
+    ///
+    /// This function can be used as an emulated "try/catch" to interoperate
+    /// with the rust runtime at the outermost boundary. It is not possible to
+    /// use this function in a nested fashion (a try/catch inside of another
+    /// try/catch). Invoking this function is quite cheap.
+    ///
+    /// If the closure `f` succeeds, then the returned task can be used again
+    /// for another invocation of `run`. If the closure `f` panics then `self`
+    /// will be internally destroyed along with all of the other associated
+    /// resources of this task. The `on_exit` callback is invoked with the
+    /// cause of panic (not returned here). This can be discovered by querying
+    /// `is_destroyed()`.
+    ///
+    /// Note that it is possible to view partial execution of the closure `f`
+    /// because it is not guaranteed to run to completion, but this function is
+    /// guaranteed to return if it panicks. Care should be taken to ensure that
+    /// stack references made by `f` are handled appropriately.
+    ///
+    /// It is invalid to call this function with a task that has been previously
+    /// destroyed via a failed call to `run`.
+    pub fn run(mut self: Box<Task>, f: ||) -> Box<Task> {
+        assert!(!self.is_destroyed(), "cannot re-use a destroyed task");
+
+        // First, make sure that no one else is in TLS. This does not allow
+        // recursive invocations of run(). If there's no one else, then
+        // relinquish ownership of ourselves back into TLS.
+        if Local::exists(None::<Task>) {
+            panic!("cannot run a task recursively inside another");
+        }
+        self.state = Armed;
+        Local::put(self);
+
+        // There are two primary reasons that general try/catch is unsafe. The
+        // first is that we do not support nested try/catch. The above check for
+        // an existing task in TLS is sufficient for this invariant to be
+        // upheld. The second is that unwinding while unwinding is not defined.
+        // We take care of that by having an 'unwinding' flag in the task
+        // itself. For these reasons, this unsafety should be ok.
+        let result = unsafe { unwind::try(f) };
+
+        // After running the closure given return the task back out if it ran
+        // successfully, or clean up the task if it panicked.
+        let task: Box<Task> = Local::take();
+        match result {
+            Ok(()) => task,
+            Err(cause) => { task.cleanup(Err(cause)) }
+        }
+    }
+
+    /// Destroy all associated resources of this task.
+    ///
+    /// This function will perform any necessary clean up to prepare the task
+    /// for destruction. It is required that this is called before a `Task`
+    /// falls out of scope.
+    ///
+    /// The returned task cannot be used for running any more code, but it may
+    /// be used to extract the runtime as necessary.
+    pub fn destroy(self: Box<Task>) -> Box<Task> {
+        if self.is_destroyed() {
+            self
+        } else {
+            self.cleanup(Ok(()))
+        }
+    }
+
+    /// Cleans up a task, processing the result of the task as appropriate.
+    ///
+    /// This function consumes ownership of the task, deallocating it once it's
+    /// done being processed. It is assumed that TLD and the local heap have
+    /// already been destroyed and/or annihilated.
+    fn cleanup(mut self: Box<Task>, result: Result) -> Box<Task> {
+        // After taking care of the data above, we need to transmit the result
+        // of this task.
+        let what_to_do = self.death.on_exit.take();
+        Local::put(self);
+
+        // FIXME: this is running in a seriously constrained context. If this
+        //        allocates TLD then it will likely abort the runtime. Similarly,
+        //        if this panics, this will also likely abort the runtime.
+        //
+        //        This closure is currently limited to a channel send via the
+        //        standard library's task interface, but this needs
+        //        reconsideration to whether it's a reasonable thing to let a
+        //        task to do or not.
+        match what_to_do {
+            Some(f) => { f.invoke(result) }
+            None => { drop(result) }
+        }
+
+        // Now that we're done, we remove the task from TLS and flag it for
+        // destruction.
+        let mut task: Box<Task> = Local::take();
+        task.state = Destroyed;
+        return task;
+    }
+
+    /// Queries whether this can be destroyed or not.
+    pub fn is_destroyed(&self) -> bool { self.state == Destroyed }
+
+    /// Deschedules the current task, invoking `f` `amt` times. It is not
+    /// recommended to use this function directly, but rather communication
+    /// primitives in `std::comm` should be used.
+    //
+    // This function gets a little interesting. There are a few safety and
+    // ownership violations going on here, but this is all done in the name of
+    // shared state. Additionally, all of the violations are protected with a
+    // mutex, so in theory there are no races.
+    //
+    // The first thing we need to do is to get a pointer to the task's internal
+    // mutex. This address will not be changing (because the task is allocated
+    // on the heap). We must have this handle separately because the task will
+    // have its ownership transferred to the given closure. We're guaranteed,
+    // however, that this memory will remain valid because *this* is the current
+    // task's execution thread.
+    //
+    // The next weird part is where ownership of the task actually goes. We
+    // relinquish it to the `f` blocking function, but upon returning this
+    // function needs to replace the task back in TLS. There is no communication
+    // from the wakeup thread back to this thread about the task pointer, and
+    // there's really no need to. In order to get around this, we cast the task
+    // to a `uint` which is then used at the end of this function to cast back
+    // to a `Box<Task>` object. Naturally, this looks like it violates
+    // ownership semantics in that there may be two `Box<Task>` objects.
+    //
+    // The fun part is that the wakeup half of this implementation knows to
+    // "forget" the task on the other end. This means that the awakening half of
+    // things silently relinquishes ownership back to this thread, but not in a
+    // way that the compiler can understand. The task's memory is always valid
+    // for both tasks because these operations are all done inside of a mutex.
+    //
+    // You'll also find that if blocking fails (the `f` function hands the
+    // BlockedTask back to us), we will `mem::forget` the handles. The
+    // reasoning for this is the same logic as above in that the task silently
+    // transfers ownership via the `uint`, not through normal compiler
+    // semantics.
+    //
+    // On a mildly unrelated note, it should also be pointed out that OS
+    // condition variables are susceptible to spurious wakeups, which we need to
+    // be ready for. In order to accommodate for this fact, we have an extra
+    // `awoken` field which indicates whether we were actually woken up via some
+    // invocation of `reawaken`. This flag is only ever accessed inside the
+    // lock, so there's no need to make it atomic.
+    pub fn deschedule<F>(mut self: Box<Task>, times: uint, mut f: F) where
+        F: FnMut(BlockedTask) -> ::core::result::Result<(), BlockedTask>,
+    {
+        unsafe {
+            let me = &mut *self as *mut Task;
+            let task = BlockedTask::block(self);
+
+            if times == 1 {
+                let guard = (*me).lock.lock();
+                (*me).awoken = false;
+                match f(task) {
+                    Ok(()) => {
+                        while !(*me).awoken {
+                            guard.wait();
+                        }
+                    }
+                    Err(task) => { mem::forget(task.wake()); }
+                }
+            } else {
+                let iter = task.make_selectable(times);
+                let guard = (*me).lock.lock();
+                (*me).awoken = false;
+
+                // Apply the given closure to all of the "selectable tasks",
+                // bailing on the first one that produces an error. Note that
+                // care must be taken such that when an error is occurred, we
+                // may not own the task, so we may still have to wait for the
+                // task to become available. In other words, if task.wake()
+                // returns `None`, then someone else has ownership and we must
+                // wait for their signal.
+                match iter.map(f).filter_map(|a| a.err()).next() {
+                    None => {}
+                    Some(task) => {
+                        match task.wake() {
+                            Some(task) => {
+                                mem::forget(task);
+                                (*me).awoken = true;
+                            }
+                            None => {}
+                        }
+                    }
+                }
+                while !(*me).awoken {
+                    guard.wait();
+                }
+            }
+            // put the task back in TLS, and everything is as it once was.
+            Local::put(mem::transmute(me));
+        }
+    }
+
+    /// Wakes up a previously blocked task. This function can only be
+    /// called on tasks that were previously blocked in `deschedule`.
+    //
+    // See the comments on `deschedule` for why the task is forgotten here, and
+    // why it's valid to do so.
+    pub fn reawaken(mut self: Box<Task>) {
+        unsafe {
+            let me = &mut *self as *mut Task;
+            mem::forget(self);
+            let guard = (*me).lock.lock();
+            (*me).awoken = true;
+            guard.signal();
+        }
+    }
+
+    /// Yields control of this task to another task. This function will
+    /// eventually return, but possibly not immediately. This is used as an
+    /// opportunity to allow other tasks a chance to run.
+    pub fn yield_now() {
+        Thread::yield_now();
+    }
+
+    /// Returns the stack bounds for this task in (lo, hi) format. The stack
+    /// bounds may not be known for all tasks, so the return value may be
+    /// `None`.
+    pub fn stack_bounds(&self) -> (uint, uint) {
+        self.stack_bounds
+    }
+
+    /// Returns the stack guard for this task, if known.
+    pub fn stack_guard(&self) -> Option<uint> {
+        if self.stack_guard != 0 {
+            Some(self.stack_guard)
+        } else {
+            None
+        }
+    }
+
+    /// Consume this task, flagging it as a candidate for destruction.
+    ///
+    /// This function is required to be invoked to destroy a task. A task
+    /// destroyed through a normal drop will abort.
+    pub fn drop(mut self) {
+        self.state = Destroyed;
+    }
+}
+
+impl Drop for Task {
+    fn drop(&mut self) {
+        rtdebug!("called drop for a task: {}", self as *mut Task as uint);
+        rtassert!(self.state != Armed);
+    }
+}
+
+impl TaskOpts {
+    pub fn new() -> TaskOpts {
+        TaskOpts { on_exit: None, name: None, stack_size: None }
+    }
+}
+
+impl Iterator<BlockedTask> for BlockedTasks {
+    fn next(&mut self) -> Option<BlockedTask> {
+        Some(Shared(self.inner.clone()))
+    }
+}
+
+impl BlockedTask {
+    /// Returns Some if the task was successfully woken; None if already killed.
+    pub fn wake(self) -> Option<Box<Task>> {
+        match self {
+            Owned(task) => Some(task),
+            Shared(arc) => {
+                match arc.swap(0, SeqCst) {
+                    0 => None,
+                    n => Some(unsafe { mem::transmute(n) }),
+                }
+            }
+        }
+    }
+
+    /// Reawakens this task if ownership is acquired. If finer-grained control
+    /// is desired, use `wake` instead.
+    pub fn reawaken(self) {
+        self.wake().map(|t| t.reawaken());
+    }
+
+    // This assertion has two flavours because the wake involves an atomic op.
+    // In the faster version, destructors will panic dramatically instead.
+    #[cfg(not(test))] pub fn trash(self) { }
+    #[cfg(test)]      pub fn trash(self) { assert!(self.wake().is_none()); }
+
+    /// Create a blocked task, unless the task was already killed.
+    pub fn block(task: Box<Task>) -> BlockedTask {
+        Owned(task)
+    }
+
+    /// Converts one blocked task handle to a list of many handles to the same.
+    pub fn make_selectable(self, num_handles: uint) -> Take<BlockedTasks> {
+        let arc = match self {
+            Owned(task) => {
+                let flag = unsafe { AtomicUint::new(mem::transmute(task)) };
+                Arc::new(flag)
+            }
+            Shared(arc) => arc.clone(),
+        };
+        BlockedTasks{ inner: arc }.take(num_handles)
+    }
+
+    /// Convert to an unsafe uint value. Useful for storing in a pipe's state
+    /// flag.
+    #[inline]
+    pub unsafe fn cast_to_uint(self) -> uint {
+        match self {
+            Owned(task) => {
+                let blocked_task_ptr: uint = mem::transmute(task);
+                rtassert!(blocked_task_ptr & 0x1 == 0);
+                blocked_task_ptr
+            }
+            Shared(arc) => {
+                let blocked_task_ptr: uint = mem::transmute(box arc);
+                rtassert!(blocked_task_ptr & 0x1 == 0);
+                blocked_task_ptr | 0x1
+            }
+        }
+    }
+
+    /// Convert from an unsafe uint value. Useful for retrieving a pipe's state
+    /// flag.
+    #[inline]
+    pub unsafe fn cast_from_uint(blocked_task_ptr: uint) -> BlockedTask {
+        if blocked_task_ptr & 0x1 == 0 {
+            Owned(mem::transmute(blocked_task_ptr))
+        } else {
+            let ptr: Box<Arc<AtomicUint>> =
+                mem::transmute(blocked_task_ptr & !1);
+            Shared(*ptr)
+        }
+    }
+}
+
+impl Death {
+    pub fn new() -> Death {
+        Death { on_exit: None }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use prelude::*;
+    use task;
+    use rt::unwind;
+
+    #[test]
+    fn unwind() {
+        let result = task::try(move|| ());
+        rtdebug!("trying first assert");
+        assert!(result.is_ok());
+        let result = task::try(move|| -> () panic!());
+        rtdebug!("trying second assert");
+        assert!(result.is_err());
+    }
+
+    #[test]
+    fn rng() {
+        use rand::{StdRng, Rng};
+        let mut r = StdRng::new().ok().unwrap();
+        let _ = r.next_u32();
+    }
+
+    #[test]
+    fn comm_stream() {
+        let (tx, rx) = channel();
+        tx.send(10i);
+        assert!(rx.recv() == 10);
+    }
+
+    #[test]
+    fn comm_shared_chan() {
+        let (tx, rx) = channel();
+        tx.send(10i);
+        assert!(rx.recv() == 10);
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_begin_unwind() {
+        use rt::unwind::begin_unwind;
+        begin_unwind("cause", &(file!(), line!()))
+    }
+
+    #[test]
+    fn drop_new_task_ok() {
+        drop(Task::new(None, None));
+    }
+
+    // Task blocking tests
+
+    #[test]
+    fn block_and_wake() {
+        let task = box Task::new(None, None);
+        let task = BlockedTask::block(task).wake().unwrap();
+        task.drop();
+    }
+}
diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs
new file mode 100644
index 00000000000..eb15a7ba378
--- /dev/null
+++ b/src/libstd/rt/unwind.rs
@@ -0,0 +1,613 @@
+// Copyright 2013 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.
+
+//! Implementation of Rust stack unwinding
+//!
+//! For background on exception handling and stack unwinding please see
+//! "Exception Handling in LLVM" (llvm.org/docs/ExceptionHandling.html) and
+//! documents linked from it.
+//! These are also good reads:
+//!     http://theofilos.cs.columbia.edu/blog/2013/09/22/base_abi/
+//!     http://monoinfinito.wordpress.com/series/exception-handling-in-c/
+//!     http://www.airs.com/blog/index.php?s=exception+frames
+//!
+//! ## A brief summary
+//!
+//! Exception handling happens in two phases: a search phase and a cleanup phase.
+//!
+//! In both phases the unwinder walks stack frames from top to bottom using
+//! information from the stack frame unwind sections of the current process's
+//! modules ("module" here refers to an OS module, i.e. an executable or a
+//! dynamic library).
+//!
+//! For each stack frame, it invokes the associated "personality routine", whose
+//! address is also stored in the unwind info section.
+//!
+//! In the search phase, the job of a personality routine is to examine exception
+//! object being thrown, and to decide whether it should be caught at that stack
+//! frame.  Once the handler frame has been identified, cleanup phase begins.
+//!
+//! In the cleanup phase, personality routines invoke cleanup code associated
+//! with their stack frames (i.e. destructors).  Once stack has been unwound down
+//! to the handler frame level, unwinding stops and the last personality routine
+//! transfers control to its catch block.
+//!
+//! ## Frame unwind info registration
+//!
+//! Each module has its own frame unwind info section (usually ".eh_frame"), and
+//! unwinder needs to know about all of them in order for unwinding to be able to
+//! cross module boundaries.
+//!
+//! On some platforms, like Linux, this is achieved by dynamically enumerating
+//! currently loaded modules via the dl_iterate_phdr() API and finding all
+//! .eh_frame sections.
+//!
+//! Others, like Windows, require modules to actively register their unwind info
+//! sections by calling __register_frame_info() API at startup.  In the latter
+//! case it is essential that there is only one copy of the unwinder runtime in
+//! the process.  This is usually achieved by linking to the dynamic version of
+//! the unwind runtime.
+//!
+//! Currently Rust uses unwind runtime provided by libgcc.
+
+use prelude::*;
+
+use any::Any;
+use cell::Cell;
+use cmp;
+use failure;
+use fmt;
+use intrinsics;
+use libc::c_void;
+use mem;
+use sync::atomic;
+use sync::{Once, ONCE_INIT};
+
+use rt::libunwind as uw;
+
+struct Exception {
+    uwe: uw::_Unwind_Exception,
+    cause: Option<Box<Any + Send>>,
+}
+
+pub type Callback = fn(msg: &(Any + Send), file: &'static str, line: uint);
+
+// Variables used for invoking callbacks when a task starts to unwind.
+//
+// For more information, see below.
+const MAX_CALLBACKS: uint = 16;
+static CALLBACKS: [atomic::AtomicUint, ..MAX_CALLBACKS] =
+        [atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT,
+         atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT,
+         atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT,
+         atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT,
+         atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT,
+         atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT,
+         atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT,
+         atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT];
+static CALLBACK_CNT: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT;
+
+thread_local! { static PANICKING: Cell<bool> = Cell::new(false) }
+
+/// Invoke a closure, capturing the cause of panic if one occurs.
+///
+/// This function will return `None` if the closure did not panic, and will
+/// return `Some(cause)` if the closure panics. The `cause` returned is the
+/// object with which panic was originally invoked.
+///
+/// This function also is unsafe for a variety of reasons:
+///
+/// * This is not safe to call in a nested fashion. The unwinding
+///   interface for Rust is designed to have at most one try/catch block per
+///   task, not multiple. No runtime checking is currently performed to uphold
+///   this invariant, so this function is not safe. A nested try/catch block
+///   may result in corruption of the outer try/catch block's state, especially
+///   if this is used within a task itself.
+///
+/// * It is not sound to trigger unwinding while already unwinding. Rust tasks
+///   have runtime checks in place to ensure this invariant, but it is not
+///   guaranteed that a rust task is in place when invoking this function.
+///   Unwinding twice can lead to resource leaks where some destructors are not
+///   run.
+pub unsafe fn try<F: FnOnce()>(f: F) -> Result<(), Box<Any + Send>> {
+    let mut f = Some(f);
+
+    let prev = PANICKING.with(|s| s.get());
+    PANICKING.with(|s| s.set(false));
+    let ep = rust_try(try_fn::<F>, &mut f as *mut _ as *mut c_void);
+    PANICKING.with(|s| s.set(prev));
+    return if ep.is_null() {
+        Ok(())
+    } else {
+        let my_ep = ep as *mut Exception;
+        rtdebug!("caught {}", (*my_ep).uwe.exception_class);
+        let cause = (*my_ep).cause.take();
+        uw::_Unwind_DeleteException(ep);
+        Err(cause.unwrap())
+    };
+
+    extern fn try_fn<F: FnOnce()>(opt_closure: *mut c_void) {
+        let opt_closure = opt_closure as *mut Option<F>;
+        unsafe { (*opt_closure).take().unwrap()(); }
+    }
+
+    #[link(name = "rustrt_native", kind = "static")]
+    #[cfg(not(test))]
+    extern {}
+
+    extern {
+        // Rust's try-catch
+        // When f(...) returns normally, the return value is null.
+        // When f(...) throws, the return value is a pointer to the caught
+        // exception object.
+        fn rust_try(f: extern fn(*mut c_void),
+                    data: *mut c_void) -> *mut uw::_Unwind_Exception;
+    }
+}
+
+/// Test if the current thread is currently panicking.
+pub fn panicking() -> bool {
+    PANICKING.with(|s| s.get())
+}
+
+// An uninlined, unmangled function upon which to slap yer breakpoints
+#[inline(never)]
+#[no_mangle]
+fn rust_panic(cause: Box<Any + Send>) -> ! {
+    rtdebug!("begin_unwind()");
+
+    unsafe {
+        let exception = box Exception {
+            uwe: uw::_Unwind_Exception {
+                exception_class: rust_exception_class(),
+                exception_cleanup: exception_cleanup,
+                private: [0, ..uw::unwinder_private_data_size],
+            },
+            cause: Some(cause),
+        };
+        let error = uw::_Unwind_RaiseException(mem::transmute(exception));
+        rtabort!("Could not unwind stack, error = {}", error as int)
+    }
+
+    extern fn exception_cleanup(_unwind_code: uw::_Unwind_Reason_Code,
+                                exception: *mut uw::_Unwind_Exception) {
+        rtdebug!("exception_cleanup()");
+        unsafe {
+            let _: Box<Exception> = mem::transmute(exception);
+        }
+    }
+}
+
+// Rust's exception class identifier.  This is used by personality routines to
+// determine whether the exception was thrown by their own runtime.
+fn rust_exception_class() -> uw::_Unwind_Exception_Class {
+    // M O Z \0  R U S T -- vendor, language
+    0x4d4f5a_00_52555354
+}
+
+// We could implement our personality routine in pure Rust, however exception
+// info decoding is tedious.  More importantly, personality routines have to
+// handle various platform quirks, which are not fun to maintain.  For this
+// reason, we attempt to reuse personality routine of the C language:
+// __gcc_personality_v0.
+//
+// Since C does not support exception catching, __gcc_personality_v0 simply
+// always returns _URC_CONTINUE_UNWIND in search phase, and always returns
+// _URC_INSTALL_CONTEXT (i.e. "invoke cleanup code") in cleanup phase.
+//
+// This is pretty close to Rust's exception handling approach, except that Rust
+// does have a single "catch-all" handler at the bottom of each task's stack.
+// So we have two versions of the personality routine:
+// - rust_eh_personality, used by all cleanup landing pads, which never catches,
+//   so the behavior of __gcc_personality_v0 is perfectly adequate there, and
+// - rust_eh_personality_catch, used only by rust_try(), which always catches.
+//
+// Note, however, that for implementation simplicity, rust_eh_personality_catch
+// lacks code to install a landing pad, so in order to obtain exception object
+// pointer (which it needs to return upstream), rust_try() employs another trick:
+// it calls into the nested rust_try_inner(), whose landing pad does not resume
+// unwinds.  Instead, it extracts the exception pointer and performs a "normal"
+// return.
+//
+// See also: rt/rust_try.ll
+
+#[cfg(all(not(target_arch = "arm"),
+          not(all(windows, target_arch = "x86_64")),
+          not(test)))]
+#[doc(hidden)]
+pub mod eabi {
+    use rt::libunwind as uw;
+    use libc::c_int;
+
+    extern "C" {
+        fn __gcc_personality_v0(version: c_int,
+                                actions: uw::_Unwind_Action,
+                                exception_class: uw::_Unwind_Exception_Class,
+                                ue_header: *mut uw::_Unwind_Exception,
+                                context: *mut uw::_Unwind_Context)
+            -> uw::_Unwind_Reason_Code;
+    }
+
+    #[lang="eh_personality"]
+    #[no_mangle] // referenced from rust_try.ll
+    extern fn rust_eh_personality(
+        version: c_int,
+        actions: uw::_Unwind_Action,
+        exception_class: uw::_Unwind_Exception_Class,
+        ue_header: *mut uw::_Unwind_Exception,
+        context: *mut uw::_Unwind_Context
+    ) -> uw::_Unwind_Reason_Code
+    {
+        unsafe {
+            __gcc_personality_v0(version, actions, exception_class, ue_header,
+                                 context)
+        }
+    }
+
+    #[no_mangle] // referenced from rust_try.ll
+    pub extern "C" fn rust_eh_personality_catch(
+        _version: c_int,
+        actions: uw::_Unwind_Action,
+        _exception_class: uw::_Unwind_Exception_Class,
+        _ue_header: *mut uw::_Unwind_Exception,
+        _context: *mut uw::_Unwind_Context
+    ) -> uw::_Unwind_Reason_Code
+    {
+
+        if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
+            uw::_URC_HANDLER_FOUND // catch!
+        }
+        else { // cleanup phase
+            uw::_URC_INSTALL_CONTEXT
+        }
+    }
+}
+
+// iOS on armv7 is using SjLj exceptions and therefore requires to use
+// a specialized personality routine: __gcc_personality_sj0
+
+#[cfg(all(target_os = "ios", target_arch = "arm", not(test)))]
+#[doc(hidden)]
+pub mod eabi {
+    use rt::libunwind as uw;
+    use libc::c_int;
+
+    extern "C" {
+        fn __gcc_personality_sj0(version: c_int,
+                                actions: uw::_Unwind_Action,
+                                exception_class: uw::_Unwind_Exception_Class,
+                                ue_header: *mut uw::_Unwind_Exception,
+                                context: *mut uw::_Unwind_Context)
+            -> uw::_Unwind_Reason_Code;
+    }
+
+    #[lang="eh_personality"]
+    #[no_mangle] // referenced from rust_try.ll
+    pub extern "C" fn rust_eh_personality(
+        version: c_int,
+        actions: uw::_Unwind_Action,
+        exception_class: uw::_Unwind_Exception_Class,
+        ue_header: *mut uw::_Unwind_Exception,
+        context: *mut uw::_Unwind_Context
+    ) -> uw::_Unwind_Reason_Code
+    {
+        unsafe {
+            __gcc_personality_sj0(version, actions, exception_class, ue_header,
+                                  context)
+        }
+    }
+
+    #[no_mangle] // referenced from rust_try.ll
+    pub extern "C" fn rust_eh_personality_catch(
+        _version: c_int,
+        actions: uw::_Unwind_Action,
+        _exception_class: uw::_Unwind_Exception_Class,
+        _ue_header: *mut uw::_Unwind_Exception,
+        _context: *mut uw::_Unwind_Context
+    ) -> uw::_Unwind_Reason_Code
+    {
+        if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
+            uw::_URC_HANDLER_FOUND // catch!
+        }
+        else { // cleanup phase
+            unsafe {
+                __gcc_personality_sj0(_version, actions, _exception_class, _ue_header,
+                                      _context)
+            }
+        }
+    }
+}
+
+
+// ARM EHABI uses a slightly different personality routine signature,
+// but otherwise works the same.
+#[cfg(all(target_arch = "arm", not(target_os = "ios"), not(test)))]
+#[doc(hidden)]
+pub mod eabi {
+    use rt::libunwind as uw;
+    use libc::c_int;
+
+    extern "C" {
+        fn __gcc_personality_v0(state: uw::_Unwind_State,
+                                ue_header: *mut uw::_Unwind_Exception,
+                                context: *mut uw::_Unwind_Context)
+            -> uw::_Unwind_Reason_Code;
+    }
+
+    #[lang="eh_personality"]
+    #[no_mangle] // referenced from rust_try.ll
+    extern "C" fn rust_eh_personality(
+        state: uw::_Unwind_State,
+        ue_header: *mut uw::_Unwind_Exception,
+        context: *mut uw::_Unwind_Context
+    ) -> uw::_Unwind_Reason_Code
+    {
+        unsafe {
+            __gcc_personality_v0(state, ue_header, context)
+        }
+    }
+
+    #[no_mangle] // referenced from rust_try.ll
+    pub extern "C" fn rust_eh_personality_catch(
+        state: uw::_Unwind_State,
+        _ue_header: *mut uw::_Unwind_Exception,
+        _context: *mut uw::_Unwind_Context
+    ) -> uw::_Unwind_Reason_Code
+    {
+        if (state as c_int & uw::_US_ACTION_MASK as c_int)
+                           == uw::_US_VIRTUAL_UNWIND_FRAME as c_int { // search phase
+            uw::_URC_HANDLER_FOUND // catch!
+        }
+        else { // cleanup phase
+            uw::_URC_INSTALL_CONTEXT
+        }
+    }
+}
+
+// Win64 SEH (see http://msdn.microsoft.com/en-us/library/1eyas8tf.aspx)
+//
+// This looks a bit convoluted because rather than implementing a native SEH handler,
+// GCC reuses the same personality routine as for the other architectures by wrapping it
+// with an "API translator" layer (_GCC_specific_handler).
+
+#[cfg(all(windows, target_arch = "x86_64", not(test)))]
+#[doc(hidden)]
+#[allow(non_camel_case_types, non_snake_case)]
+pub mod eabi {
+    pub use self::EXCEPTION_DISPOSITION::*;
+    use rt::libunwind as uw;
+    use libc::{c_void, c_int};
+
+    #[repr(C)]
+    #[allow(missing_copy_implementations)]
+    pub struct EXCEPTION_RECORD;
+    #[repr(C)]
+    #[allow(missing_copy_implementations)]
+    pub struct CONTEXT;
+    #[repr(C)]
+    #[allow(missing_copy_implementations)]
+    pub struct DISPATCHER_CONTEXT;
+
+    #[repr(C)]
+    #[deriving(Copy)]
+    pub enum EXCEPTION_DISPOSITION {
+        ExceptionContinueExecution,
+        ExceptionContinueSearch,
+        ExceptionNestedException,
+        ExceptionCollidedUnwind
+    }
+
+    type _Unwind_Personality_Fn =
+        extern "C" fn(
+            version: c_int,
+            actions: uw::_Unwind_Action,
+            exception_class: uw::_Unwind_Exception_Class,
+            ue_header: *mut uw::_Unwind_Exception,
+            context: *mut uw::_Unwind_Context
+        ) -> uw::_Unwind_Reason_Code;
+
+    extern "C" {
+        fn __gcc_personality_seh0(
+            exceptionRecord: *mut EXCEPTION_RECORD,
+            establisherFrame: *mut c_void,
+            contextRecord: *mut CONTEXT,
+            dispatcherContext: *mut DISPATCHER_CONTEXT
+        ) -> EXCEPTION_DISPOSITION;
+
+        fn _GCC_specific_handler(
+            exceptionRecord: *mut EXCEPTION_RECORD,
+            establisherFrame: *mut c_void,
+            contextRecord: *mut CONTEXT,
+            dispatcherContext: *mut DISPATCHER_CONTEXT,
+            personality: _Unwind_Personality_Fn
+        ) -> EXCEPTION_DISPOSITION;
+    }
+
+    #[lang="eh_personality"]
+    #[no_mangle] // referenced from rust_try.ll
+    extern "C" fn rust_eh_personality(
+        exceptionRecord: *mut EXCEPTION_RECORD,
+        establisherFrame: *mut c_void,
+        contextRecord: *mut CONTEXT,
+        dispatcherContext: *mut DISPATCHER_CONTEXT
+    ) -> EXCEPTION_DISPOSITION
+    {
+        unsafe {
+            __gcc_personality_seh0(exceptionRecord, establisherFrame,
+                                   contextRecord, dispatcherContext)
+        }
+    }
+
+    #[no_mangle] // referenced from rust_try.ll
+    pub extern "C" fn rust_eh_personality_catch(
+        exceptionRecord: *mut EXCEPTION_RECORD,
+        establisherFrame: *mut c_void,
+        contextRecord: *mut CONTEXT,
+        dispatcherContext: *mut DISPATCHER_CONTEXT
+    ) -> EXCEPTION_DISPOSITION
+    {
+        extern "C" fn inner(
+                _version: c_int,
+                actions: uw::_Unwind_Action,
+                _exception_class: uw::_Unwind_Exception_Class,
+                _ue_header: *mut uw::_Unwind_Exception,
+                _context: *mut uw::_Unwind_Context
+            ) -> uw::_Unwind_Reason_Code
+        {
+            if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
+                uw::_URC_HANDLER_FOUND // catch!
+            }
+            else { // cleanup phase
+                uw::_URC_INSTALL_CONTEXT
+            }
+        }
+
+        unsafe {
+            _GCC_specific_handler(exceptionRecord, establisherFrame,
+                                  contextRecord, dispatcherContext,
+                                  inner)
+        }
+    }
+}
+
+// Entry point of panic from the libcore crate
+#[cfg(not(test))]
+#[lang = "panic_fmt"]
+pub extern fn rust_begin_unwind(msg: &fmt::Arguments,
+                                file: &'static str, line: uint) -> ! {
+    begin_unwind_fmt(msg, &(file, line))
+}
+
+/// The entry point for unwinding with a formatted message.
+///
+/// This is designed to reduce the amount of code required at the call
+/// site as much as possible (so that `panic!()` has as low an impact
+/// on (e.g.) the inlining of other functions as possible), by moving
+/// the actual formatting into this shared place.
+#[inline(never)] #[cold]
+pub fn begin_unwind_fmt(msg: &fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
+    use fmt::FormatWriter;
+
+    // We do two allocations here, unfortunately. But (a) they're
+    // required with the current scheme, and (b) we don't handle
+    // panic + OOM properly anyway (see comment in begin_unwind
+    // below).
+
+    struct VecWriter<'a> { v: &'a mut Vec<u8> }
+
+    impl<'a> fmt::FormatWriter for VecWriter<'a> {
+        fn write(&mut self, buf: &[u8]) -> fmt::Result {
+            self.v.push_all(buf);
+            Ok(())
+        }
+    }
+
+    let mut v = Vec::new();
+    let _ = write!(&mut VecWriter { v: &mut v }, "{}", msg);
+
+    let msg = box String::from_utf8_lossy(v.as_slice()).into_owned();
+    begin_unwind_inner(msg, file_line)
+}
+
+/// This is the entry point of unwinding for panic!() and assert!().
+#[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible
+pub fn begin_unwind<M: Any + Send>(msg: M, file_line: &(&'static str, uint)) -> ! {
+    // Note that this should be the only allocation performed in this code path.
+    // Currently this means that panic!() on OOM will invoke this code path,
+    // but then again we're not really ready for panic on OOM anyway. If
+    // we do start doing this, then we should propagate this allocation to
+    // be performed in the parent of this task instead of the task that's
+    // panicking.
+
+    // see below for why we do the `Any` coercion here.
+    begin_unwind_inner(box msg, file_line)
+}
+
+/// The core of the unwinding.
+///
+/// This is non-generic to avoid instantiation bloat in other crates
+/// (which makes compilation of small crates noticeably slower). (Note:
+/// we need the `Any` object anyway, we're not just creating it to
+/// avoid being generic.)
+///
+/// Doing this split took the LLVM IR line counts of `fn main() { panic!()
+/// }` from ~1900/3700 (-O/no opts) to 180/590.
+#[inline(never)] #[cold] // this is the slow path, please never inline this
+fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) -> ! {
+    // Make sure the default failure handler is registered before we look at the
+    // callbacks.
+    static INIT: Once = ONCE_INIT;
+    INIT.doit(|| unsafe { register(failure::on_fail); });
+
+    // First, invoke call the user-defined callbacks triggered on task panic.
+    //
+    // By the time that we see a callback has been registered (by reading
+    // MAX_CALLBACKS), the actual callback itself may have not been stored yet,
+    // so we just chalk it up to a race condition and move on to the next
+    // callback. Additionally, CALLBACK_CNT may briefly be higher than
+    // MAX_CALLBACKS, so we're sure to clamp it as necessary.
+    let callbacks = {
+        let amt = CALLBACK_CNT.load(atomic::SeqCst);
+        CALLBACKS[..cmp::min(amt, MAX_CALLBACKS)]
+    };
+    for cb in callbacks.iter() {
+        match cb.load(atomic::SeqCst) {
+            0 => {}
+            n => {
+                let f: Callback = unsafe { mem::transmute(n) };
+                let (file, line) = *file_line;
+                f(&*msg, file, line);
+            }
+        }
+    };
+
+    // Now that we've run all the necessary unwind callbacks, we actually
+    // perform the unwinding.
+    if panicking() {
+        // If a thread panics while it's already unwinding then we
+        // have limited options. Currently our preference is to
+        // just abort. In the future we may consider resuming
+        // unwinding or otherwise exiting the task cleanly.
+        rterrln!("thread panicked while panicking. aborting.");
+        unsafe { intrinsics::abort() }
+    }
+    PANICKING.with(|s| s.set(true));
+    rust_panic(msg);
+}
+
+/// Register a callback to be invoked when a task unwinds.
+///
+/// This is an unsafe and experimental API which allows for an arbitrary
+/// callback to be invoked when a task panics. This callback is invoked on both
+/// the initial unwinding and a double unwinding if one occurs. Additionally,
+/// the local `Task` will be in place for the duration of the callback, and
+/// the callback must ensure that it remains in place once the callback returns.
+///
+/// Only a limited number of callbacks can be registered, and this function
+/// returns whether the callback was successfully registered or not. It is not
+/// currently possible to unregister a callback once it has been registered.
+#[experimental]
+pub unsafe fn register(f: Callback) -> bool {
+    match CALLBACK_CNT.fetch_add(1, atomic::SeqCst) {
+        // The invocation code has knowledge of this window where the count has
+        // been incremented, but the callback has not been stored. We're
+        // guaranteed that the slot we're storing into is 0.
+        n if n < MAX_CALLBACKS => {
+            let prev = CALLBACKS[n].swap(mem::transmute(f), atomic::SeqCst);
+            rtassert!(prev == 0);
+            true
+        }
+        // If we accidentally bumped the count too high, pull it back.
+        _ => {
+            CALLBACK_CNT.store(MAX_CALLBACKS, atomic::SeqCst);
+            false
+        }
+    }
+}
diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs
index 92657d1b59b..d8cd8455deb 100644
--- a/src/libstd/rt/util.rs
+++ b/src/libstd/rt/util.rs
@@ -7,11 +7,19 @@
 // <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.
+//
+// ignore-lexer-test FIXME #15677
+
+use prelude::*;
 
+use cmp;
+use fmt;
+use intrinsics;
 use libc::uintptr_t;
-use option::{Some, None, Option};
+use libc;
 use os;
-use str::{FromStr, from_str, Str};
+use slice;
+use str;
 use sync::atomic;
 
 /// Dynamically inquire about whether we're running under V.
@@ -44,7 +52,7 @@ pub fn min_stack() -> uint {
         0 => {}
         n => return n - 1,
     }
-    let amt = os::getenv("RUST_MIN_STACK").and_then(|s| from_str(s.as_slice()));
+    let amt = os::getenv("RUST_MIN_STACK").and_then(|s| s.parse());
     let amt = amt.unwrap_or(2 * 1024 * 1024);
     // 0 is our sentinel value, so ensure that we'll never see 0 after
     // initialization has run
@@ -57,7 +65,7 @@ pub fn min_stack() -> uint {
 pub fn default_sched_threads() -> uint {
     match os::getenv("RUST_THREADS") {
         Some(nstr) => {
-            let opt_n: Option<uint> = FromStr::from_str(nstr.as_slice());
+            let opt_n: Option<uint> = nstr.parse();
             match opt_n {
                 Some(n) if n > 0 => n,
                 _ => panic!("`RUST_THREADS` is `{}`, should be a positive integer", nstr)
@@ -72,3 +80,130 @@ pub fn default_sched_threads() -> uint {
         }
     }
 }
+
+// Indicates whether we should perform expensive sanity checks, including rtassert!
+//
+// FIXME: Once the runtime matures remove the `true` below to turn off rtassert,
+//        etc.
+pub const ENFORCE_SANITY: bool = true || !cfg!(rtopt) || cfg!(rtdebug) ||
+                                  cfg!(rtassert);
+
+#[allow(missing_copy_implementations)]
+pub struct Stdio(libc::c_int);
+
+#[allow(non_upper_case_globals)]
+pub const Stdout: Stdio = Stdio(libc::STDOUT_FILENO);
+#[allow(non_upper_case_globals)]
+pub const Stderr: Stdio = Stdio(libc::STDERR_FILENO);
+
+impl fmt::FormatWriter for Stdio {
+    fn write(&mut self, data: &[u8]) -> fmt::Result {
+        #[cfg(unix)]
+        type WriteLen = libc::size_t;
+        #[cfg(windows)]
+        type WriteLen = libc::c_uint;
+        unsafe {
+            let Stdio(fd) = *self;
+            libc::write(fd,
+                        data.as_ptr() as *const libc::c_void,
+                        data.len() as WriteLen);
+        }
+        Ok(()) // yes, we're lying
+    }
+}
+
+pub fn dumb_print(args: &fmt::Arguments) {
+    let mut w = Stderr;
+    let _ = write!(&mut w, "{}", args);
+}
+
+pub fn abort(args: &fmt::Arguments) -> ! {
+    use fmt::FormatWriter;
+
+    struct BufWriter<'a> {
+        buf: &'a mut [u8],
+        pos: uint,
+    }
+    impl<'a> FormatWriter for BufWriter<'a> {
+        fn write(&mut self, bytes: &[u8]) -> fmt::Result {
+            let left = self.buf[mut self.pos..];
+            let to_write = bytes[..cmp::min(bytes.len(), left.len())];
+            slice::bytes::copy_memory(left, to_write);
+            self.pos += to_write.len();
+            Ok(())
+        }
+    }
+
+    // Convert the arguments into a stack-allocated string
+    let mut msg = [0u8, ..512];
+    let mut w = BufWriter { buf: &mut msg, pos: 0 };
+    let _ = write!(&mut w, "{}", args);
+    let msg = str::from_utf8(w.buf[mut ..w.pos]).unwrap_or("aborted");
+    let msg = if msg.is_empty() {"aborted"} else {msg};
+
+    // Give some context to the message
+    let hash = msg.bytes().fold(0, |accum, val| accum + (val as uint) );
+    let quote = match hash % 10 {
+        0 => "
+It was from the artists and poets that the pertinent answers came, and I
+know that panic would have broken loose had they been able to compare notes.
+As it was, lacking their original letters, I half suspected the compiler of
+having asked leading questions, or of having edited the correspondence in
+corroboration of what he had latently resolved to see.",
+        1 => "
+There are not many persons who know what wonders are opened to them in the
+stories and visions of their youth; for when as children we listen and dream,
+we think but half-formed thoughts, and when as men we try to remember, we are
+dulled and prosaic with the poison of life. But some of us awake in the night
+with strange phantasms of enchanted hills and gardens, of fountains that sing
+in the sun, of golden cliffs overhanging murmuring seas, of plains that stretch
+down to sleeping cities of bronze and stone, and of shadowy companies of heroes
+that ride caparisoned white horses along the edges of thick forests; and then
+we know that we have looked back through the ivory gates into that world of
+wonder which was ours before we were wise and unhappy.",
+        2 => "
+Instead of the poems I had hoped for, there came only a shuddering blackness
+and ineffable loneliness; and I saw at last a fearful truth which no one had
+ever dared to breathe before — the unwhisperable secret of secrets — The fact
+that this city of stone and stridor is not a sentient perpetuation of Old New
+York as London is of Old London and Paris of Old Paris, but that it is in fact
+quite dead, its sprawling body imperfectly embalmed and infested with queer
+animate things which have nothing to do with it as it was in life.",
+        3 => "
+The ocean ate the last of the land and poured into the smoking gulf, thereby
+giving up all it had ever conquered. From the new-flooded lands it flowed
+again, uncovering death and decay; and from its ancient and immemorial bed it
+trickled loathsomely, uncovering nighted secrets of the years when Time was
+young and the gods unborn. Above the waves rose weedy remembered spires. The
+moon laid pale lilies of light on dead London, and Paris stood up from its damp
+grave to be sanctified with star-dust. Then rose spires and monoliths that were
+weedy but not remembered; terrible spires and monoliths of lands that men never
+knew were lands...",
+        4 => "
+There was a night when winds from unknown spaces whirled us irresistibly into
+limitless vacuum beyond all thought and entity. Perceptions of the most
+maddeningly untransmissible sort thronged upon us; perceptions of infinity
+which at the time convulsed us with joy, yet which are now partly lost to my
+memory and partly incapable of presentation to others.",
+        _ => "You've met with a terrible fate, haven't you?"
+    };
+    rterrln!("{}", "");
+    rterrln!("{}", quote);
+    rterrln!("{}", "");
+    rterrln!("fatal runtime error: {}", msg);
+    unsafe { intrinsics::abort(); }
+}
+
+pub unsafe fn report_overflow() {
+    use thread::Thread;
+
+    // See the message below for why this is not emitted to the
+    // ^ Where did the message below go?
+    // task's logger. This has the additional conundrum of the
+    // logger may not be initialized just yet, meaning that an FFI
+    // call would happen to initialized it (calling out to libuv),
+    // and the FFI call needs 2MB of stack when we just ran out.
+
+    rterrln!("\nthread '{}' has overflowed its stack",
+             Thread::current().name().unwrap_or("<unknown>"));
+}
diff --git a/src/libstd/rtdeps.rs b/src/libstd/rtdeps.rs
index 35a87137115..862808a9e3d 100644
--- a/src/libstd/rtdeps.rs
+++ b/src/libstd/rtdeps.rs
@@ -22,7 +22,7 @@ extern {}
 // LLVM implements the `frem` instruction as a call to `fmod`, which lives in
 // libm. Hence, we must explicitly link to it.
 //
-// On Linux, librt and libdl are indirect dependencies via rustrt,
+// On Linux, librt and libdl are indirect dependencies via std,
 // and binutils 2.22+ won't add them automatically
 #[cfg(target_os = "linux")]
 #[link(name = "dl")]
diff --git a/src/libstd/sync/atomic.rs b/src/libstd/sync/atomic.rs
new file mode 100644
index 00000000000..26778ef70b3
--- /dev/null
+++ b/src/libstd/sync/atomic.rs
@@ -0,0 +1,225 @@
+// Copyright 2012-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.
+
+//! Atomic types
+//!
+//! Atomic types provide primitive shared-memory communication between
+//! threads, and are the building blocks of other concurrent
+//! types.
+//!
+//! This module defines atomic versions of a select number of primitive
+//! types, including `AtomicBool`, `AtomicInt`, `AtomicUint`, and `AtomicOption`.
+//! Atomic types present operations that, when used correctly, synchronize
+//! updates between threads.
+//!
+//! Each method takes an `Ordering` which represents the strength of
+//! the memory barrier for that operation. These orderings are the
+//! same as [C++11 atomic orderings][1].
+//!
+//! [1]: http://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync
+//!
+//! Atomic variables are safe to share between threads (they implement `Sync`)
+//! but they do not themselves provide the mechanism for sharing. The most
+//! common way to share an atomic variable is to put it into an `Arc` (an
+//! atomically-reference-counted shared pointer).
+//!
+//! Most atomic types may be stored in static variables, initialized using
+//! the provided static initializers like `INIT_ATOMIC_BOOL`. Atomic statics
+//! are often used for lazy global initialization.
+//!
+//!
+//! # Examples
+//!
+//! A simple spinlock:
+//!
+//! ```
+//! use std::sync::Arc;
+//! use std::sync::atomic::{AtomicUint, SeqCst};
+//! use std::thread::Thread;
+//!
+//! fn main() {
+//!     let spinlock = Arc::new(AtomicUint::new(1));
+//!
+//!     let spinlock_clone = spinlock.clone();
+//!     Thread::spawn(move|| {
+//!         spinlock_clone.store(0, SeqCst);
+//!     }).detach();
+//!
+//!     // Wait for the other task to release the lock
+//!     while spinlock.load(SeqCst) != 0 {}
+//! }
+//! ```
+//!
+//! Transferring a heap object with `AtomicOption`:
+//!
+//! ```
+//! use std::sync::Arc;
+//! use std::sync::atomic::{AtomicOption, SeqCst};
+//! use std::thread::Thread;
+//!
+//! fn main() {
+//!     struct BigObject;
+//!
+//!     let shared_big_object = Arc::new(AtomicOption::empty());
+//!
+//!     let shared_big_object_clone = shared_big_object.clone();
+//!     Thread::spawn(move|| {
+//!         let unwrapped_big_object = shared_big_object_clone.take(SeqCst);
+//!         if unwrapped_big_object.is_some() {
+//!             println!("got a big object from another task");
+//!         } else {
+//!             println!("other task hasn't sent big object yet");
+//!         }
+//!     }).detach();
+//!
+//!     shared_big_object.swap(box BigObject, SeqCst);
+//! }
+//! ```
+//!
+//! Keep a global count of live tasks:
+//!
+//! ```
+//! use std::sync::atomic::{AtomicUint, SeqCst, INIT_ATOMIC_UINT};
+//!
+//! static GLOBAL_TASK_COUNT: AtomicUint = INIT_ATOMIC_UINT;
+//!
+//! let old_task_count = GLOBAL_TASK_COUNT.fetch_add(1, SeqCst);
+//! println!("live tasks: {}", old_task_count + 1);
+//! ```
+
+#![allow(deprecated)]
+
+use alloc::boxed::Box;
+use core::mem;
+use core::prelude::{Send, Drop, None, Option, Some};
+
+pub use core::atomic::{AtomicBool, AtomicInt, AtomicUint, AtomicPtr};
+pub use core::atomic::{Ordering, Relaxed, Release, Acquire, AcqRel, SeqCst};
+pub use core::atomic::{INIT_ATOMIC_BOOL, INIT_ATOMIC_INT, INIT_ATOMIC_UINT};
+pub use core::atomic::fence;
+
+/// An atomic, nullable unique pointer
+///
+/// This can be used as the concurrency primitive for operations that transfer
+/// owned heap objects across tasks.
+#[unsafe_no_drop_flag]
+#[deprecated = "no longer used; will eventually be replaced by a higher-level\
+                concept like MVar"]
+pub struct AtomicOption<T> {
+    p: AtomicUint,
+}
+
+impl<T: Send> AtomicOption<T> {
+    /// Create a new `AtomicOption`
+    pub fn new(p: Box<T>) -> AtomicOption<T> {
+        unsafe { AtomicOption { p: AtomicUint::new(mem::transmute(p)) } }
+    }
+
+    /// Create a new `AtomicOption` that doesn't contain a value
+    pub fn empty() -> AtomicOption<T> { AtomicOption { p: AtomicUint::new(0) } }
+
+    /// Store a value, returning the old value
+    #[inline]
+    pub fn swap(&self, val: Box<T>, order: Ordering) -> Option<Box<T>> {
+        let val = unsafe { mem::transmute(val) };
+
+        match self.p.swap(val, order) {
+            0 => None,
+            n => Some(unsafe { mem::transmute(n) }),
+        }
+    }
+
+    /// Remove the value, leaving the `AtomicOption` empty.
+    #[inline]
+    pub fn take(&self, order: Ordering) -> Option<Box<T>> {
+        unsafe { self.swap(mem::transmute(0u), order) }
+    }
+
+    /// Replace an empty value with a non-empty value.
+    ///
+    /// Succeeds if the option is `None` and returns `None` if so. If
+    /// the option was already `Some`, returns `Some` of the rejected
+    /// value.
+    #[inline]
+    pub fn fill(&self, val: Box<T>, order: Ordering) -> Option<Box<T>> {
+        unsafe {
+            let val = mem::transmute(val);
+            let expected = mem::transmute(0u);
+            let oldval = self.p.compare_and_swap(expected, val, order);
+            if oldval == expected {
+                None
+            } else {
+                Some(mem::transmute(val))
+            }
+        }
+    }
+
+    /// Returns `true` if the `AtomicOption` is empty.
+    ///
+    /// Be careful: The caller must have some external method of ensuring the
+    /// result does not get invalidated by another task after this returns.
+    #[inline]
+    pub fn is_empty(&self, order: Ordering) -> bool {
+        self.p.load(order) as uint == 0
+    }
+}
+
+#[unsafe_destructor]
+impl<T: Send> Drop for AtomicOption<T> {
+    fn drop(&mut self) {
+        let _ = self.take(SeqCst);
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use prelude::*;
+    use super::*;
+
+    #[test]
+    fn option_empty() {
+        let option: AtomicOption<()> = AtomicOption::empty();
+        assert!(option.is_empty(SeqCst));
+    }
+
+    #[test]
+    fn option_swap() {
+        let p = AtomicOption::new(box 1i);
+        let a = box 2i;
+
+        let b = p.swap(a, SeqCst);
+
+        assert!(b == Some(box 1));
+        assert!(p.take(SeqCst) == Some(box 2));
+    }
+
+    #[test]
+    fn option_take() {
+        let p = AtomicOption::new(box 1i);
+
+        assert!(p.take(SeqCst) == Some(box 1));
+        assert!(p.take(SeqCst) == None);
+
+        let p2 = box 2i;
+        p.swap(p2, SeqCst);
+
+        assert!(p.take(SeqCst) == Some(box 2));
+    }
+
+    #[test]
+    fn option_fill() {
+        let p = AtomicOption::new(box 1i);
+        assert!(p.fill(box 2i, SeqCst).is_some()); // should fail; shouldn't leak!
+        assert!(p.take(SeqCst) == Some(box 1));
+
+        assert!(p.fill(box 2i, SeqCst).is_none()); // shouldn't fail
+        assert!(p.take(SeqCst) == Some(box 2));
+    }
+}
diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs
new file mode 100644
index 00000000000..6573d9273ce
--- /dev/null
+++ b/src/libstd/sync/barrier.rs
@@ -0,0 +1,117 @@
+// 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.
+
+use sync::{Mutex, Condvar};
+
+/// A barrier enables multiple tasks to synchronize the beginning
+/// of some computation.
+///
+/// ```rust
+/// use std::sync::{Arc, Barrier};
+/// use std::thread::Thread;
+///
+/// let barrier = Arc::new(Barrier::new(10));
+/// for _ in range(0u, 10) {
+///     let c = barrier.clone();
+///     // The same messages will be printed together.
+///     // You will NOT see any interleaving.
+///     Thread::spawn(move|| {
+///         println!("before wait");
+///         c.wait();
+///         println!("after wait");
+///     }).detach();
+/// }
+/// ```
+pub struct Barrier {
+    lock: Mutex<BarrierState>,
+    cvar: Condvar,
+    num_threads: uint,
+}
+
+// The inner state of a double barrier
+struct BarrierState {
+    count: uint,
+    generation_id: uint,
+}
+
+impl Barrier {
+    /// Create a new barrier that can block a given number of threads.
+    ///
+    /// A barrier will block `n`-1 threads which call `wait` and then wake up
+    /// all threads at once when the `n`th thread calls `wait`.
+    pub fn new(n: uint) -> Barrier {
+        Barrier {
+            lock: Mutex::new(BarrierState {
+                count: 0,
+                generation_id: 0,
+            }),
+            cvar: Condvar::new(),
+            num_threads: n,
+        }
+    }
+
+    /// Block the current thread until all threads has rendezvoused here.
+    ///
+    /// Barriers are re-usable after all threads have rendezvoused once, and can
+    /// be used continuously.
+    pub fn wait(&self) {
+        let mut lock = self.lock.lock();
+        let local_gen = lock.generation_id;
+        lock.count += 1;
+        if lock.count < self.num_threads {
+            // We need a while loop to guard against spurious wakeups.
+            // http://en.wikipedia.org/wiki/Spurious_wakeup
+            while local_gen == lock.generation_id &&
+                  lock.count < self.num_threads {
+                self.cvar.wait(&lock);
+            }
+        } else {
+            lock.count = 0;
+            lock.generation_id += 1;
+            self.cvar.notify_all();
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use prelude::*;
+
+    use sync::{Arc, Barrier};
+    use comm::Empty;
+
+    #[test]
+    fn test_barrier() {
+        let barrier = Arc::new(Barrier::new(10));
+        let (tx, rx) = channel();
+
+        for _ in range(0u, 9) {
+            let c = barrier.clone();
+            let tx = tx.clone();
+            spawn(move|| {
+                c.wait();
+                tx.send(true);
+            });
+        }
+
+        // At this point, all spawned tasks should be blocked,
+        // so we shouldn't get anything from the port
+        assert!(match rx.try_recv() {
+            Err(Empty) => true,
+            _ => false,
+        });
+
+        barrier.wait();
+        // Now, the barrier is cleared and we should get data.
+        for _ in range(0u, 9) {
+            rx.recv();
+        }
+    }
+}
diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs
new file mode 100644
index 00000000000..be27c06b83c
--- /dev/null
+++ b/src/libstd/sync/condvar.rs
@@ -0,0 +1,365 @@
+// 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.
+
+use prelude::*;
+
+use sync::atomic::{mod, AtomicUint};
+use sync::{mutex, StaticMutexGuard};
+use sys_common::condvar as sys;
+use sys_common::mutex as sys_mutex;
+use time::Duration;
+
+/// A Condition Variable
+///
+/// Condition variables represent the ability to block a thread such that it
+/// consumes no CPU time while waiting for an event to occur. Condition
+/// variables are typically associated with a boolean predicate (a condition)
+/// and a mutex. The predicate is always verified inside of the mutex before
+/// determining that thread must block.
+///
+/// Functions in this module will block the current **thread** of execution and
+/// are bindings to system-provided condition variables where possible. Note
+/// that this module places one additional restriction over the system condition
+/// variables: each condvar can be used with precisely one mutex at runtime. Any
+/// attempt to use multiple mutexes on the same condition variable will result
+/// in a runtime panic. If this is not desired, then the unsafe primitives in
+/// `sys` do not have this restriction but may result in undefined behavior.
+///
+/// # Example
+///
+/// ```
+/// use std::sync::{Arc, Mutex, Condvar};
+/// use std::thread::Thread;
+///
+/// let pair = Arc::new((Mutex::new(false), Condvar::new()));
+/// let pair2 = pair.clone();
+///
+/// // Inside of our lock, spawn a new thread, and then wait for it to start
+/// Thread::spawn(move|| {
+///     let &(ref lock, ref cvar) = &*pair2;
+///     let mut started = lock.lock();
+///     *started = true;
+///     cvar.notify_one();
+/// }).detach();
+///
+/// // wait for the thread to start up
+/// let &(ref lock, ref cvar) = &*pair;
+/// let started = lock.lock();
+/// while !*started {
+///     cvar.wait(&started);
+/// }
+/// ```
+pub struct Condvar { inner: Box<StaticCondvar> }
+
+/// Statically allocated condition variables.
+///
+/// This structure is identical to `Condvar` except that it is suitable for use
+/// in static initializers for other structures.
+///
+/// # Example
+///
+/// ```
+/// use std::sync::{StaticCondvar, CONDVAR_INIT};
+///
+/// static CVAR: StaticCondvar = CONDVAR_INIT;
+/// ```
+pub struct StaticCondvar {
+    inner: sys::Condvar,
+    mutex: AtomicUint,
+}
+
+/// Constant initializer for a statically allocated condition variable.
+pub const CONDVAR_INIT: StaticCondvar = StaticCondvar {
+    inner: sys::CONDVAR_INIT,
+    mutex: atomic::INIT_ATOMIC_UINT,
+};
+
+/// A trait for vaules which can be passed to the waiting methods of condition
+/// variables. This is implemented by the mutex guards in this module.
+///
+/// Note that this trait should likely not be implemented manually unless you
+/// really know what you're doing.
+pub trait AsMutexGuard {
+    #[allow(missing_docs)]
+    unsafe fn as_mutex_guard(&self) -> &StaticMutexGuard;
+}
+
+impl Condvar {
+    /// Creates a new condition variable which is ready to be waited on and
+    /// notified.
+    pub fn new() -> Condvar {
+        Condvar {
+            inner: box StaticCondvar {
+                inner: unsafe { sys::Condvar::new() },
+                mutex: AtomicUint::new(0),
+            }
+        }
+    }
+
+    /// Block the current thread until this condition variable receives a
+    /// notification.
+    ///
+    /// This function will atomically unlock the mutex specified (represented by
+    /// `guard`) and block the current thread. This means that any calls to
+    /// `notify_*()` which happen logically after the mutex is unlocked are
+    /// candidates to wake this thread up. When this function call returns, the
+    /// lock specified will have been re-acquired.
+    ///
+    /// Note that this function is susceptible to spurious wakeups. Condition
+    /// variables normally have a boolean predicate associated with them, and
+    /// the predicate must always be checked each time this function returns to
+    /// protect against spurious wakeups.
+    ///
+    /// # Panics
+    ///
+    /// This function will `panic!()` if it is used with more than one mutex
+    /// over time. Each condition variable is dynamically bound to exactly one
+    /// mutex to ensure defined behavior across platforms. If this functionality
+    /// is not desired, then unsafe primitives in `sys` are provided.
+    pub fn wait<T: AsMutexGuard>(&self, mutex_guard: &T) {
+        unsafe {
+            let me: &'static Condvar = &*(self as *const _);
+            me.inner.wait(mutex_guard)
+        }
+    }
+
+    /// Wait on this condition variable for a notification, timing out after a
+    /// specified duration.
+    ///
+    /// The semantics of this function are equivalent to `wait()` except that
+    /// the thread will be blocked for roughly no longer than `dur`. This method
+    /// should not be used for precise timing due to anomalies such as
+    /// preemption or platform differences that may not cause the maximum amount
+    /// of time waited to be precisely `dur`.
+    ///
+    /// If the wait timed out, then `false` will be returned. Otherwise if a
+    /// notification was received then `true` will be returned.
+    ///
+    /// Like `wait`, the lock specified will be re-acquired when this function
+    /// returns, regardless of whether the timeout elapsed or not.
+    // Note that this method is *not* public, and this is quite intentional
+    // because we're not quite sure about the semantics of relative vs absolute
+    // durations or how the timing guarantees play into what the system APIs
+    // provide. There are also additional concerns about the unix-specific
+    // implementation which may need to be addressed.
+    #[allow(dead_code)]
+    fn wait_timeout<T: AsMutexGuard>(&self, mutex_guard: &T,
+                                     dur: Duration) -> bool {
+        unsafe {
+            let me: &'static Condvar = &*(self as *const _);
+            me.inner.wait_timeout(mutex_guard, dur)
+        }
+    }
+
+    /// Wake up one blocked thread on this condvar.
+    ///
+    /// If there is a blocked thread on this condition variable, then it will
+    /// be woken up from its call to `wait` or `wait_timeout`. Calls to
+    /// `notify_one` are not buffered in any way.
+    ///
+    /// To wake up all threads, see `notify_one()`.
+    pub fn notify_one(&self) { unsafe { self.inner.inner.notify_one() } }
+
+    /// Wake up all blocked threads on this condvar.
+    ///
+    /// This method will ensure that any current waiters on the condition
+    /// variable are awoken. Calls to `notify_all()` are not buffered in any
+    /// way.
+    ///
+    /// To wake up only one thread, see `notify_one()`.
+    pub fn notify_all(&self) { unsafe { self.inner.inner.notify_all() } }
+}
+
+impl Drop for Condvar {
+    fn drop(&mut self) {
+        unsafe { self.inner.inner.destroy() }
+    }
+}
+
+impl StaticCondvar {
+    /// Block the current thread until this condition variable receives a
+    /// notification.
+    ///
+    /// See `Condvar::wait`.
+    pub fn wait<T: AsMutexGuard>(&'static self, mutex_guard: &T) {
+        unsafe {
+            let lock = mutex_guard.as_mutex_guard();
+            let sys = mutex::guard_lock(lock);
+            self.verify(sys);
+            self.inner.wait(sys);
+            (*mutex::guard_poison(lock)).check("mutex");
+        }
+    }
+
+    /// Wait on this condition variable for a notification, timing out after a
+    /// specified duration.
+    ///
+    /// See `Condvar::wait_timeout`.
+    #[allow(dead_code)] // may want to stabilize this later, see wait_timeout above
+    fn wait_timeout<T: AsMutexGuard>(&'static self, mutex_guard: &T,
+                                     dur: Duration) -> bool {
+        unsafe {
+            let lock = mutex_guard.as_mutex_guard();
+            let sys = mutex::guard_lock(lock);
+            self.verify(sys);
+            let ret = self.inner.wait_timeout(sys, dur);
+            (*mutex::guard_poison(lock)).check("mutex");
+            return ret;
+        }
+    }
+
+    /// Wake up one blocked thread on this condvar.
+    ///
+    /// See `Condvar::notify_one`.
+    pub fn notify_one(&'static self) { unsafe { self.inner.notify_one() } }
+
+    /// Wake up all blocked threads on this condvar.
+    ///
+    /// See `Condvar::notify_all`.
+    pub fn notify_all(&'static self) { unsafe { self.inner.notify_all() } }
+
+    /// Deallocate all resources associated with this static condvar.
+    ///
+    /// This method is unsafe to call as there is no guarantee that there are no
+    /// active users of the condvar, and this also doesn't prevent any future
+    /// users of the condvar. This method is required to be called to not leak
+    /// memory on all platforms.
+    pub unsafe fn destroy(&'static self) {
+        self.inner.destroy()
+    }
+
+    fn verify(&self, mutex: &sys_mutex::Mutex) {
+        let addr = mutex as *const _ as uint;
+        match self.mutex.compare_and_swap(0, addr, atomic::SeqCst) {
+            // If we got out 0, then we have successfully bound the mutex to
+            // this cvar.
+            0 => {}
+
+            // If we get out a value that's the same as `addr`, then someone
+            // already beat us to the punch.
+            n if n == addr => {}
+
+            // Anything else and we're using more than one mutex on this cvar,
+            // which is currently disallowed.
+            _ => panic!("attempted to use a condition variable with two \
+                         mutexes"),
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use prelude::*;
+
+    use time::Duration;
+    use super::{StaticCondvar, CONDVAR_INIT};
+    use sync::{StaticMutex, MUTEX_INIT, Condvar, Mutex, Arc};
+
+    #[test]
+    fn smoke() {
+        let c = Condvar::new();
+        c.notify_one();
+        c.notify_all();
+    }
+
+    #[test]
+    fn static_smoke() {
+        static C: StaticCondvar = CONDVAR_INIT;
+        C.notify_one();
+        C.notify_all();
+        unsafe { C.destroy(); }
+    }
+
+    #[test]
+    fn notify_one() {
+        static C: StaticCondvar = CONDVAR_INIT;
+        static M: StaticMutex = MUTEX_INIT;
+
+        let g = M.lock();
+        spawn(move|| {
+            let _g = M.lock();
+            C.notify_one();
+        });
+        C.wait(&g);
+        drop(g);
+        unsafe { C.destroy(); M.destroy(); }
+    }
+
+    #[test]
+    fn notify_all() {
+        const N: uint = 10;
+
+        let data = Arc::new((Mutex::new(0), Condvar::new()));
+        let (tx, rx) = channel();
+        for _ in range(0, N) {
+            let data = data.clone();
+            let tx = tx.clone();
+            spawn(move|| {
+                let &(ref lock, ref cond) = &*data;
+                let mut cnt = lock.lock();
+                *cnt += 1;
+                if *cnt == N {
+                    tx.send(());
+                }
+                while *cnt != 0 {
+                    cond.wait(&cnt);
+                }
+                tx.send(());
+            });
+        }
+        drop(tx);
+
+        let &(ref lock, ref cond) = &*data;
+        rx.recv();
+        let mut cnt = lock.lock();
+        *cnt = 0;
+        cond.notify_all();
+        drop(cnt);
+
+        for _ in range(0, N) {
+            rx.recv();
+        }
+    }
+
+    #[test]
+    fn wait_timeout() {
+        static C: StaticCondvar = CONDVAR_INIT;
+        static M: StaticMutex = MUTEX_INIT;
+
+        let g = M.lock();
+        assert!(!C.wait_timeout(&g, Duration::nanoseconds(1000)));
+        spawn(move|| {
+            let _g = M.lock();
+            C.notify_one();
+        });
+        assert!(C.wait_timeout(&g, Duration::days(1)));
+        drop(g);
+        unsafe { C.destroy(); M.destroy(); }
+    }
+
+    #[test]
+    #[should_fail]
+    fn two_mutexes() {
+        static M1: StaticMutex = MUTEX_INIT;
+        static M2: StaticMutex = MUTEX_INIT;
+        static C: StaticCondvar = CONDVAR_INIT;
+
+        let g = M1.lock();
+        spawn(move|| {
+            let _g = M1.lock();
+            C.notify_one();
+        });
+        C.wait(&g);
+        drop(g);
+
+        C.wait(&M2.lock());
+
+    }
+}
diff --git a/src/libstd/sync/future.rs b/src/libstd/sync/future.rs
index e37d1f83877..51899a87a32 100644
--- a/src/libstd/sync/future.rs
+++ b/src/libstd/sync/future.rs
@@ -8,21 +8,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/*!
- * A type representing values that may be computed concurrently and
- * operations for working with them.
- *
- * # Example
- *
- * ```rust
- * use std::sync::Future;
- * # fn fib(n: uint) -> uint {42};
- * # fn make_a_sandwich() {};
- * let mut delayed_fib = Future::spawn(proc() { fib(5000) });
- * make_a_sandwich();
- * println!("fib(5000) = {}", delayed_fib.get())
- * ```
- */
+//! A type representing values that may be computed concurrently and operations for working with
+//! them.
+//!
+//! # Example
+//!
+//! ```rust
+//! use std::sync::Future;
+//! # fn fib(n: uint) -> uint {42};
+//! # fn make_a_sandwich() {};
+//! let mut delayed_fib = Future::spawn(move|| { fib(5000) });
+//! make_a_sandwich();
+//! println!("fib(5000) = {}", delayed_fib.get())
+//! ```
 
 #![allow(missing_docs)]
 
@@ -31,7 +29,8 @@ use core::mem::replace;
 
 use self::FutureState::*;
 use comm::{Receiver, channel};
-use task::spawn;
+use thunk::{Thunk};
+use thread::Thread;
 
 /// A type encapsulating the result of a computation which may not be complete
 pub struct Future<A> {
@@ -39,7 +38,7 @@ pub struct Future<A> {
 }
 
 enum FutureState<A> {
-    Pending(proc():Send -> A),
+    Pending(Thunk<(),A>),
     Evaluating,
     Forced(A)
 }
@@ -54,7 +53,7 @@ impl<A:Clone> Future<A> {
 
 impl<A> Future<A> {
     /// Gets the value from this future, forcing evaluation.
-    pub fn unwrap(mut self) -> A {
+    pub fn into_inner(mut self) -> A {
         self.get_ref();
         let state = replace(&mut self.state, Evaluating);
         match state {
@@ -63,6 +62,10 @@ impl<A> Future<A> {
         }
     }
 
+    /// Deprecated, use into_inner() instead
+    #[deprecated = "renamed to into_inner()"]
+    pub fn unwrap(self) -> A { self.into_inner() }
+
     pub fn get_ref<'a>(&'a mut self) -> &'a A {
         /*!
         * Executes the future's closure and then returns a reference
@@ -76,7 +79,7 @@ impl<A> Future<A> {
                 match replace(&mut self.state, Evaluating) {
                     Forced(_) | Evaluating => panic!("Logic error."),
                     Pending(f) => {
-                        self.state = Forced(f());
+                        self.state = Forced(f.invoke(()));
                         self.get_ref()
                     }
                 }
@@ -95,7 +98,9 @@ impl<A> Future<A> {
         Future {state: Forced(val)}
     }
 
-    pub fn from_fn(f: proc():Send -> A) -> Future<A> {
+    pub fn from_fn<F>(f: F) -> Future<A>
+        where F : FnOnce() -> A, F : Send
+    {
         /*!
          * Create a future from a function.
          *
@@ -104,7 +109,7 @@ impl<A> Future<A> {
          * function. It is not spawned into another task.
          */
 
-        Future {state: Pending(f)}
+        Future {state: Pending(Thunk::new(f))}
     }
 }
 
@@ -117,12 +122,14 @@ impl<A:Send> Future<A> {
          * waiting for the result to be received on the port.
          */
 
-        Future::from_fn(proc() {
+        Future::from_fn(move|:| {
             rx.recv()
         })
     }
 
-    pub fn spawn(blk: proc():Send -> A) -> Future<A> {
+    pub fn spawn<F>(blk: F) -> Future<A>
+        where F : FnOnce() -> A, F : Send
+    {
         /*!
          * Create a future from a unique closure.
          *
@@ -132,10 +139,10 @@ impl<A:Send> Future<A> {
 
         let (tx, rx) = channel();
 
-        spawn(proc() {
+        Thread::spawn(move |:| {
             // Don't panic if the other end has hung up
             let _ = tx.send_opt(blk());
-        });
+        }).detach();
 
         Future::from_receiver(rx)
     }
@@ -146,12 +153,11 @@ mod test {
     use prelude::*;
     use sync::Future;
     use task;
-    use comm::{channel, Sender};
 
     #[test]
     fn test_from_value() {
         let mut f = Future::from_value("snail".to_string());
-        assert_eq!(f.get(), "snail".to_string());
+        assert_eq!(f.get(), "snail");
     }
 
     #[test]
@@ -159,25 +165,25 @@ mod test {
         let (tx, rx) = channel();
         tx.send("whale".to_string());
         let mut f = Future::from_receiver(rx);
-        assert_eq!(f.get(), "whale".to_string());
+        assert_eq!(f.get(), "whale");
     }
 
     #[test]
     fn test_from_fn() {
-        let mut f = Future::from_fn(proc() "brail".to_string());
-        assert_eq!(f.get(), "brail".to_string());
+        let mut f = Future::from_fn(move|| "brail".to_string());
+        assert_eq!(f.get(), "brail");
     }
 
     #[test]
     fn test_interface_get() {
         let mut f = Future::from_value("fail".to_string());
-        assert_eq!(f.get(), "fail".to_string());
+        assert_eq!(f.get(), "fail");
     }
 
     #[test]
     fn test_interface_unwrap() {
         let f = Future::from_value("fail".to_string());
-        assert_eq!(f.unwrap(), "fail".to_string());
+        assert_eq!(f.unwrap(), "fail");
     }
 
     #[test]
@@ -188,14 +194,14 @@ mod test {
 
     #[test]
     fn test_spawn() {
-        let mut f = Future::spawn(proc() "bale".to_string());
-        assert_eq!(f.get(), "bale".to_string());
+        let mut f = Future::spawn(move|| "bale".to_string());
+        assert_eq!(f.get(), "bale");
     }
 
     #[test]
     #[should_fail]
     fn test_future_panic() {
-        let mut f = Future::spawn(proc() panic!());
+        let mut f = Future::spawn(move|| panic!());
         let _x: String = f.get();
     }
 
@@ -203,35 +209,11 @@ mod test {
     fn test_sendable_future() {
         let expected = "schlorf";
         let (tx, rx) = channel();
-        let f = Future::spawn(proc() { expected });
-        task::spawn(proc() {
+        let f = Future::spawn(move|| { expected });
+        task::spawn(move|| {
             let mut f = f;
             tx.send(f.get());
         });
         assert_eq!(rx.recv(), expected);
     }
-
-    #[test]
-    fn test_dropped_future_doesnt_panic() {
-        struct Bomb(Sender<bool>);
-
-        local_data_key!(LOCAL: Bomb)
-
-        impl Drop for Bomb {
-            fn drop(&mut self) {
-                let Bomb(ref tx) = *self;
-                tx.send(task::failing());
-            }
-        }
-
-        // Spawn a future, but drop it immediately. When we receive the result
-        // later on, we should never view the task as having panicked.
-        let (tx, rx) = channel();
-        drop(Future::spawn(proc() {
-            LOCAL.replace(Some(Bomb(tx)));
-        }));
-
-        // Make sure the future didn't panic the task.
-        assert!(!rx.recv());
-    }
 }
diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs
index 38e1e952f77..7605a6a96a0 100644
--- a/src/libstd/sync/mod.rs
+++ b/src/libstd/sync/mod.rs
@@ -17,17 +17,27 @@
 
 #![experimental]
 
-#[stable]
-pub use core_sync::atomic;
+pub use alloc::arc::{Arc, Weak};
 
-pub use core_sync::{deque, mpmc_bounded_queue, mpsc_queue, spsc_queue};
-pub use core_sync::{Arc, Weak, Mutex, MutexGuard, Condvar, Barrier};
-pub use core_sync::{RWLock, RWLockReadGuard, RWLockWriteGuard};
-pub use core_sync::{Semaphore, SemaphoreGuard};
-pub use core_sync::one::{Once, ONCE_INIT};
+pub use self::mutex::{Mutex, MutexGuard, StaticMutex, StaticMutexGuard, MUTEX_INIT};
+pub use self::rwlock::{RWLock, StaticRWLock, RWLOCK_INIT};
+pub use self::rwlock::{RWLockReadGuard, RWLockWriteGuard};
+pub use self::rwlock::{StaticRWLockReadGuard, StaticRWLockWriteGuard};
+pub use self::condvar::{Condvar, StaticCondvar, CONDVAR_INIT, AsMutexGuard};
+pub use self::once::{Once, ONCE_INIT};
+pub use self::semaphore::{Semaphore, SemaphoreGuard};
+pub use self::barrier::Barrier;
 
 pub use self::future::Future;
 pub use self::task_pool::TaskPool;
 
+pub mod atomic;
+mod barrier;
+mod condvar;
 mod future;
+mod mutex;
+mod once;
+mod poison;
+mod rwlock;
+mod semaphore;
 mod task_pool;
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
new file mode 100644
index 00000000000..4829be569cc
--- /dev/null
+++ b/src/libstd/sync/mutex.rs
@@ -0,0 +1,433 @@
+// 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.
+
+use prelude::*;
+
+use cell::UnsafeCell;
+use kinds::marker;
+use sync::{poison, AsMutexGuard};
+use sys_common::mutex as sys;
+
+/// A mutual exclusion primitive useful for protecting shared data
+///
+/// This mutex will block threads waiting for the lock to become available. The
+/// mutex can also be statically initialized or created via a `new`
+/// constructor. Each mutex has a type parameter which represents the data that
+/// it is protecting. The data can only be accessed through the RAII guards
+/// returned from `lock` and `try_lock`, which guarantees that the data is only
+/// ever accessed when the mutex is locked.
+///
+/// # Poisoning
+///
+/// In order to prevent access to otherwise invalid data, each mutex will
+/// propagate any panics which occur while the lock is held. Once a thread has
+/// panicked while holding the lock, then all other threads will immediately
+/// panic as well once they hold the lock.
+///
+/// # Example
+///
+/// ```rust
+/// use std::sync::{Arc, Mutex};
+/// use std::thread::Thread;
+/// const N: uint = 10;
+///
+/// // Spawn a few threads to increment a shared variable (non-atomically), and
+/// // let the main thread know once all increments are done.
+/// //
+/// // Here we're using an Arc to share memory among tasks, and the data inside
+/// // the Arc is protected with a mutex.
+/// let data = Arc::new(Mutex::new(0));
+///
+/// let (tx, rx) = channel();
+/// for _ in range(0u, 10) {
+///     let (data, tx) = (data.clone(), tx.clone());
+///     Thread::spawn(move|| {
+///         // The shared static can only be accessed once the lock is held.
+///         // Our non-atomic increment is safe because we're the only thread
+///         // which can access the shared state when the lock is held.
+///         let mut data = data.lock();
+///         *data += 1;
+///         if *data == N {
+///             tx.send(());
+///         }
+///         // the lock is unlocked here when `data` goes out of scope.
+///     }).detach();
+/// }
+///
+/// rx.recv();
+/// ```
+pub struct Mutex<T> {
+    // Note that this static mutex is in a *box*, not inlined into the struct
+    // itself. Once a native mutex has been used once, its address can never
+    // change (it can't be moved). This mutex type can be safely moved at any
+    // time, so to ensure that the native mutex is used correctly we box the
+    // inner lock to give it a constant address.
+    inner: Box<StaticMutex>,
+    data: UnsafeCell<T>,
+}
+
+/// The static mutex type is provided to allow for static allocation of mutexes.
+///
+/// Note that this is a separate type because using a Mutex correctly means that
+/// it needs to have a destructor run. In Rust, statics are not allowed to have
+/// destructors. As a result, a `StaticMutex` has one extra method when compared
+/// to a `Mutex`, a `destroy` method. This method is unsafe to call, and
+/// documentation can be found directly on the method.
+///
+/// # Example
+///
+/// ```rust
+/// use std::sync::{StaticMutex, MUTEX_INIT};
+///
+/// static LOCK: StaticMutex = MUTEX_INIT;
+///
+/// {
+///     let _g = LOCK.lock();
+///     // do some productive work
+/// }
+/// // lock is unlocked here.
+/// ```
+pub struct StaticMutex {
+    lock: sys::Mutex,
+    poison: UnsafeCell<poison::Flag>,
+}
+
+/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
+/// dropped (falls out of scope), the lock will be unlocked.
+///
+/// The data protected by the mutex can be access through this guard via its
+/// Deref and DerefMut implementations
+#[must_use]
+pub struct MutexGuard<'a, T: 'a> {
+    // funny underscores due to how Deref/DerefMut currently work (they
+    // disregard field privacy).
+    __lock: &'a Mutex<T>,
+    __guard: StaticMutexGuard,
+}
+
+/// An RAII implementation of a "scoped lock" of a static mutex. When this
+/// structure is dropped (falls out of scope), the lock will be unlocked.
+#[must_use]
+pub struct StaticMutexGuard {
+    lock: &'static sys::Mutex,
+    marker: marker::NoSend,
+    poison: poison::Guard<'static>,
+}
+
+/// Static initialization of a mutex. This constant can be used to initialize
+/// other mutex constants.
+pub const MUTEX_INIT: StaticMutex = StaticMutex {
+    lock: sys::MUTEX_INIT,
+    poison: UnsafeCell { value: poison::Flag { failed: false } },
+};
+
+impl<T: Send> Mutex<T> {
+    /// Creates a new mutex in an unlocked state ready for use.
+    pub fn new(t: T) -> Mutex<T> {
+        Mutex {
+            inner: box MUTEX_INIT,
+            data: UnsafeCell::new(t),
+        }
+    }
+
+    /// Acquires a mutex, blocking the current task until it is able to do so.
+    ///
+    /// This function will block the local task until it is available to acquire
+    /// the mutex. Upon returning, the task is the only task with the mutex
+    /// held. An RAII guard is returned to allow scoped unlock of the lock. When
+    /// the guard goes out of scope, the mutex will be unlocked.
+    ///
+    /// # Panics
+    ///
+    /// If another user of this mutex panicked while holding the mutex, then
+    /// this call will immediately panic once the mutex is acquired.
+    pub fn lock(&self) -> MutexGuard<T> {
+        unsafe {
+            let lock: &'static StaticMutex = &*(&*self.inner as *const _);
+            MutexGuard::new(self, lock.lock())
+        }
+    }
+
+    /// Attempts to acquire this lock.
+    ///
+    /// If the lock could not be acquired at this time, then `None` is returned.
+    /// Otherwise, an RAII guard is returned. The lock will be unlocked when the
+    /// guard is dropped.
+    ///
+    /// This function does not block.
+    ///
+    /// # Panics
+    ///
+    /// If another user of this mutex panicked while holding the mutex, then
+    /// this call will immediately panic if the mutex would otherwise be
+    /// acquired.
+    pub fn try_lock(&self) -> Option<MutexGuard<T>> {
+        unsafe {
+            let lock: &'static StaticMutex = &*(&*self.inner as *const _);
+            lock.try_lock().map(|guard| {
+                MutexGuard::new(self, guard)
+            })
+        }
+    }
+}
+
+#[unsafe_destructor]
+impl<T: Send> Drop for Mutex<T> {
+    fn drop(&mut self) {
+        // This is actually safe b/c we know that there is no further usage of
+        // this mutex (it's up to the user to arrange for a mutex to get
+        // dropped, that's not our job)
+        unsafe { self.inner.lock.destroy() }
+    }
+}
+
+impl StaticMutex {
+    /// Acquires this lock, see `Mutex::lock`
+    pub fn lock(&'static self) -> StaticMutexGuard {
+        unsafe { self.lock.lock() }
+        StaticMutexGuard::new(self)
+    }
+
+    /// Attempts to grab this lock, see `Mutex::try_lock`
+    pub fn try_lock(&'static self) -> Option<StaticMutexGuard> {
+        if unsafe { self.lock.try_lock() } {
+            Some(StaticMutexGuard::new(self))
+        } else {
+            None
+        }
+    }
+
+    /// Deallocates resources associated with this static mutex.
+    ///
+    /// This method is unsafe because it provides no guarantees that there are
+    /// no active users of this mutex, and safety is not guaranteed if there are
+    /// active users of this mutex.
+    ///
+    /// This method is required to ensure that there are no memory leaks on
+    /// *all* platforms. It may be the case that some platforms do not leak
+    /// memory if this method is not called, but this is not guaranteed to be
+    /// true on all platforms.
+    pub unsafe fn destroy(&'static self) {
+        self.lock.destroy()
+    }
+}
+
+impl<'mutex, T> MutexGuard<'mutex, T> {
+    fn new(lock: &Mutex<T>, guard: StaticMutexGuard) -> MutexGuard<T> {
+        MutexGuard { __lock: lock, __guard: guard }
+    }
+}
+
+impl<'mutex, T> AsMutexGuard for MutexGuard<'mutex, T> {
+    unsafe fn as_mutex_guard(&self) -> &StaticMutexGuard { &self.__guard }
+}
+
+impl<'mutex, T> Deref<T> for MutexGuard<'mutex, T> {
+    fn deref<'a>(&'a self) -> &'a T { unsafe { &*self.__lock.data.get() } }
+}
+impl<'mutex, T> DerefMut<T> for MutexGuard<'mutex, T> {
+    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
+        unsafe { &mut *self.__lock.data.get() }
+    }
+}
+
+impl StaticMutexGuard {
+    fn new(lock: &'static StaticMutex) -> StaticMutexGuard {
+        unsafe {
+            let guard = StaticMutexGuard {
+                lock: &lock.lock,
+                marker: marker::NoSend,
+                poison: (*lock.poison.get()).borrow(),
+            };
+            guard.poison.check("mutex");
+            return guard;
+        }
+    }
+}
+
+pub fn guard_lock(guard: &StaticMutexGuard) -> &sys::Mutex { guard.lock }
+pub fn guard_poison(guard: &StaticMutexGuard) -> &poison::Guard {
+    &guard.poison
+}
+
+impl AsMutexGuard for StaticMutexGuard {
+    unsafe fn as_mutex_guard(&self) -> &StaticMutexGuard { self }
+}
+
+#[unsafe_destructor]
+impl Drop for StaticMutexGuard {
+    fn drop(&mut self) {
+        unsafe {
+            self.poison.done();
+            self.lock.unlock();
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use prelude::*;
+
+    use thread::Thread;
+    use sync::{Arc, Mutex, StaticMutex, MUTEX_INIT, Condvar};
+
+    #[test]
+    fn smoke() {
+        let m = Mutex::new(());
+        drop(m.lock());
+        drop(m.lock());
+    }
+
+    #[test]
+    fn smoke_static() {
+        static M: StaticMutex = MUTEX_INIT;
+        unsafe {
+            drop(M.lock());
+            drop(M.lock());
+            M.destroy();
+        }
+    }
+
+    #[test]
+    fn lots_and_lots() {
+        static M: StaticMutex = MUTEX_INIT;
+        static mut CNT: uint = 0;
+        static J: uint = 1000;
+        static K: uint = 3;
+
+        fn inc() {
+            for _ in range(0, J) {
+                unsafe {
+                    let _g = M.lock();
+                    CNT += 1;
+                }
+            }
+        }
+
+        let (tx, rx) = channel();
+        for _ in range(0, K) {
+            let tx2 = tx.clone();
+            spawn(move|| { inc(); tx2.send(()); });
+            let tx2 = tx.clone();
+            spawn(move|| { inc(); tx2.send(()); });
+        }
+
+        drop(tx);
+        for _ in range(0, 2 * K) {
+            rx.recv();
+        }
+        assert_eq!(unsafe {CNT}, J * K * 2);
+        unsafe {
+            M.destroy();
+        }
+    }
+
+    #[test]
+    fn try_lock() {
+        let m = Mutex::new(());
+        assert!(m.try_lock().is_some());
+    }
+
+    #[test]
+    fn test_mutex_arc_condvar() {
+        let arc = Arc::new((Mutex::new(false), Condvar::new()));
+        let arc2 = arc.clone();
+        let (tx, rx) = channel();
+        spawn(move|| {
+            // wait until parent gets in
+            rx.recv();
+            let &(ref lock, ref cvar) = &*arc2;
+            let mut lock = lock.lock();
+            *lock = true;
+            cvar.notify_one();
+        });
+
+        let &(ref lock, ref cvar) = &*arc;
+        let lock = lock.lock();
+        tx.send(());
+        assert!(!*lock);
+        while !*lock {
+            cvar.wait(&lock);
+        }
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_arc_condvar_poison() {
+        let arc = Arc::new((Mutex::new(1i), Condvar::new()));
+        let arc2 = arc.clone();
+        let (tx, rx) = channel();
+
+        spawn(move|| {
+            rx.recv();
+            let &(ref lock, ref cvar) = &*arc2;
+            let _g = lock.lock();
+            cvar.notify_one();
+            // Parent should fail when it wakes up.
+            panic!();
+        });
+
+        let &(ref lock, ref cvar) = &*arc;
+        let lock = lock.lock();
+        tx.send(());
+        while *lock == 1 {
+            cvar.wait(&lock);
+        }
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_mutex_arc_poison() {
+        let arc = Arc::new(Mutex::new(1i));
+        let arc2 = arc.clone();
+        let _ = Thread::spawn(move|| {
+            let lock = arc2.lock();
+            assert_eq!(*lock, 2);
+        }).join();
+        let lock = arc.lock();
+        assert_eq!(*lock, 1);
+    }
+
+    #[test]
+    fn test_mutex_arc_nested() {
+        // Tests nested mutexes and access
+        // to underlying data.
+        let arc = Arc::new(Mutex::new(1i));
+        let arc2 = Arc::new(Mutex::new(arc));
+        let (tx, rx) = channel();
+        spawn(move|| {
+            let lock = arc2.lock();
+            let lock2 = lock.deref().lock();
+            assert_eq!(*lock2, 1);
+            tx.send(());
+        });
+        rx.recv();
+    }
+
+    #[test]
+    fn test_mutex_arc_access_in_unwind() {
+        let arc = Arc::new(Mutex::new(1i));
+        let arc2 = arc.clone();
+        let _ = Thread::spawn(move|| -> () {
+            struct Unwinder {
+                i: Arc<Mutex<int>>,
+            }
+            impl Drop for Unwinder {
+                fn drop(&mut self) {
+                    *self.i.lock() += 1;
+                }
+            }
+            let _u = Unwinder { i: arc2 };
+            panic!();
+        }).join();
+        let lock = arc.lock();
+        assert_eq!(*lock, 2);
+    }
+}
diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs
new file mode 100644
index 00000000000..a43f822e351
--- /dev/null
+++ b/src/libstd/sync/once.rs
@@ -0,0 +1,170 @@
+// 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.
+
+//! A "once initialization" primitive
+//!
+//! This primitive is meant to be used to run one-time initialization. An
+//! example use case would be for initializing an FFI library.
+
+use int;
+use mem::drop;
+use ops::FnOnce;
+use sync::atomic;
+use sync::{StaticMutex, MUTEX_INIT};
+
+/// A synchronization primitive which can be used to run a one-time global
+/// initialization. Useful for one-time initialization for FFI or related
+/// functionality. This type can only be constructed with the `ONCE_INIT`
+/// value.
+///
+/// # Example
+///
+/// ```rust
+/// use std::sync::{Once, ONCE_INIT};
+///
+/// static START: Once = ONCE_INIT;
+///
+/// START.doit(|| {
+///     // run initialization here
+/// });
+/// ```
+pub struct Once {
+    mutex: StaticMutex,
+    cnt: atomic::AtomicInt,
+    lock_cnt: atomic::AtomicInt,
+}
+
+/// Initialization value for static `Once` values.
+pub const ONCE_INIT: Once = Once {
+    mutex: MUTEX_INIT,
+    cnt: atomic::INIT_ATOMIC_INT,
+    lock_cnt: atomic::INIT_ATOMIC_INT,
+};
+
+impl Once {
+    /// Perform an initialization routine once and only once. The given closure
+    /// will be executed if this is the first time `doit` has been called, and
+    /// otherwise the routine will *not* be invoked.
+    ///
+    /// This method will block the calling task if another initialization
+    /// routine is currently running.
+    ///
+    /// When this function returns, it is guaranteed that some initialization
+    /// has run and completed (it may not be the closure specified).
+    pub fn doit<F>(&'static self, f: F) where F: FnOnce() {
+        // Optimize common path: load is much cheaper than fetch_add.
+        if self.cnt.load(atomic::SeqCst) < 0 {
+            return
+        }
+
+        // Implementation-wise, this would seem like a fairly trivial primitive.
+        // The stickler part is where our mutexes currently require an
+        // allocation, and usage of a `Once` shouldn't leak this allocation.
+        //
+        // This means that there must be a deterministic destroyer of the mutex
+        // contained within (because it's not needed after the initialization
+        // has run).
+        //
+        // The general scheme here is to gate all future threads once
+        // initialization has completed with a "very negative" count, and to
+        // allow through threads to lock the mutex if they see a non negative
+        // count. For all threads grabbing the mutex, exactly one of them should
+        // be responsible for unlocking the mutex, and this should only be done
+        // once everyone else is done with the mutex.
+        //
+        // This atomicity is achieved by swapping a very negative value into the
+        // shared count when the initialization routine has completed. This will
+        // read the number of threads which will at some point attempt to
+        // acquire the mutex. This count is then squirreled away in a separate
+        // variable, and the last person on the way out of the mutex is then
+        // responsible for destroying the mutex.
+        //
+        // It is crucial that the negative value is swapped in *after* the
+        // initialization routine has completed because otherwise new threads
+        // calling `doit` will return immediately before the initialization has
+        // completed.
+
+        let prev = self.cnt.fetch_add(1, atomic::SeqCst);
+        if prev < 0 {
+            // Make sure we never overflow, we'll never have int::MIN
+            // simultaneous calls to `doit` to make this value go back to 0
+            self.cnt.store(int::MIN, atomic::SeqCst);
+            return
+        }
+
+        // If the count is negative, then someone else finished the job,
+        // otherwise we run the job and record how many people will try to grab
+        // this lock
+        let guard = self.mutex.lock();
+        if self.cnt.load(atomic::SeqCst) > 0 {
+            f();
+            let prev = self.cnt.swap(int::MIN, atomic::SeqCst);
+            self.lock_cnt.store(prev, atomic::SeqCst);
+        }
+        drop(guard);
+
+        // Last one out cleans up after everyone else, no leaks!
+        if self.lock_cnt.fetch_add(-1, atomic::SeqCst) == 1 {
+            unsafe { self.mutex.destroy() }
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use prelude::*;
+
+    use thread::Thread;
+    use super::{ONCE_INIT, Once};
+
+    #[test]
+    fn smoke_once() {
+        static O: Once = ONCE_INIT;
+        let mut a = 0i;
+        O.doit(|| a += 1);
+        assert_eq!(a, 1);
+        O.doit(|| a += 1);
+        assert_eq!(a, 1);
+    }
+
+    #[test]
+    fn stampede_once() {
+        static O: Once = ONCE_INIT;
+        static mut run: bool = false;
+
+        let (tx, rx) = channel();
+        for _ in range(0u, 10) {
+            let tx = tx.clone();
+            spawn(move|| {
+                for _ in range(0u, 4) { Thread::yield_now() }
+                unsafe {
+                    O.doit(|| {
+                        assert!(!run);
+                        run = true;
+                    });
+                    assert!(run);
+                }
+                tx.send(());
+            });
+        }
+
+        unsafe {
+            O.doit(|| {
+                assert!(!run);
+                run = true;
+            });
+            assert!(run);
+        }
+
+        for _ in range(0u, 10) {
+            rx.recv();
+        }
+    }
+}
diff --git a/src/libstd/sync/poison.rs b/src/libstd/sync/poison.rs
new file mode 100644
index 00000000000..ad08e9873fa
--- /dev/null
+++ b/src/libstd/sync/poison.rs
@@ -0,0 +1,38 @@
+// 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.
+
+use thread::Thread;
+
+pub struct Flag { pub failed: bool }
+
+impl Flag {
+    pub fn borrow(&mut self) -> Guard {
+        Guard { flag: &mut self.failed, panicking: Thread::panicking() }
+    }
+}
+
+pub struct Guard<'a> {
+    flag: &'a mut bool,
+    panicking: bool,
+}
+
+impl<'a> Guard<'a> {
+    pub fn check(&self, name: &str) {
+        if *self.flag {
+            panic!("poisoned {} - another task failed inside", name);
+        }
+    }
+
+    pub fn done(&mut self) {
+        if !self.panicking && Thread::panicking() {
+            *self.flag = true;
+        }
+    }
+}
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
new file mode 100644
index 00000000000..3f177a42f44
--- /dev/null
+++ b/src/libstd/sync/rwlock.rs
@@ -0,0 +1,514 @@
+// 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.
+
+use prelude::*;
+
+use kinds::marker;
+use cell::UnsafeCell;
+use sys_common::rwlock as sys;
+use sync::poison;
+
+/// A reader-writer lock
+///
+/// This type of lock allows a number of readers or at most one writer at any
+/// point in time. The write portion of this lock typically allows modification
+/// of the underlying data (exclusive access) and the read portion of this lock
+/// typically allows for read-only access (shared access).
+///
+/// The type parameter `T` represents the data that this lock protects. It is
+/// required that `T` satisfies `Send` to be shared across tasks and `Sync` to
+/// allow concurrent access through readers. The RAII guards returned from the
+/// locking methods implement `Deref` (and `DerefMut` for the `write` methods)
+/// to allow access to the contained of the lock.
+///
+/// RWLocks, like Mutexes, will become poisoned on panics. Note, however, that
+/// an RWLock may only be poisoned if a panic occurs while it is locked
+/// exclusively (write mode). If a panic occurs in any reader, then the lock
+/// will not be poisoned.
+///
+/// # Example
+///
+/// ```
+/// use std::sync::RWLock;
+///
+/// let lock = RWLock::new(5i);
+///
+/// // many reader locks can be held at once
+/// {
+///     let r1 = lock.read();
+///     let r2 = lock.read();
+///     assert_eq!(*r1, 5);
+///     assert_eq!(*r2, 5);
+/// } // read locks are dropped at this point
+///
+/// // only one write lock may be held, however
+/// {
+///     let mut w = lock.write();
+///     *w += 1;
+///     assert_eq!(*w, 6);
+/// } // write lock is dropped here
+/// ```
+pub struct RWLock<T> {
+    inner: Box<StaticRWLock>,
+    data: UnsafeCell<T>,
+}
+
+/// Structure representing a statically allocated RWLock.
+///
+/// This structure is intended to be used inside of a `static` and will provide
+/// automatic global access as well as lazy initialization. The internal
+/// resources of this RWLock, however, must be manually deallocated.
+///
+/// # Example
+///
+/// ```
+/// use std::sync::{StaticRWLock, RWLOCK_INIT};
+///
+/// static LOCK: StaticRWLock = RWLOCK_INIT;
+///
+/// {
+///     let _g = LOCK.read();
+///     // ... shared read access
+/// }
+/// {
+///     let _g = LOCK.write();
+///     // ... exclusive write access
+/// }
+/// unsafe { LOCK.destroy() } // free all resources
+/// ```
+pub struct StaticRWLock {
+    inner: sys::RWLock,
+    poison: UnsafeCell<poison::Flag>,
+}
+
+/// Constant initialization for a statically-initialized rwlock.
+pub const RWLOCK_INIT: StaticRWLock = StaticRWLock {
+    inner: sys::RWLOCK_INIT,
+    poison: UnsafeCell { value: poison::Flag { failed: false } },
+};
+
+/// RAII structure used to release the shared read access of a lock when
+/// dropped.
+#[must_use]
+pub struct RWLockReadGuard<'a, T: 'a> {
+    __lock: &'a RWLock<T>,
+    __guard: StaticRWLockReadGuard,
+}
+
+/// RAII structure used to release the exclusive write access of a lock when
+/// dropped.
+#[must_use]
+pub struct RWLockWriteGuard<'a, T: 'a> {
+    __lock: &'a RWLock<T>,
+    __guard: StaticRWLockWriteGuard,
+}
+
+/// RAII structure used to release the shared read access of a lock when
+/// dropped.
+#[must_use]
+pub struct StaticRWLockReadGuard {
+    lock: &'static sys::RWLock,
+    marker: marker::NoSend,
+}
+
+/// RAII structure used to release the exclusive write access of a lock when
+/// dropped.
+#[must_use]
+pub struct StaticRWLockWriteGuard {
+    lock: &'static sys::RWLock,
+    marker: marker::NoSend,
+    poison: poison::Guard<'static>,
+}
+
+impl<T: Send + Sync> RWLock<T> {
+    /// Creates a new instance of an RWLock which is unlocked and read to go.
+    pub fn new(t: T) -> RWLock<T> {
+        RWLock { inner: box RWLOCK_INIT, data: UnsafeCell::new(t) }
+    }
+
+    /// Locks this rwlock with shared read access, blocking the current thread
+    /// until it can be acquired.
+    ///
+    /// The calling thread will be blocked until there are no more writers which
+    /// hold the lock. There may be other readers currently inside the lock when
+    /// this method returns. This method does not provide any guarantees with
+    /// respect to the ordering of whether contentious readers or writers will
+    /// acquire the lock first.
+    ///
+    /// Returns an RAII guard which will release this thread's shared access
+    /// once it is dropped.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if the RWLock is poisoned. An RWLock is
+    /// poisoned whenever a writer panics while holding an exclusive lock. The
+    /// panic will occur immediately after the lock has been acquired.
+    #[inline]
+    pub fn read(&self) -> RWLockReadGuard<T> {
+        unsafe {
+            let lock: &'static StaticRWLock = &*(&*self.inner as *const _);
+            RWLockReadGuard::new(self, lock.read())
+        }
+    }
+
+    /// Attempt to acquire this lock with shared read access.
+    ///
+    /// This function will never block and will return immediately if `read`
+    /// would otherwise succeed. Returns `Some` of an RAII guard which will
+    /// release the shared access of this thread when dropped, or `None` if the
+    /// access could not be granted. This method does not provide any
+    /// guarantees with respect to the ordering of whether contentious readers
+    /// or writers will acquire the lock first.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if the RWLock is poisoned. An RWLock is
+    /// poisoned whenever a writer panics while holding an exclusive lock. A
+    /// panic will only occur if the lock is acquired.
+    #[inline]
+    pub fn try_read(&self) -> Option<RWLockReadGuard<T>> {
+        unsafe {
+            let lock: &'static StaticRWLock = &*(&*self.inner as *const _);
+            lock.try_read().map(|guard| {
+                RWLockReadGuard::new(self, guard)
+            })
+        }
+    }
+
+    /// Lock this rwlock with exclusive write access, blocking the current
+    /// thread until it can be acquired.
+    ///
+    /// This function will not return while other writers or other readers
+    /// currently have access to the lock.
+    ///
+    /// Returns an RAII guard which will drop the write access of this rwlock
+    /// when dropped.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if the RWLock is poisoned. An RWLock is
+    /// poisoned whenever a writer panics while holding an exclusive lock. The
+    /// panic will occur when the lock is acquired.
+    #[inline]
+    pub fn write(&self) -> RWLockWriteGuard<T> {
+        unsafe {
+            let lock: &'static StaticRWLock = &*(&*self.inner as *const _);
+            RWLockWriteGuard::new(self, lock.write())
+        }
+    }
+
+    /// Attempt to lock this rwlock with exclusive write access.
+    ///
+    /// This function does not ever block, and it will return `None` if a call
+    /// to `write` would otherwise block. If successful, an RAII guard is
+    /// returned.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if the RWLock is poisoned. An RWLock is
+    /// poisoned whenever a writer panics while holding an exclusive lock. A
+    /// panic will only occur if the lock is acquired.
+    #[inline]
+    pub fn try_write(&self) -> Option<RWLockWriteGuard<T>> {
+        unsafe {
+            let lock: &'static StaticRWLock = &*(&*self.inner as *const _);
+            lock.try_write().map(|guard| {
+                RWLockWriteGuard::new(self, guard)
+            })
+        }
+    }
+}
+
+#[unsafe_destructor]
+impl<T> Drop for RWLock<T> {
+    fn drop(&mut self) {
+        unsafe { self.inner.inner.destroy() }
+    }
+}
+
+impl StaticRWLock {
+    /// Locks this rwlock with shared read access, blocking the current thread
+    /// until it can be acquired.
+    ///
+    /// See `RWLock::read`.
+    #[inline]
+    pub fn read(&'static self) -> StaticRWLockReadGuard {
+        unsafe { self.inner.read() }
+        StaticRWLockReadGuard::new(self)
+    }
+
+    /// Attempt to acquire this lock with shared read access.
+    ///
+    /// See `RWLock::try_read`.
+    #[inline]
+    pub fn try_read(&'static self) -> Option<StaticRWLockReadGuard> {
+        if unsafe { self.inner.try_read() } {
+            Some(StaticRWLockReadGuard::new(self))
+        } else {
+            None
+        }
+    }
+
+    /// Lock this rwlock with exclusive write access, blocking the current
+    /// thread until it can be acquired.
+    ///
+    /// See `RWLock::write`.
+    #[inline]
+    pub fn write(&'static self) -> StaticRWLockWriteGuard {
+        unsafe { self.inner.write() }
+        StaticRWLockWriteGuard::new(self)
+    }
+
+    /// Attempt to lock this rwlock with exclusive write access.
+    ///
+    /// See `RWLock::try_write`.
+    #[inline]
+    pub fn try_write(&'static self) -> Option<StaticRWLockWriteGuard> {
+        if unsafe { self.inner.try_write() } {
+            Some(StaticRWLockWriteGuard::new(self))
+        } else {
+            None
+        }
+    }
+
+    /// Deallocate all resources associated with this static lock.
+    ///
+    /// This method is unsafe to call as there is no guarantee that there are no
+    /// active users of the lock, and this also doesn't prevent any future users
+    /// of this lock. This method is required to be called to not leak memory on
+    /// all platforms.
+    pub unsafe fn destroy(&'static self) {
+        self.inner.destroy()
+    }
+}
+
+impl<'rwlock, T> RWLockReadGuard<'rwlock, T> {
+    fn new(lock: &RWLock<T>, guard: StaticRWLockReadGuard)
+           -> RWLockReadGuard<T> {
+        RWLockReadGuard { __lock: lock, __guard: guard }
+    }
+}
+impl<'rwlock, T> RWLockWriteGuard<'rwlock, T> {
+    fn new(lock: &RWLock<T>, guard: StaticRWLockWriteGuard)
+           -> RWLockWriteGuard<T> {
+        RWLockWriteGuard { __lock: lock, __guard: guard }
+    }
+}
+
+impl<'rwlock, T> Deref<T> for RWLockReadGuard<'rwlock, T> {
+    fn deref(&self) -> &T { unsafe { &*self.__lock.data.get() } }
+}
+impl<'rwlock, T> Deref<T> for RWLockWriteGuard<'rwlock, T> {
+    fn deref(&self) -> &T { unsafe { &*self.__lock.data.get() } }
+}
+impl<'rwlock, T> DerefMut<T> for RWLockWriteGuard<'rwlock, T> {
+    fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.__lock.data.get() } }
+}
+
+impl StaticRWLockReadGuard {
+    fn new(lock: &'static StaticRWLock) -> StaticRWLockReadGuard {
+        let guard = StaticRWLockReadGuard {
+            lock: &lock.inner,
+            marker: marker::NoSend,
+        };
+        unsafe { (*lock.poison.get()).borrow().check("rwlock"); }
+        return guard;
+    }
+}
+impl StaticRWLockWriteGuard {
+    fn new(lock: &'static StaticRWLock) -> StaticRWLockWriteGuard {
+        unsafe {
+            let guard = StaticRWLockWriteGuard {
+                lock: &lock.inner,
+                marker: marker::NoSend,
+                poison: (*lock.poison.get()).borrow(),
+            };
+            guard.poison.check("rwlock");
+            return guard;
+        }
+    }
+}
+
+#[unsafe_destructor]
+impl Drop for StaticRWLockReadGuard {
+    fn drop(&mut self) {
+        unsafe { self.lock.read_unlock(); }
+    }
+}
+
+#[unsafe_destructor]
+impl Drop for StaticRWLockWriteGuard {
+    fn drop(&mut self) {
+        self.poison.done();
+        unsafe { self.lock.write_unlock(); }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use prelude::*;
+
+    use rand::{mod, Rng};
+    use thread::Thread;
+    use sync::{Arc, RWLock, StaticRWLock, RWLOCK_INIT};
+
+    #[test]
+    fn smoke() {
+        let l = RWLock::new(());
+        drop(l.read());
+        drop(l.write());
+        drop((l.read(), l.read()));
+        drop(l.write());
+    }
+
+    #[test]
+    fn static_smoke() {
+        static R: StaticRWLock = RWLOCK_INIT;
+        drop(R.read());
+        drop(R.write());
+        drop((R.read(), R.read()));
+        drop(R.write());
+        unsafe { R.destroy(); }
+    }
+
+    #[test]
+    fn frob() {
+        static R: StaticRWLock = RWLOCK_INIT;
+        static N: uint = 10;
+        static M: uint = 1000;
+
+        let (tx, rx) = channel::<()>();
+        for _ in range(0, N) {
+            let tx = tx.clone();
+            spawn(move|| {
+                let mut rng = rand::task_rng();
+                for _ in range(0, M) {
+                    if rng.gen_weighted_bool(N) {
+                        drop(R.write());
+                    } else {
+                        drop(R.read());
+                    }
+                }
+                drop(tx);
+            });
+        }
+        drop(tx);
+        let _ = rx.recv_opt();
+        unsafe { R.destroy(); }
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_rw_arc_poison_wr() {
+        let arc = Arc::new(RWLock::new(1i));
+        let arc2 = arc.clone();
+        let _ = Thread::spawn(move|| {
+            let lock = arc2.write();
+            assert_eq!(*lock, 2);
+        }).join();
+        let lock = arc.read();
+        assert_eq!(*lock, 1);
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_rw_arc_poison_ww() {
+        let arc = Arc::new(RWLock::new(1i));
+        let arc2 = arc.clone();
+        let _ = Thread::spawn(move|| {
+            let lock = arc2.write();
+            assert_eq!(*lock, 2);
+        }).join();
+        let lock = arc.write();
+        assert_eq!(*lock, 1);
+    }
+
+    #[test]
+    fn test_rw_arc_no_poison_rr() {
+        let arc = Arc::new(RWLock::new(1i));
+        let arc2 = arc.clone();
+        let _ = Thread::spawn(move|| {
+            let lock = arc2.read();
+            assert_eq!(*lock, 2);
+        }).join();
+        let lock = arc.read();
+        assert_eq!(*lock, 1);
+    }
+    #[test]
+    fn test_rw_arc_no_poison_rw() {
+        let arc = Arc::new(RWLock::new(1i));
+        let arc2 = arc.clone();
+        let _ = Thread::spawn(move|| {
+            let lock = arc2.read();
+            assert_eq!(*lock, 2);
+        }).join();
+        let lock = arc.write();
+        assert_eq!(*lock, 1);
+    }
+
+    #[test]
+    fn test_rw_arc() {
+        let arc = Arc::new(RWLock::new(0i));
+        let arc2 = arc.clone();
+        let (tx, rx) = channel();
+
+        Thread::spawn(move|| {
+            let mut lock = arc2.write();
+            for _ in range(0u, 10) {
+                let tmp = *lock;
+                *lock = -1;
+                Thread::yield_now();
+                *lock = tmp + 1;
+            }
+            tx.send(());
+        }).detach();
+
+        // Readers try to catch the writer in the act
+        let mut children = Vec::new();
+        for _ in range(0u, 5) {
+            let arc3 = arc.clone();
+            children.push(Thread::spawn(move|| {
+                let lock = arc3.read();
+                assert!(*lock >= 0);
+            }));
+        }
+
+        // Wait for children to pass their asserts
+        for r in children.into_iter() {
+            assert!(r.join().is_ok());
+        }
+
+        // Wait for writer to finish
+        rx.recv();
+        let lock = arc.read();
+        assert_eq!(*lock, 10);
+    }
+
+    #[test]
+    fn test_rw_arc_access_in_unwind() {
+        let arc = Arc::new(RWLock::new(1i));
+        let arc2 = arc.clone();
+        let _ = Thread::spawn(move|| -> () {
+            struct Unwinder {
+                i: Arc<RWLock<int>>,
+            }
+            impl Drop for Unwinder {
+                fn drop(&mut self) {
+                    let mut lock = self.i.write();
+                    *lock += 1;
+                }
+            }
+            let _u = Unwinder { i: arc2 };
+            panic!();
+        }).join();
+        let lock = arc.read();
+        assert_eq!(*lock, 2);
+    }
+}
diff --git a/src/libstd/sync/semaphore.rs b/src/libstd/sync/semaphore.rs
new file mode 100644
index 00000000000..574b0f22bee
--- /dev/null
+++ b/src/libstd/sync/semaphore.rs
@@ -0,0 +1,195 @@
+// 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.
+
+use ops::Drop;
+use sync::{Mutex, Condvar};
+
+/// A counting, blocking, semaphore.
+///
+/// Semaphores are a form of atomic counter where access is only granted if the
+/// counter is a positive value. Each acquisition will block the calling thread
+/// until the counter is positive, and each release will increment the counter
+/// and unblock any threads if necessary.
+///
+/// # Example
+///
+/// ```
+/// use std::sync::Semaphore;
+///
+/// // Create a semaphore that represents 5 resources
+/// let sem = Semaphore::new(5);
+///
+/// // Acquire one of the resources
+/// sem.acquire();
+///
+/// // Acquire one of the resources for a limited period of time
+/// {
+///     let _guard = sem.access();
+///     // ...
+/// } // resources is released here
+///
+/// // Release our initially acquired resource
+/// sem.release();
+/// ```
+pub struct Semaphore {
+    lock: Mutex<int>,
+    cvar: Condvar,
+}
+
+/// An RAII guard which will release a resource acquired from a semaphore when
+/// dropped.
+pub struct SemaphoreGuard<'a> {
+    sem: &'a Semaphore,
+}
+
+impl Semaphore {
+    /// Creates a new semaphore with the initial count specified.
+    ///
+    /// The count specified can be thought of as a number of resources, and a
+    /// call to `acquire` or `access` will block until at least one resource is
+    /// available. It is valid to initialize a semaphore with a negative count.
+    pub fn new(count: int) -> Semaphore {
+        Semaphore {
+            lock: Mutex::new(count),
+            cvar: Condvar::new(),
+        }
+    }
+
+    /// Acquires a resource of this semaphore, blocking the current thread until
+    /// it can do so.
+    ///
+    /// This method will block until the internal count of the semaphore is at
+    /// least 1.
+    pub fn acquire(&self) {
+        let mut count = self.lock.lock();
+        while *count <= 0 {
+            self.cvar.wait(&count);
+        }
+        *count -= 1;
+    }
+
+    /// Release a resource from this semaphore.
+    ///
+    /// This will increment the number of resources in this semaphore by 1 and
+    /// will notify any pending waiters in `acquire` or `access` if necessary.
+    pub fn release(&self) {
+        *self.lock.lock() += 1;
+        self.cvar.notify_one();
+    }
+
+    /// Acquires a resource of this semaphore, returning an RAII guard to
+    /// release the semaphore when dropped.
+    ///
+    /// This function is semantically equivalent to an `acquire` followed by a
+    /// `release` when the guard returned is dropped.
+    pub fn access(&self) -> SemaphoreGuard {
+        self.acquire();
+        SemaphoreGuard { sem: self }
+    }
+}
+
+#[unsafe_destructor]
+impl<'a> Drop for SemaphoreGuard<'a> {
+    fn drop(&mut self) {
+        self.sem.release();
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use prelude::*;
+
+    use sync::Arc;
+    use super::Semaphore;
+
+    #[test]
+    fn test_sem_acquire_release() {
+        let s = Semaphore::new(1);
+        s.acquire();
+        s.release();
+        s.acquire();
+    }
+
+    #[test]
+    fn test_sem_basic() {
+        let s = Semaphore::new(1);
+        let _g = s.access();
+    }
+
+    #[test]
+    fn test_sem_as_mutex() {
+        let s = Arc::new(Semaphore::new(1));
+        let s2 = s.clone();
+        spawn(move|| {
+            let _g = s2.access();
+        });
+        let _g = s.access();
+    }
+
+    #[test]
+    fn test_sem_as_cvar() {
+        /* Child waits and parent signals */
+        let (tx, rx) = channel();
+        let s = Arc::new(Semaphore::new(0));
+        let s2 = s.clone();
+        spawn(move|| {
+            s2.acquire();
+            tx.send(());
+        });
+        s.release();
+        let _ = rx.recv();
+
+        /* Parent waits and child signals */
+        let (tx, rx) = channel();
+        let s = Arc::new(Semaphore::new(0));
+        let s2 = s.clone();
+        spawn(move|| {
+            s2.release();
+            let _ = rx.recv();
+        });
+        s.acquire();
+        tx.send(());
+    }
+
+    #[test]
+    fn test_sem_multi_resource() {
+        // Parent and child both get in the critical section at the same
+        // time, and shake hands.
+        let s = Arc::new(Semaphore::new(2));
+        let s2 = s.clone();
+        let (tx1, rx1) = channel();
+        let (tx2, rx2) = channel();
+        spawn(move|| {
+            let _g = s2.access();
+            let _ = rx2.recv();
+            tx1.send(());
+        });
+        let _g = s.access();
+        tx2.send(());
+        let _ = rx1.recv();
+    }
+
+    #[test]
+    fn test_sem_runtime_friendly_blocking() {
+        let s = Arc::new(Semaphore::new(1));
+        let s2 = s.clone();
+        let (tx, rx) = channel();
+        {
+            let _g = s.access();
+            spawn(move|| {
+                tx.send(());
+                drop(s2.access());
+                tx.send(());
+            });
+            rx.recv(); // wait for child to come alive
+        }
+        rx.recv(); // wait for child to be done
+    }
+}
diff --git a/src/libstd/sync/task_pool.rs b/src/libstd/sync/task_pool.rs
index 4ae5cd054f6..366e4b7d35b 100644
--- a/src/libstd/sync/task_pool.rs
+++ b/src/libstd/sync/task_pool.rs
@@ -12,17 +12,18 @@
 
 use core::prelude::*;
 
-use task::spawn;
+use thread::Thread;
 use comm::{channel, Sender, Receiver};
 use sync::{Arc, Mutex};
+use thunk::Thunk;
 
 struct Sentinel<'a> {
-    jobs: &'a Arc<Mutex<Receiver<proc(): Send>>>,
+    jobs: &'a Arc<Mutex<Receiver<Thunk>>>,
     active: bool
 }
 
 impl<'a> Sentinel<'a> {
-    fn new(jobs: &Arc<Mutex<Receiver<proc(): Send>>>) -> Sentinel {
+    fn new(jobs: &Arc<Mutex<Receiver<Thunk>>>) -> Sentinel {
         Sentinel {
             jobs: jobs,
             active: true
@@ -60,7 +61,7 @@ impl<'a> Drop for Sentinel<'a> {
 /// let (tx, rx) = channel();
 /// for _ in range(0, 8u) {
 ///     let tx = tx.clone();
-///     pool.execute(proc() {
+///     pool.execute(move|| {
 ///         tx.send(1u);
 ///     });
 /// }
@@ -72,7 +73,7 @@ pub struct TaskPool {
     //
     // This is the only such Sender, so when it is dropped all subtasks will
     // quit.
-    jobs: Sender<proc(): Send>
+    jobs: Sender<Thunk>
 }
 
 impl TaskPool {
@@ -84,7 +85,7 @@ impl TaskPool {
     pub fn new(tasks: uint) -> TaskPool {
         assert!(tasks >= 1);
 
-        let (tx, rx) = channel::<proc(): Send>();
+        let (tx, rx) = channel::<Thunk>();
         let rx = Arc::new(Mutex::new(rx));
 
         // Taskpool tasks.
@@ -96,13 +97,15 @@ impl TaskPool {
     }
 
     /// Executes the function `job` on a task in the pool.
-    pub fn execute(&self, job: proc():Send) {
-        self.jobs.send(job);
+    pub fn execute<F>(&self, job: F)
+        where F : FnOnce(), F : Send
+    {
+        self.jobs.send(Thunk::new(job));
     }
 }
 
-fn spawn_in_pool(jobs: Arc<Mutex<Receiver<proc(): Send>>>) {
-    spawn(proc() {
+fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk>>>) {
+    Thread::spawn(move |:| {
         // Will spawn a new task on panic unless it is cancelled.
         let sentinel = Sentinel::new(&jobs);
 
@@ -115,7 +118,7 @@ fn spawn_in_pool(jobs: Arc<Mutex<Receiver<proc(): Send>>>) {
             };
 
             match message {
-                Ok(job) => job(),
+                Ok(job) => job.invoke(()),
 
                 // The Taskpool was dropped.
                 Err(..) => break
@@ -123,15 +126,13 @@ fn spawn_in_pool(jobs: Arc<Mutex<Receiver<proc(): Send>>>) {
         }
 
         sentinel.cancel();
-    })
+    }).detach();
 }
 
 #[cfg(test)]
 mod test {
-    use core::prelude::*;
+    use prelude::*;
     use super::*;
-    use comm::channel;
-    use iter::range;
 
     const TEST_TASKS: uint = 4u;
 
@@ -144,7 +145,7 @@ mod test {
         let (tx, rx) = channel();
         for _ in range(0, TEST_TASKS) {
             let tx = tx.clone();
-            pool.execute(proc() {
+            pool.execute(move|| {
                 tx.send(1u);
             });
         }
@@ -166,14 +167,14 @@ mod test {
 
         // Panic all the existing tasks.
         for _ in range(0, TEST_TASKS) {
-            pool.execute(proc() { panic!() });
+            pool.execute(move|| -> () { panic!() });
         }
 
         // Ensure new tasks were spawned to compensate.
         let (tx, rx) = channel();
         for _ in range(0, TEST_TASKS) {
             let tx = tx.clone();
-            pool.execute(proc() {
+            pool.execute(move|| {
                 tx.send(1u);
             });
         }
@@ -191,7 +192,7 @@ mod test {
         // Panic all the existing tasks in a bit.
         for _ in range(0, TEST_TASKS) {
             let waiter = waiter.clone();
-            pool.execute(proc() {
+            pool.execute(move|| {
                 waiter.wait();
                 panic!();
             });
@@ -203,4 +204,3 @@ mod test {
         waiter.wait();
     }
 }
-
diff --git a/src/libstd/sys/common/backtrace.rs b/src/libstd/sys/common/backtrace.rs
new file mode 100644
index 00000000000..1d646eb06b1
--- /dev/null
+++ b/src/libstd/sys/common/backtrace.rs
@@ -0,0 +1,136 @@
+// 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.
+
+use prelude::*;
+
+use io::IoResult;
+
+#[cfg(target_word_size = "64")] pub const HEX_WIDTH: uint = 18;
+#[cfg(target_word_size = "32")] pub const HEX_WIDTH: uint = 10;
+
+// All rust symbols are in theory lists of "::"-separated identifiers. Some
+// assemblers, however, can't handle these characters in symbol names. To get
+// around this, we use C++-style mangling. The mangling method is:
+//
+// 1. Prefix the symbol with "_ZN"
+// 2. For each element of the path, emit the length plus the element
+// 3. End the path with "E"
+//
+// For example, "_ZN4testE" => "test" and "_ZN3foo3bar" => "foo::bar".
+//
+// We're the ones printing our backtraces, so we can't rely on anything else to
+// demangle our symbols. It's *much* nicer to look at demangled symbols, so
+// this function is implemented to give us nice pretty output.
+//
+// Note that this demangler isn't quite as fancy as it could be. We have lots
+// of other information in our symbols like hashes, version, type information,
+// etc. Additionally, this doesn't handle glue symbols at all.
+pub fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> {
+    // First validate the symbol. If it doesn't look like anything we're
+    // expecting, we just print it literally. Note that we must handle non-rust
+    // symbols because we could have any function in the backtrace.
+    let mut valid = true;
+    let mut inner = s;
+    if s.len() > 4 && s.starts_with("_ZN") && s.ends_with("E") {
+        inner = s.slice(3, s.len() - 1);
+    // On Windows, dbghelp strips leading underscores, so we accept "ZN...E" form too.
+    } else if s.len() > 3 && s.starts_with("ZN") && s.ends_with("E") {
+        inner = s.slice(2, s.len() - 1);
+    } else {
+        valid = false;
+    }
+
+    if valid {
+        let mut chars = inner.chars();
+        while valid {
+            let mut i = 0;
+            for c in chars {
+                if c.is_numeric() {
+                    i = i * 10 + c as uint - '0' as uint;
+                } else {
+                    break
+                }
+            }
+            if i == 0 {
+                valid = chars.next().is_none();
+                break
+            } else if chars.by_ref().take(i - 1).count() != i - 1 {
+                valid = false;
+            }
+        }
+    }
+
+    // Alright, let's do this.
+    if !valid {
+        try!(writer.write_str(s));
+    } else {
+        let mut first = true;
+        while inner.len() > 0 {
+            if !first {
+                try!(writer.write_str("::"));
+            } else {
+                first = false;
+            }
+            let mut rest = inner;
+            while rest.char_at(0).is_numeric() {
+                rest = rest.slice_from(1);
+            }
+            let i: uint = inner.slice_to(inner.len() - rest.len()).parse().unwrap();
+            inner = rest.slice_from(i);
+            rest = rest.slice_to(i);
+            while rest.len() > 0 {
+                if rest.starts_with("$") {
+                    macro_rules! demangle {
+                        ($($pat:expr => $demangled:expr),*) => ({
+                            $(if rest.starts_with($pat) {
+                                try!(writer.write_str($demangled));
+                                rest = rest.slice_from($pat.len());
+                              } else)*
+                            {
+                                try!(writer.write_str(rest));
+                                break;
+                            }
+
+                        })
+                    }
+
+                    // see src/librustc/back/link.rs for these mappings
+                    demangle! (
+                        "$SP$" => "@",
+                        "$UP$" => "Box",
+                        "$RP$" => "*",
+                        "$BP$" => "&",
+                        "$LT$" => "<",
+                        "$GT$" => ">",
+                        "$LP$" => "(",
+                        "$RP$" => ")",
+                        "$C$"  => ",",
+
+                        // in theory we can demangle any Unicode code point, but
+                        // for simplicity we just catch the common ones.
+                        "$x20" => " ",
+                        "$x27" => "'",
+                        "$x5b" => "[",
+                        "$x5d" => "]"
+                    )
+                } else {
+                    let idx = match rest.find('$') {
+                        None => rest.len(),
+                        Some(i) => i,
+                    };
+                    try!(writer.write_str(rest.slice_to(idx)));
+                    rest = rest.slice_from(idx);
+                }
+            }
+        }
+    }
+
+    Ok(())
+}
diff --git a/src/libstd/sys/common/condvar.rs b/src/libstd/sys/common/condvar.rs
new file mode 100644
index 00000000000..e09d9704029
--- /dev/null
+++ b/src/libstd/sys/common/condvar.rs
@@ -0,0 +1,67 @@
+// 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.
+
+use time::Duration;
+use sys_common::mutex::{mod, Mutex};
+use sys::condvar as imp;
+
+/// An OS-based condition variable.
+///
+/// This structure is the lowest layer possible on top of the OS-provided
+/// condition variables. It is consequently entirely unsafe to use. It is
+/// recommended to use the safer types at the top level of this crate instead of
+/// this type.
+pub struct Condvar(imp::Condvar);
+
+/// Static initializer for condition variables.
+pub const CONDVAR_INIT: Condvar = Condvar(imp::CONDVAR_INIT);
+
+impl Condvar {
+    /// Creates a new condition variable for use.
+    ///
+    /// Behavior is undefined if the condition variable is moved after it is
+    /// first used with any of the functions below.
+    #[inline]
+    pub unsafe fn new() -> Condvar { Condvar(imp::Condvar::new()) }
+
+    /// Signal one waiter on this condition variable to wake up.
+    #[inline]
+    pub unsafe fn notify_one(&self) { self.0.notify_one() }
+
+    /// Awaken all current waiters on this condition variable.
+    #[inline]
+    pub unsafe fn notify_all(&self) { self.0.notify_all() }
+
+    /// Wait for a signal on the specified mutex.
+    ///
+    /// Behavior is undefined if the mutex is not locked by the current thread.
+    /// Behavior is also undefined if more than one mutex is used concurrently
+    /// on this condition variable.
+    #[inline]
+    pub unsafe fn wait(&self, mutex: &Mutex) { self.0.wait(mutex::raw(mutex)) }
+
+    /// Wait for a signal on the specified mutex with a timeout duration
+    /// specified by `dur` (a relative time into the future).
+    ///
+    /// Behavior is undefined if the mutex is not locked by the current thread.
+    /// Behavior is also undefined if more than one mutex is used concurrently
+    /// on this condition variable.
+    #[inline]
+    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
+        self.0.wait_timeout(mutex::raw(mutex), dur)
+    }
+
+    /// Deallocate all resources associated with this condition variable.
+    ///
+    /// Behavior is undefined if there are current or will be future users of
+    /// this condition variable.
+    #[inline]
+    pub unsafe fn destroy(&self) { self.0.destroy() }
+}
diff --git a/src/libstd/sys/common/helper_thread.rs b/src/libstd/sys/common/helper_thread.rs
index 9508d8d9232..421778e2012 100644
--- a/src/libstd/sys/common/helper_thread.rs
+++ b/src/libstd/sys/common/helper_thread.rs
@@ -20,15 +20,15 @@
 //! can be created in the future and there must be no active timers at that
 //! time.
 
-use mem;
-use rustrt::bookkeeping;
-use rustrt::mutex::StaticNativeMutex;
-use rustrt;
+use prelude::*;
+
 use cell::UnsafeCell;
+use mem;
+use sync::{StaticMutex, StaticCondvar};
+use rt;
 use sys::helper_signal;
-use prelude::*;
 
-use task;
+use thread::Thread;
 
 /// A structure for management of a helper thread.
 ///
@@ -39,7 +39,8 @@ use task;
 /// is for static initialization.
 pub struct Helper<M> {
     /// Internal lock which protects the remaining fields
-    pub lock: StaticNativeMutex,
+    pub lock: StaticMutex,
+    pub cond: StaticCondvar,
 
     // You'll notice that the remaining fields are UnsafeCell<T>, and this is
     // because all helper thread operations are done through &self, but we need
@@ -53,6 +54,9 @@ pub struct Helper<M> {
 
     /// Flag if this helper thread has booted and been initialized yet.
     pub initialized: UnsafeCell<bool>,
+
+    /// Flag if this helper thread has shut down
+    pub shutdown: UnsafeCell<bool>,
 }
 
 impl<M: Send> Helper<M> {
@@ -65,9 +69,10 @@ impl<M: Send> Helper<M> {
     /// passed to the helper thread in a separate task.
     ///
     /// This function is safe to be called many times.
-    pub fn boot<T: Send>(&'static self,
-                         f: || -> T,
-                         helper: fn(helper_signal::signal, Receiver<M>, T)) {
+    pub fn boot<T, F>(&'static self, f: F, helper: fn(helper_signal::signal, Receiver<M>, T)) where
+        T: Send,
+        F: FnOnce() -> T,
+    {
         unsafe {
             let _guard = self.lock.lock();
             if !*self.initialized.get() {
@@ -77,13 +82,14 @@ impl<M: Send> Helper<M> {
                 *self.signal.get() = send as uint;
 
                 let t = f();
-                task::spawn(proc() {
-                    bookkeeping::decrement();
+                Thread::spawn(move |:| {
                     helper(receive, rx, t);
-                    self.lock.lock().signal()
-                });
+                    let _g = self.lock.lock();
+                    *self.shutdown.get() = true;
+                    self.cond.notify_one()
+                }).detach();
 
-                rustrt::at_exit(proc() { self.shutdown() });
+                rt::at_exit(move|:| { self.shutdown() });
                 *self.initialized.get() = true;
             }
         }
@@ -119,7 +125,9 @@ impl<M: Send> Helper<M> {
             helper_signal::signal(*self.signal.get() as helper_signal::signal);
 
             // Wait for the child to exit
-            guard.wait();
+            while !*self.shutdown.get() {
+                self.cond.wait(&guard);
+            }
             drop(guard);
 
             // Clean up after ourselves
diff --git a/src/libstd/sys/common/mod.rs b/src/libstd/sys/common/mod.rs
index cacb128faa5..dc0ad08cdbe 100644
--- a/src/libstd/sys/common/mod.rs
+++ b/src/libstd/sys/common/mod.rs
@@ -13,14 +13,22 @@
 
 use io::{mod, IoError, IoResult};
 use prelude::*;
-use sys::{last_error, retry, fs};
+use sys::{last_error, retry};
 use c_str::CString;
 use num::Int;
 use path::BytesContainer;
 use collections;
 
-pub mod net;
+pub mod backtrace;
+pub mod condvar;
 pub mod helper_thread;
+pub mod mutex;
+pub mod net;
+pub mod rwlock;
+pub mod stack;
+pub mod thread;
+pub mod thread_info;
+pub mod thread_local;
 
 // common error constructors
 
@@ -65,7 +73,9 @@ pub fn mkerr_libc<T: Int>(ret: T) -> IoResult<()> {
     }
 }
 
-pub fn keep_going(data: &[u8], f: |*const u8, uint| -> i64) -> i64 {
+pub fn keep_going<F>(data: &[u8], mut f: F) -> i64 where
+    F: FnMut(*const u8, uint) -> i64,
+{
     let origamt = data.len();
     let mut data = data.as_ptr();
     let mut amt = origamt;
@@ -83,10 +93,9 @@ pub fn keep_going(data: &[u8], f: |*const u8, uint| -> i64) -> i64 {
     return (origamt - amt) as i64;
 }
 
-// traits for extracting representations from
-
-pub trait AsFileDesc {
-    fn as_fd(&self) -> &fs::FileDesc;
+// A trait for extracting representations from std::io types
+pub trait AsInner<Inner> {
+    fn as_inner(&self) -> &Inner;
 }
 
 pub trait ProcessConfig<K: BytesContainer, V: BytesContainer> {
diff --git a/src/libstd/sys/common/mutex.rs b/src/libstd/sys/common/mutex.rs
new file mode 100644
index 00000000000..1a8a92a105a
--- /dev/null
+++ b/src/libstd/sys/common/mutex.rs
@@ -0,0 +1,62 @@
+// 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.
+
+use sys::mutex as imp;
+
+/// An OS-based mutual exclusion lock.
+///
+/// This is the thinnest cross-platform wrapper around OS mutexes. All usage of
+/// this mutex is unsafe and it is recommended to instead use the safe wrapper
+/// at the top level of the crate instead of this type.
+pub struct Mutex(imp::Mutex);
+
+/// Constant initializer for statically allocated mutexes.
+pub const MUTEX_INIT: Mutex = Mutex(imp::MUTEX_INIT);
+
+impl Mutex {
+    /// Creates a newly initialized mutex.
+    ///
+    /// Behavior is undefined if the mutex is moved after the first method is
+    /// called on the mutex.
+    #[inline]
+    pub unsafe fn new() -> Mutex { Mutex(imp::Mutex::new()) }
+
+    /// Lock the mutex blocking the current thread until it is available.
+    ///
+    /// Behavior is undefined if the mutex has been moved between this and any
+    /// previous function call.
+    #[inline]
+    pub unsafe fn lock(&self) { self.0.lock() }
+
+    /// Attempt to lock the mutex without blocking, returning whether it was
+    /// successfully acquired or not.
+    ///
+    /// Behavior is undefined if the mutex has been moved between this and any
+    /// previous function call.
+    #[inline]
+    pub unsafe fn try_lock(&self) -> bool { self.0.try_lock() }
+
+    /// Unlock the mutex.
+    ///
+    /// Behavior is undefined if the current thread does not actually hold the
+    /// mutex.
+    #[inline]
+    pub unsafe fn unlock(&self) { self.0.unlock() }
+
+    /// Deallocate all resources associated with this mutex.
+    ///
+    /// Behavior is undefined if there are current or will be future users of
+    /// this mutex.
+    #[inline]
+    pub unsafe fn destroy(&self) { self.0.destroy() }
+}
+
+// not meant to be exported to the outside world, just the containing module
+pub fn raw(mutex: &Mutex) -> &imp::Mutex { &mutex.0 }
diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs
index 029fc852742..382f6875b28 100644
--- a/src/libstd/sys/common/net.rs
+++ b/src/libstd/sys/common/net.rs
@@ -8,21 +8,21 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub use self::SocketStatus::*;
-pub use self::InAddr::*;
+use self::SocketStatus::*;
+use self::InAddr::*;
 
 use alloc::arc::Arc;
 use libc::{mod, c_char, c_int};
 use mem;
 use num::Int;
 use ptr::{mod, null, null_mut};
-use rustrt::mutex;
 use io::net::ip::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr};
 use io::net::addrinfo;
 use io::{IoResult, IoError};
 use sys::{mod, retry, c, sock_t, last_error, last_net_error, last_gai_error, close_sock,
           wrlen, msglen_t, os, wouldblock, set_nonblocking, timer, ms_to_timeval,
           decode_error_detailed};
+use sync::{Mutex, MutexGuard};
 use sys_common::{mod, keep_going, short_write, timeout};
 use prelude::*;
 use cmp;
@@ -344,10 +344,10 @@ pub fn get_host_addresses(host: Option<&str>, servname: Option<&str>,
 // [1] http://twistedmatrix.com/pipermail/twisted-commits/2012-April/034692.html
 // [2] http://stackoverflow.com/questions/19819198/does-send-msg-dontwait
 
-pub fn read<T>(fd: sock_t,
-               deadline: u64,
-               lock: || -> T,
-               read: |bool| -> libc::c_int) -> IoResult<uint> {
+pub fn read<T, L, R>(fd: sock_t, deadline: u64, mut lock: L, mut read: R) -> IoResult<uint> where
+    L: FnMut() -> T,
+    R: FnMut(bool) -> libc::c_int,
+{
     let mut ret = -1;
     if deadline == 0 {
         ret = retry(|| read(false));
@@ -386,12 +386,15 @@ pub fn read<T>(fd: sock_t,
     }
 }
 
-pub fn write<T>(fd: sock_t,
-                deadline: u64,
-                buf: &[u8],
-                write_everything: bool,
-                lock: || -> T,
-                write: |bool, *const u8, uint| -> i64) -> IoResult<uint> {
+pub fn write<T, L, W>(fd: sock_t,
+                      deadline: u64,
+                      buf: &[u8],
+                      write_everything: bool,
+                      mut lock: L,
+                      mut write: W) -> IoResult<uint> where
+    L: FnMut() -> T,
+    W: FnMut(bool, *const u8, uint) -> i64,
+{
     let mut ret = -1;
     let mut written = 0;
     if deadline == 0 {
@@ -557,12 +560,12 @@ struct Inner {
 
     // Unused on Linux, where this lock is not necessary.
     #[allow(dead_code)]
-    lock: mutex::NativeMutex
+    lock: Mutex<()>,
 }
 
 impl Inner {
     fn new(fd: sock_t) -> Inner {
-        Inner { fd: fd, lock: unsafe { mutex::NativeMutex::new() } }
+        Inner { fd: fd, lock: Mutex::new(()) }
     }
 }
 
@@ -572,7 +575,7 @@ impl Drop for Inner {
 
 pub struct Guard<'a> {
     pub fd: sock_t,
-    pub guard: mutex::LockGuard<'a>,
+    pub guard: MutexGuard<'a, ()>,
 }
 
 #[unsafe_destructor]
@@ -666,7 +669,7 @@ impl TcpStream {
     fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
         let ret = Guard {
             fd: self.fd(),
-            guard: unsafe { self.inner.lock.lock() },
+            guard: self.inner.lock.lock(),
         };
         assert!(set_nonblocking(self.fd(), true).is_ok());
         ret
@@ -674,8 +677,8 @@ impl TcpStream {
 
     pub fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
         let fd = self.fd();
-        let dolock = || self.lock_nonblocking();
-        let doread = |nb| unsafe {
+        let dolock = |&:| self.lock_nonblocking();
+        let doread = |&mut: nb| unsafe {
             let flags = if nb {c::MSG_DONTWAIT} else {0};
             libc::recv(fd,
                        buf.as_mut_ptr() as *mut libc::c_void,
@@ -687,8 +690,8 @@ impl TcpStream {
 
     pub fn write(&mut self, buf: &[u8]) -> IoResult<()> {
         let fd = self.fd();
-        let dolock = || self.lock_nonblocking();
-        let dowrite = |nb: bool, buf: *const u8, len: uint| unsafe {
+        let dolock = |&:| self.lock_nonblocking();
+        let dowrite = |&: nb: bool, buf: *const u8, len: uint| unsafe {
             let flags = if nb {c::MSG_DONTWAIT} else {0};
             libc::send(fd,
                        buf as *const _,
@@ -805,7 +808,7 @@ impl UdpSocket {
     fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
         let ret = Guard {
             fd: self.fd(),
-            guard: unsafe { self.inner.lock.lock() },
+            guard: self.inner.lock.lock(),
         };
         assert!(set_nonblocking(self.fd(), true).is_ok());
         ret
@@ -822,7 +825,7 @@ impl UdpSocket {
         let mut addrlen: libc::socklen_t =
                 mem::size_of::<libc::sockaddr_storage>() as libc::socklen_t;
 
-        let dolock = || self.lock_nonblocking();
+        let dolock = |&:| self.lock_nonblocking();
         let n = try!(read(fd, self.read_deadline, dolock, |nb| unsafe {
             let flags = if nb {c::MSG_DONTWAIT} else {0};
             libc::recvfrom(fd,
@@ -843,8 +846,8 @@ impl UdpSocket {
         let dstp = &storage as *const _ as *const libc::sockaddr;
 
         let fd = self.fd();
-        let dolock = || self.lock_nonblocking();
-        let dowrite = |nb, buf: *const u8, len: uint| unsafe {
+        let dolock = |&: | self.lock_nonblocking();
+        let dowrite = |&mut: nb, buf: *const u8, len: uint| unsafe {
             let flags = if nb {c::MSG_DONTWAIT} else {0};
             libc::sendto(fd,
                          buf as *const libc::c_void,
diff --git a/src/libstd/sys/common/rwlock.rs b/src/libstd/sys/common/rwlock.rs
new file mode 100644
index 00000000000..df016b9e293
--- /dev/null
+++ b/src/libstd/sys/common/rwlock.rs
@@ -0,0 +1,86 @@
+// 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.
+
+use sys::rwlock as imp;
+
+/// An OS-based reader-writer lock.
+///
+/// This structure is entirely unsafe and serves as the lowest layer of a
+/// cross-platform binding of system rwlocks. It is recommended to use the
+/// safer types at the top level of this crate instead of this type.
+pub struct RWLock(imp::RWLock);
+
+/// Constant initializer for static RWLocks.
+pub const RWLOCK_INIT: RWLock = RWLock(imp::RWLOCK_INIT);
+
+impl RWLock {
+    /// Creates a new instance of an RWLock.
+    ///
+    /// Usage of an RWLock is undefined if it is moved after its first use (any
+    /// function calls below).
+    #[inline]
+    pub unsafe fn new() -> RWLock { RWLock(imp::RWLock::new()) }
+
+    /// Acquire shared access to the underlying lock, blocking the current
+    /// thread to do so.
+    ///
+    /// Behavior is undefined if the rwlock has been moved between this and any
+    /// previous methodo call.
+    #[inline]
+    pub unsafe fn read(&self) { self.0.read() }
+
+    /// Attempt to acquire shared access to this lock, returning whether it
+    /// succeeded or not.
+    ///
+    /// This function does not block the current thread.
+    ///
+    /// Behavior is undefined if the rwlock has been moved between this and any
+    /// previous methodo call.
+    #[inline]
+    pub unsafe fn try_read(&self) -> bool { self.0.try_read() }
+
+    /// Acquire write access to the underlying lock, blocking the current thread
+    /// to do so.
+    ///
+    /// Behavior is undefined if the rwlock has been moved between this and any
+    /// previous methodo call.
+    #[inline]
+    pub unsafe fn write(&self) { self.0.write() }
+
+    /// Attempt to acquire exclusive access to this lock, returning whether it
+    /// succeeded or not.
+    ///
+    /// This function does not block the current thread.
+    ///
+    /// Behavior is undefined if the rwlock has been moved between this and any
+    /// previous methodo call.
+    #[inline]
+    pub unsafe fn try_write(&self) -> bool { self.0.try_write() }
+
+    /// Unlock previously acquired shared access to this lock.
+    ///
+    /// Behavior is undefined if the current thread does not have shared access.
+    #[inline]
+    pub unsafe fn read_unlock(&self) { self.0.read_unlock() }
+
+    /// Unlock previously acquired exclusive access to this lock.
+    ///
+    /// Behavior is undefined if the current thread does not currently have
+    /// exclusive access.
+    #[inline]
+    pub unsafe fn write_unlock(&self) { self.0.write_unlock() }
+
+    /// Destroy OS-related resources with this RWLock.
+    ///
+    /// Behavior is undefined if there are any currently active users of this
+    /// lock.
+    #[inline]
+    pub unsafe fn destroy(&self) { self.0.destroy() }
+}
diff --git a/src/libstd/sys/common/stack.rs b/src/libstd/sys/common/stack.rs
new file mode 100644
index 00000000000..2a88e20c8fa
--- /dev/null
+++ b/src/libstd/sys/common/stack.rs
@@ -0,0 +1,325 @@
+// Copyright 2013 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.
+
+//! Rust stack-limit management
+//!
+//! Currently Rust uses a segmented-stack-like scheme in order to detect stack
+//! overflow for rust tasks. In this scheme, the prologue of all functions are
+//! preceded with a check to see whether the current stack limits are being
+//! exceeded.
+//!
+//! This module provides the functionality necessary in order to manage these
+//! stack limits (which are stored in platform-specific locations). The
+//! functions here are used at the borders of the task lifetime in order to
+//! manage these limits.
+//!
+//! This function is an unstable module because this scheme for stack overflow
+//! detection is not guaranteed to continue in the future. Usage of this module
+//! is discouraged unless absolutely necessary.
+
+// iOS related notes
+//
+// It is possible to implement it using idea from
+// http://www.opensource.apple.com/source/Libc/Libc-825.40.1/pthreads/pthread_machdep.h
+//
+// In short: _pthread_{get,set}_specific_direct allows extremely fast
+// access, exactly what is required for segmented stack
+// There is a pool of reserved slots for Apple internal use (0..119)
+// First dynamic allocated pthread key starts with 257 (on iOS7)
+// So using slot 149 should be pretty safe ASSUMING space is reserved
+// for every key < first dynamic key
+//
+// There is also an opportunity to steal keys reserved for Garbage Collection
+// ranges 80..89 and 110..119, especially considering the fact Garbage Collection
+// never supposed to work on iOS. But as everybody knows it - there is a chance
+// that those slots will be re-used, like it happened with key 95 (moved from
+// JavaScriptCore to CoreText)
+//
+// Unfortunately Apple rejected patch to LLVM which generated
+// corresponding prolog, decision was taken to disable segmented
+// stack support on iOS.
+
+pub const RED_ZONE: uint = 20 * 1024;
+
+/// This function is invoked from rust's current __morestack function. Segmented
+/// stacks are currently not enabled as segmented stacks, but rather one giant
+/// stack segment. This means that whenever we run out of stack, we want to
+/// truly consider it to be stack overflow rather than allocating a new stack.
+#[cfg(not(test))] // in testing, use the original libstd's version
+#[lang = "stack_exhausted"]
+extern fn stack_exhausted() {
+    use intrinsics;
+
+    unsafe {
+        // We're calling this function because the stack just ran out. We need
+        // to call some other rust functions, but if we invoke the functions
+        // right now it'll just trigger this handler being called again. In
+        // order to alleviate this, we move the stack limit to be inside of the
+        // red zone that was allocated for exactly this reason.
+        let limit = get_sp_limit();
+        record_sp_limit(limit - RED_ZONE / 2);
+
+        // This probably isn't the best course of action. Ideally one would want
+        // to unwind the stack here instead of just aborting the entire process.
+        // This is a tricky problem, however. There's a few things which need to
+        // be considered:
+        //
+        //  1. We're here because of a stack overflow, yet unwinding will run
+        //     destructors and hence arbitrary code. What if that code overflows
+        //     the stack? One possibility is to use the above allocation of an
+        //     extra 10k to hope that we don't hit the limit, and if we do then
+        //     abort the whole program. Not the best, but kind of hard to deal
+        //     with unless we want to switch stacks.
+        //
+        //  2. LLVM will optimize functions based on whether they can unwind or
+        //     not. It will flag functions with 'nounwind' if it believes that
+        //     the function cannot trigger unwinding, but if we do unwind on
+        //     stack overflow then it means that we could unwind in any function
+        //     anywhere. We would have to make sure that LLVM only places the
+        //     nounwind flag on functions which don't call any other functions.
+        //
+        //  3. The function that overflowed may have owned arguments. These
+        //     arguments need to have their destructors run, but we haven't even
+        //     begun executing the function yet, so unwinding will not run the
+        //     any landing pads for these functions. If this is ignored, then
+        //     the arguments will just be leaked.
+        //
+        // Exactly what to do here is a very delicate topic, and is possibly
+        // still up in the air for what exactly to do. Some relevant issues:
+        //
+        //  #3555 - out-of-stack failure leaks arguments
+        //  #3695 - should there be a stack limit?
+        //  #9855 - possible strategies which could be taken
+        //  #9854 - unwinding on windows through __morestack has never worked
+        //  #2361 - possible implementation of not using landing pads
+
+        ::rt::util::report_overflow();
+
+        intrinsics::abort();
+    }
+}
+
+// Windows maintains a record of upper and lower stack bounds in the Thread Information
+// Block (TIB), and some syscalls do check that addresses which are supposed to be in
+// the stack, indeed lie between these two values.
+// (See https://github.com/rust-lang/rust/issues/3445#issuecomment-26114839)
+//
+// When using Rust-managed stacks (libgreen), we must maintain these values accordingly.
+// For OS-managed stacks (libnative), we let the OS manage them for us.
+//
+// On all other platforms both variants behave identically.
+
+#[inline(always)]
+pub unsafe fn record_os_managed_stack_bounds(stack_lo: uint, _stack_hi: uint) {
+    record_sp_limit(stack_lo + RED_ZONE);
+}
+
+#[inline(always)]
+pub unsafe fn record_rust_managed_stack_bounds(stack_lo: uint, stack_hi: uint) {
+    // When the old runtime had segmented stacks, it used a calculation that was
+    // "limit + RED_ZONE + FUDGE". The red zone was for things like dynamic
+    // symbol resolution, llvm function calls, etc. In theory this red zone
+    // value is 0, but it matters far less when we have gigantic stacks because
+    // we don't need to be so exact about our stack budget. The "fudge factor"
+    // was because LLVM doesn't emit a stack check for functions < 256 bytes in
+    // size. Again though, we have giant stacks, so we round all these
+    // calculations up to the nice round number of 20k.
+    record_sp_limit(stack_lo + RED_ZONE);
+
+    return target_record_stack_bounds(stack_lo, stack_hi);
+
+    #[cfg(not(windows))] #[inline(always)]
+    unsafe fn target_record_stack_bounds(_stack_lo: uint, _stack_hi: uint) {}
+
+    #[cfg(all(windows, target_arch = "x86"))] #[inline(always)]
+    unsafe fn target_record_stack_bounds(stack_lo: uint, stack_hi: uint) {
+        // stack range is at TIB: %fs:0x04 (top) and %fs:0x08 (bottom)
+        asm!("mov $0, %fs:0x04" :: "r"(stack_hi) :: "volatile");
+        asm!("mov $0, %fs:0x08" :: "r"(stack_lo) :: "volatile");
+    }
+    #[cfg(all(windows, target_arch = "x86_64"))] #[inline(always)]
+    unsafe fn target_record_stack_bounds(stack_lo: uint, stack_hi: uint) {
+        // stack range is at TIB: %gs:0x08 (top) and %gs:0x10 (bottom)
+        asm!("mov $0, %gs:0x08" :: "r"(stack_hi) :: "volatile");
+        asm!("mov $0, %gs:0x10" :: "r"(stack_lo) :: "volatile");
+    }
+}
+
+/// Records the current limit of the stack as specified by `end`.
+///
+/// This is stored in an OS-dependent location, likely inside of the thread
+/// local storage. The location that the limit is stored is a pre-ordained
+/// location because it's where LLVM has emitted code to check.
+///
+/// Note that this cannot be called under normal circumstances. This function is
+/// changing the stack limit, so upon returning any further function calls will
+/// possibly be triggering the morestack logic if you're not careful.
+///
+/// Also note that this and all of the inside functions are all flagged as
+/// "inline(always)" because they're messing around with the stack limits.  This
+/// would be unfortunate for the functions themselves to trigger a morestack
+/// invocation (if they were an actual function call).
+#[inline(always)]
+pub unsafe fn record_sp_limit(limit: uint) {
+    return target_record_sp_limit(limit);
+
+    // x86-64
+    #[cfg(all(target_arch = "x86_64",
+              any(target_os = "macos", target_os = "ios")))]
+    #[inline(always)]
+    unsafe fn target_record_sp_limit(limit: uint) {
+        asm!("movq $$0x60+90*8, %rsi
+              movq $0, %gs:(%rsi)" :: "r"(limit) : "rsi" : "volatile")
+    }
+    #[cfg(all(target_arch = "x86_64", target_os = "linux"))] #[inline(always)]
+    unsafe fn target_record_sp_limit(limit: uint) {
+        asm!("movq $0, %fs:112" :: "r"(limit) :: "volatile")
+    }
+    #[cfg(all(target_arch = "x86_64", target_os = "windows"))] #[inline(always)]
+    unsafe fn target_record_sp_limit(_: uint) {
+    }
+    #[cfg(all(target_arch = "x86_64", target_os = "freebsd"))] #[inline(always)]
+    unsafe fn target_record_sp_limit(limit: uint) {
+        asm!("movq $0, %fs:24" :: "r"(limit) :: "volatile")
+    }
+    #[cfg(all(target_arch = "x86_64", target_os = "dragonfly"))] #[inline(always)]
+    unsafe fn target_record_sp_limit(limit: uint) {
+        asm!("movq $0, %fs:32" :: "r"(limit) :: "volatile")
+    }
+
+    // x86
+    #[cfg(all(target_arch = "x86",
+              any(target_os = "macos", target_os = "ios")))]
+    #[inline(always)]
+    unsafe fn target_record_sp_limit(limit: uint) {
+        asm!("movl $$0x48+90*4, %eax
+              movl $0, %gs:(%eax)" :: "r"(limit) : "eax" : "volatile")
+    }
+    #[cfg(all(target_arch = "x86",
+              any(target_os = "linux", target_os = "freebsd")))]
+    #[inline(always)]
+    unsafe fn target_record_sp_limit(limit: uint) {
+        asm!("movl $0, %gs:48" :: "r"(limit) :: "volatile")
+    }
+    #[cfg(all(target_arch = "x86", target_os = "windows"))] #[inline(always)]
+    unsafe fn target_record_sp_limit(_: uint) {
+    }
+
+    // mips, arm - Some brave soul can port these to inline asm, but it's over
+    //             my head personally
+    #[cfg(any(target_arch = "mips",
+              target_arch = "mipsel",
+              all(target_arch = "arm", not(target_os = "ios"))))]
+    #[inline(always)]
+    unsafe fn target_record_sp_limit(limit: uint) {
+        use libc::c_void;
+        return record_sp_limit(limit as *const c_void);
+        extern {
+            fn record_sp_limit(limit: *const c_void);
+        }
+    }
+
+    // iOS segmented stack is disabled for now, see related notes
+    #[cfg(all(target_arch = "arm", target_os = "ios"))] #[inline(always)]
+    unsafe fn target_record_sp_limit(_: uint) {
+    }
+}
+
+/// The counterpart of the function above, this function will fetch the current
+/// stack limit stored in TLS.
+///
+/// Note that all of these functions are meant to be exact counterparts of their
+/// brethren above, except that the operands are reversed.
+///
+/// As with the setter, this function does not have a __morestack header and can
+/// therefore be called in a "we're out of stack" situation.
+#[inline(always)]
+pub unsafe fn get_sp_limit() -> uint {
+    return target_get_sp_limit();
+
+    // x86-64
+    #[cfg(all(target_arch = "x86_64",
+              any(target_os = "macos", target_os = "ios")))]
+    #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        let limit;
+        asm!("movq $$0x60+90*8, %rsi
+              movq %gs:(%rsi), $0" : "=r"(limit) :: "rsi" : "volatile");
+        return limit;
+    }
+    #[cfg(all(target_arch = "x86_64", target_os = "linux"))] #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        let limit;
+        asm!("movq %fs:112, $0" : "=r"(limit) ::: "volatile");
+        return limit;
+    }
+    #[cfg(all(target_arch = "x86_64", target_os = "windows"))] #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        return 1024;
+    }
+    #[cfg(all(target_arch = "x86_64", target_os = "freebsd"))] #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        let limit;
+        asm!("movq %fs:24, $0" : "=r"(limit) ::: "volatile");
+        return limit;
+    }
+    #[cfg(all(target_arch = "x86_64", target_os = "dragonfly"))] #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        let limit;
+        asm!("movq %fs:32, $0" : "=r"(limit) ::: "volatile");
+        return limit;
+    }
+
+
+    // x86
+    #[cfg(all(target_arch = "x86",
+              any(target_os = "macos", target_os = "ios")))]
+    #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        let limit;
+        asm!("movl $$0x48+90*4, %eax
+              movl %gs:(%eax), $0" : "=r"(limit) :: "eax" : "volatile");
+        return limit;
+    }
+    #[cfg(all(target_arch = "x86",
+              any(target_os = "linux", target_os = "freebsd")))]
+    #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        let limit;
+        asm!("movl %gs:48, $0" : "=r"(limit) ::: "volatile");
+        return limit;
+    }
+    #[cfg(all(target_arch = "x86", target_os = "windows"))] #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        return 1024;
+    }
+
+    // mips, arm - Some brave soul can port these to inline asm, but it's over
+    //             my head personally
+    #[cfg(any(target_arch = "mips",
+              target_arch = "mipsel",
+              all(target_arch = "arm", not(target_os = "ios"))))]
+    #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        use libc::c_void;
+        return get_sp_limit() as uint;
+        extern {
+            fn get_sp_limit() -> *const c_void;
+        }
+    }
+
+    // iOS doesn't support segmented stacks yet. This function might
+    // be called by runtime though so it is unsafe to mark it as
+    // unreachable, let's return a fixed constant.
+    #[cfg(all(target_arch = "arm", target_os = "ios"))] #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        1024
+    }
+}
diff --git a/src/libstd/sys/common/thread.rs b/src/libstd/sys/common/thread.rs
new file mode 100644
index 00000000000..048e33399a3
--- /dev/null
+++ b/src/libstd/sys/common/thread.rs
@@ -0,0 +1,35 @@
+// 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.
+
+use core::prelude::*;
+
+use boxed::Box;
+use mem;
+use uint;
+use libc;
+use thunk::Thunk;
+use sys_common::stack;
+use sys::{thread, stack_overflow};
+
+// This is the starting point of rust os threads. The first thing we do
+// is make sure that we don't trigger __morestack (also why this has a
+// no_stack_check annotation), and then we extract the main function
+// and invoke it.
+#[no_stack_check]
+pub fn start_thread(main: *mut libc::c_void) -> thread::rust_thread_return {
+    unsafe {
+        stack::record_os_managed_stack_bounds(0, uint::MAX);
+        let handler = stack_overflow::Handler::new();
+        let f: Box<Thunk> = mem::transmute(main);
+        f.invoke(());
+        drop(handler);
+        mem::transmute(0 as thread::rust_thread_return)
+    }
+}
diff --git a/src/libstd/sys/common/thread_info.rs b/src/libstd/sys/common/thread_info.rs
new file mode 100644
index 00000000000..dc21feb17a8
--- /dev/null
+++ b/src/libstd/sys/common/thread_info.rs
@@ -0,0 +1,68 @@
+// 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.
+
+use core::prelude::*;
+
+use thread::Thread;
+use cell::RefCell;
+use string::String;
+
+struct ThreadInfo {
+    // This field holds the known bounds of the stack in (lo, hi)
+    // form. Not all threads necessarily know their precise bounds,
+    // hence this is optional.
+    stack_bounds: (uint, uint),
+    stack_guard: uint,
+    thread: Thread,
+}
+
+thread_local! { static THREAD_INFO: RefCell<Option<ThreadInfo>> = RefCell::new(None) }
+
+impl ThreadInfo {
+    fn with<R>(f: |&mut ThreadInfo| -> R) -> R {
+        if THREAD_INFO.destroyed() {
+            panic!("Use of std::thread::Thread::current() is not possible after \
+                    the thread's local data has been destroyed");
+        }
+
+        THREAD_INFO.with(|c| {
+            if c.borrow().is_none() {
+                *c.borrow_mut() = Some(ThreadInfo {
+                    stack_bounds: (0, 0),
+                    stack_guard: 0,
+                    thread: NewThread::new(None),
+                })
+            }
+            f(c.borrow_mut().as_mut().unwrap())
+        })
+    }
+}
+
+pub fn current_thread() -> Thread {
+    ThreadInfo::with(|info| info.thread.clone())
+}
+
+pub fn stack_guard() -> uint {
+    ThreadInfo::with(|info| info.stack_guard)
+}
+
+pub fn set(stack_bounds: (uint, uint), stack_guard: uint, thread: Thread) {
+    THREAD_INFO.with(|c| assert!(c.borrow().is_none()));
+    THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{
+        stack_bounds: stack_bounds,
+        stack_guard: stack_guard,
+        thread: thread,
+    }));
+}
+
+// a hack to get around privacy restrictions; implemented by `std::thread::Thread`
+pub trait NewThread {
+    fn new(name: Option<String>) -> Self;
+}
diff --git a/src/libstd/sys/common/thread_local.rs b/src/libstd/sys/common/thread_local.rs
new file mode 100644
index 00000000000..fe7a7d8d037
--- /dev/null
+++ b/src/libstd/sys/common/thread_local.rs
@@ -0,0 +1,284 @@
+// 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.
+
+//! OS-based thread local storage
+//!
+//! This module provides an implementation of OS-based thread local storage,
+//! using the native OS-provided facilities (think `TlsAlloc` or
+//! `pthread_setspecific`). The interface of this differs from the other types
+//! of thread-local-storage provided in this crate in that OS-based TLS can only
+//! get/set pointers,
+//!
+//! This module also provides two flavors of TLS. One is intended for static
+//! initialization, and does not contain a `Drop` implementation to deallocate
+//! the OS-TLS key. The other is a type which does implement `Drop` and hence
+//! has a safe interface.
+//!
+//! # Usage
+//!
+//! This module should likely not be used directly unless other primitives are
+//! being built on. types such as `thread_local::scoped::Key` are likely much
+//! more useful in practice than this OS-based version which likely requires
+//! unsafe code to interoperate with.
+//!
+//! # Example
+//!
+//! Using a dynamically allocated TLS key. Note that this key can be shared
+//! among many threads via an `Arc`.
+//!
+//! ```rust,ignore
+//! let key = Key::new(None);
+//! assert!(key.get().is_null());
+//! key.set(1 as *mut u8);
+//! assert!(!key.get().is_null());
+//!
+//! drop(key); // deallocate this TLS slot.
+//! ```
+//!
+//! Sometimes a statically allocated key is either required or easier to work
+//! with, however.
+//!
+//! ```rust,ignore
+//! static KEY: StaticKey = INIT;
+//!
+//! unsafe {
+//!     assert!(KEY.get().is_null());
+//!     KEY.set(1 as *mut u8);
+//! }
+//! ```
+
+#![allow(non_camel_case_types)]
+
+use prelude::*;
+
+use sync::atomic::{mod, AtomicUint};
+use sync::{Mutex, Once, ONCE_INIT};
+
+use sys::thread_local as imp;
+
+/// A type for TLS keys that are statically allocated.
+///
+/// This type is entirely `unsafe` to use as it does not protect against
+/// use-after-deallocation or use-during-deallocation.
+///
+/// The actual OS-TLS key is lazily allocated when this is used for the first
+/// time. The key is also deallocated when the Rust runtime exits or `destroy`
+/// is called, whichever comes first.
+///
+/// # Example
+///
+/// ```ignore
+/// use tls::os::{StaticKey, INIT};
+///
+/// static KEY: StaticKey = INIT;
+///
+/// unsafe {
+///     assert!(KEY.get().is_null());
+///     KEY.set(1 as *mut u8);
+/// }
+/// ```
+pub struct StaticKey {
+    /// Inner static TLS key (internals), created with by `INIT_INNER` in this
+    /// module.
+    pub inner: StaticKeyInner,
+    /// Destructor for the TLS value.
+    ///
+    /// See `Key::new` for information about when the destructor runs and how
+    /// it runs.
+    pub dtor: Option<unsafe extern fn(*mut u8)>,
+}
+
+/// Inner contents of `StaticKey`, created by the `INIT_INNER` constant.
+pub struct StaticKeyInner {
+    key: AtomicUint,
+}
+
+/// A type for a safely managed OS-based TLS slot.
+///
+/// This type allocates an OS TLS key when it is initialized and will deallocate
+/// the key when it falls out of scope. When compared with `StaticKey`, this
+/// type is entirely safe to use.
+///
+/// Implementations will likely, however, contain unsafe code as this type only
+/// operates on `*mut u8`, an unsafe pointer.
+///
+/// # Example
+///
+/// ```rust,ignore
+/// use tls::os::Key;
+///
+/// let key = Key::new(None);
+/// assert!(key.get().is_null());
+/// key.set(1 as *mut u8);
+/// assert!(!key.get().is_null());
+///
+/// drop(key); // deallocate this TLS slot.
+/// ```
+pub struct Key {
+    key: imp::Key,
+}
+
+/// Constant initialization value for static TLS keys.
+///
+/// This value specifies no destructor by default.
+pub const INIT: StaticKey = StaticKey {
+    inner: INIT_INNER,
+    dtor: None,
+};
+
+/// Constant initialization value for the inner part of static TLS keys.
+///
+/// This value allows specific configuration of the destructor for a TLS key.
+pub const INIT_INNER: StaticKeyInner = StaticKeyInner {
+    key: atomic::INIT_ATOMIC_UINT,
+};
+
+static INIT_KEYS: Once = ONCE_INIT;
+static mut KEYS: *mut Mutex<Vec<imp::Key>> = 0 as *mut _;
+
+impl StaticKey {
+    /// Gets the value associated with this TLS key
+    ///
+    /// This will lazily allocate a TLS key from the OS if one has not already
+    /// been allocated.
+    #[inline]
+    pub unsafe fn get(&self) -> *mut u8 { imp::get(self.key()) }
+
+    /// Sets this TLS key to a new value.
+    ///
+    /// This will lazily allocate a TLS key from the OS if one has not already
+    /// been allocated.
+    #[inline]
+    pub unsafe fn set(&self, val: *mut u8) { imp::set(self.key(), val) }
+
+    /// Deallocates this OS TLS key.
+    ///
+    /// This function is unsafe as there is no guarantee that the key is not
+    /// currently in use by other threads or will not ever be used again.
+    ///
+    /// Note that this does *not* run the user-provided destructor if one was
+    /// specified at definition time. Doing so must be done manually.
+    pub unsafe fn destroy(&self) {
+        match self.inner.key.swap(0, atomic::SeqCst) {
+            0 => {}
+            n => { imp::destroy(n as imp::Key) }
+        }
+    }
+
+    #[inline]
+    unsafe fn key(&self) -> imp::Key {
+        match self.inner.key.load(atomic::Relaxed) {
+            0 => self.lazy_init() as imp::Key,
+            n => n as imp::Key
+        }
+    }
+
+    unsafe fn lazy_init(&self) -> uint {
+        // POSIX allows the key created here to be 0, but the compare_and_swap
+        // below relies on using 0 as a sentinel value to check who won the
+        // race to set the shared TLS key. As far as I know, there is no
+        // guaranteed value that cannot be returned as a posix_key_create key,
+        // so there is no value we can initialize the inner key with to
+        // prove that it has not yet been set. As such, we'll continue using a
+        // value of 0, but with some gyrations to make sure we have a non-0
+        // value returned from the creation routine.
+        // FIXME: this is clearly a hack, and should be cleaned up.
+        let key1 = imp::create(self.dtor);
+        let key = if key1 != 0 {
+            key1
+        } else {
+            let key2 = imp::create(self.dtor);
+            imp::destroy(key1);
+            key2
+        };
+        assert!(key != 0);
+        match self.inner.key.compare_and_swap(0, key as uint, atomic::SeqCst) {
+            // The CAS succeeded, so we've created the actual key
+            0 => key as uint,
+            // If someone beat us to the punch, use their key instead
+            n => { imp::destroy(key); n }
+        }
+    }
+}
+
+impl Key {
+    /// Create a new managed OS TLS key.
+    ///
+    /// This key will be deallocated when the key falls out of scope.
+    ///
+    /// The argument provided is an optionally-specified destructor for the
+    /// value of this TLS key. When a thread exits and the value for this key
+    /// is non-null the destructor will be invoked. The TLS value will be reset
+    /// to null before the destructor is invoked.
+    ///
+    /// Note that the destructor will not be run when the `Key` goes out of
+    /// scope.
+    #[inline]
+    pub fn new(dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
+        Key { key: unsafe { imp::create(dtor) } }
+    }
+
+    /// See StaticKey::get
+    #[inline]
+    pub fn get(&self) -> *mut u8 {
+        unsafe { imp::get(self.key) }
+    }
+
+    /// See StaticKey::set
+    #[inline]
+    pub fn set(&self, val: *mut u8) {
+        unsafe { imp::set(self.key, val) }
+    }
+}
+
+impl Drop for Key {
+    fn drop(&mut self) {
+        unsafe { imp::destroy(self.key) }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use prelude::*;
+    use super::{Key, StaticKey, INIT_INNER};
+
+    fn assert_sync<T: Sync>() {}
+    fn assert_send<T: Send>() {}
+
+    #[test]
+    fn smoke() {
+        assert_sync::<Key>();
+        assert_send::<Key>();
+
+        let k1 = Key::new(None);
+        let k2 = Key::new(None);
+        assert!(k1.get().is_null());
+        assert!(k2.get().is_null());
+        k1.set(1 as *mut _);
+        k2.set(2 as *mut _);
+        assert_eq!(k1.get() as uint, 1);
+        assert_eq!(k2.get() as uint, 2);
+    }
+
+    #[test]
+    fn statik() {
+        static K1: StaticKey = StaticKey { inner: INIT_INNER, dtor: None };
+        static K2: StaticKey = StaticKey { inner: INIT_INNER, dtor: None };
+
+        unsafe {
+            assert!(K1.get().is_null());
+            assert!(K2.get().is_null());
+            K1.set(1 as *mut _);
+            K2.set(2 as *mut _);
+            assert_eq!(K1.get() as uint, 1);
+            assert_eq!(K2.get() as uint, 2);
+        }
+    }
+}
diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs
new file mode 100644
index 00000000000..983d0e5fa14
--- /dev/null
+++ b/src/libstd/sys/unix/backtrace.rs
@@ -0,0 +1,493 @@
+// 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.
+
+/// Backtrace support built on libgcc with some extra OS-specific support
+///
+/// Some methods of getting a backtrace:
+///
+/// * The backtrace() functions on unix. It turns out this doesn't work very
+///   well for green threads on OSX, and the address to symbol portion of it
+///   suffers problems that are described below.
+///
+/// * Using libunwind. This is more difficult than it sounds because libunwind
+///   isn't installed everywhere by default. It's also a bit of a hefty library,
+///   so possibly not the best option. When testing, libunwind was excellent at
+///   getting both accurate backtraces and accurate symbols across platforms.
+///   This route was not chosen in favor of the next option, however.
+///
+/// * We're already using libgcc_s for exceptions in rust (triggering task
+///   unwinding and running destructors on the stack), and it turns out that it
+///   conveniently comes with a function that also gives us a backtrace. All of
+///   these functions look like _Unwind_*, but it's not quite the full
+///   repertoire of the libunwind API. Due to it already being in use, this was
+///   the chosen route of getting a backtrace.
+///
+/// After choosing libgcc_s for backtraces, the sad part is that it will only
+/// give us a stack trace of instruction pointers. Thankfully these instruction
+/// pointers are accurate (they work for green and native threads), but it's
+/// then up to us again to figure out how to translate these addresses to
+/// symbols. As with before, we have a few options. Before, that, a little bit
+/// of an interlude about symbols. This is my very limited knowledge about
+/// symbol tables, and this information is likely slightly wrong, but the
+/// general idea should be correct.
+///
+/// When talking about symbols, it's helpful to know a few things about where
+/// symbols are located. Some symbols are located in the dynamic symbol table
+/// of the executable which in theory means that they're available for dynamic
+/// linking and lookup. Other symbols end up only in the local symbol table of
+/// the file. This loosely corresponds to pub and priv functions in Rust.
+///
+/// Armed with this knowledge, we know that our solution for address to symbol
+/// translation will need to consult both the local and dynamic symbol tables.
+/// With that in mind, here's our options of translating an address to
+/// a symbol.
+///
+/// * Use dladdr(). The original backtrace()-based idea actually uses dladdr()
+///   behind the scenes to translate, and this is why backtrace() was not used.
+///   Conveniently, this method works fantastically on OSX. It appears dladdr()
+///   uses magic to consult the local symbol table, or we're putting everything
+///   in the dynamic symbol table anyway. Regardless, for OSX, this is the
+///   method used for translation. It's provided by the system and easy to do.o
+///
+///   Sadly, all other systems have a dladdr() implementation that does not
+///   consult the local symbol table. This means that most functions are blank
+///   because they don't have symbols. This means that we need another solution.
+///
+/// * Use unw_get_proc_name(). This is part of the libunwind api (not the
+///   libgcc_s version of the libunwind api), but involves taking a dependency
+///   to libunwind. We may pursue this route in the future if we bundle
+///   libunwind, but libunwind was unwieldy enough that it was not chosen at
+///   this time to provide this functionality.
+///
+/// * Shell out to a utility like `readelf`. Crazy though it may sound, it's a
+///   semi-reasonable solution. The stdlib already knows how to spawn processes,
+///   so in theory it could invoke readelf, parse the output, and consult the
+///   local/dynamic symbol tables from there. This ended up not getting chosen
+///   due to the craziness of the idea plus the advent of the next option.
+///
+/// * Use `libbacktrace`. It turns out that this is a small library bundled in
+///   the gcc repository which provides backtrace and symbol translation
+///   functionality. All we really need from it is the backtrace functionality,
+///   and we only really need this on everything that's not OSX, so this is the
+///   chosen route for now.
+///
+/// In summary, the current situation uses libgcc_s to get a trace of stack
+/// pointers, and we use dladdr() or libbacktrace to translate these addresses
+/// to symbols. This is a bit of a hokey implementation as-is, but it works for
+/// all unix platforms we support right now, so it at least gets the job done.
+
+use c_str::CString;
+use io::{IoResult, Writer};
+use libc;
+use mem;
+use option::Option::{mod, Some, None};
+use result::Result::{Ok, Err};
+use sync::{StaticMutex, MUTEX_INIT};
+
+use sys_common::backtrace::*;
+
+/// As always - iOS on arm uses SjLj exceptions and
+/// _Unwind_Backtrace is even not available there. Still,
+/// backtraces could be extracted using a backtrace function,
+/// which thanks god is public
+///
+/// As mentioned in a huge comment block above, backtrace doesn't
+/// play well with green threads, so while it is extremely nice
+/// and simple to use it should be used only on iOS devices as the
+/// only viable option.
+#[cfg(all(target_os = "ios", target_arch = "arm"))]
+#[inline(never)]
+pub fn write(w: &mut Writer) -> IoResult<()> {
+    use iter::{IteratorExt, range};
+    use result;
+    use slice::SliceExt;
+
+    extern {
+        fn backtrace(buf: *mut *mut libc::c_void,
+                     sz: libc::c_int) -> libc::c_int;
+    }
+
+    // while it doesn't requires lock for work as everything is
+    // local, it still displays much nicer backtraces when a
+    // couple of tasks panic simultaneously
+    static LOCK: StaticMutex = MUTEX_INIT;
+    let _g = unsafe { LOCK.lock() };
+
+    try!(writeln!(w, "stack backtrace:"));
+    // 100 lines should be enough
+    const SIZE: uint = 100;
+    let mut buf: [*mut libc::c_void, ..SIZE] = unsafe {mem::zeroed()};
+    let cnt = unsafe { backtrace(buf.as_mut_ptr(), SIZE as libc::c_int) as uint};
+
+    // skipping the first one as it is write itself
+    let iter = range(1, cnt).map(|i| {
+        print(w, i as int, buf[i])
+    });
+    result::fold(iter, (), |_, _| ())
+}
+
+#[cfg(not(all(target_os = "ios", target_arch = "arm")))]
+#[inline(never)] // if we know this is a function call, we can skip it when
+                 // tracing
+pub fn write(w: &mut Writer) -> IoResult<()> {
+    use io::IoError;
+
+    struct Context<'a> {
+        idx: int,
+        writer: &'a mut (Writer+'a),
+        last_error: Option<IoError>,
+    }
+
+    // When using libbacktrace, we use some necessary global state, so we
+    // need to prevent more than one thread from entering this block. This
+    // is semi-reasonable in terms of printing anyway, and we know that all
+    // I/O done here is blocking I/O, not green I/O, so we don't have to
+    // worry about this being a native vs green mutex.
+    static LOCK: StaticMutex = MUTEX_INIT;
+    let _g = unsafe { LOCK.lock() };
+
+    try!(writeln!(w, "stack backtrace:"));
+
+    let mut cx = Context { writer: w, last_error: None, idx: 0 };
+    return match unsafe {
+        uw::_Unwind_Backtrace(trace_fn,
+                              &mut cx as *mut Context as *mut libc::c_void)
+    } {
+        uw::_URC_NO_REASON => {
+            match cx.last_error {
+                Some(err) => Err(err),
+                None => Ok(())
+            }
+        }
+        _ => Ok(()),
+    };
+
+    extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
+                       arg: *mut libc::c_void) -> uw::_Unwind_Reason_Code {
+        let cx: &mut Context = unsafe { mem::transmute(arg) };
+        let ip = unsafe { uw::_Unwind_GetIP(ctx) as *mut libc::c_void };
+        // dladdr() on osx gets whiny when we use FindEnclosingFunction, and
+        // it appears to work fine without it, so we only use
+        // FindEnclosingFunction on non-osx platforms. In doing so, we get a
+        // slightly more accurate stack trace in the process.
+        //
+        // This is often because panic involves the last instruction of a
+        // function being "call std::rt::begin_unwind", with no ret
+        // instructions after it. This means that the return instruction
+        // pointer points *outside* of the calling function, and by
+        // unwinding it we go back to the original function.
+        let ip = if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
+            ip
+        } else {
+            unsafe { uw::_Unwind_FindEnclosingFunction(ip) }
+        };
+
+        // Don't print out the first few frames (they're not user frames)
+        cx.idx += 1;
+        if cx.idx <= 0 { return uw::_URC_NO_REASON }
+        // Don't print ginormous backtraces
+        if cx.idx > 100 {
+            match write!(cx.writer, " ... <frames omitted>\n") {
+                Ok(()) => {}
+                Err(e) => { cx.last_error = Some(e); }
+            }
+            return uw::_URC_FAILURE
+        }
+
+        // Once we hit an error, stop trying to print more frames
+        if cx.last_error.is_some() { return uw::_URC_FAILURE }
+
+        match print(cx.writer, cx.idx, ip) {
+            Ok(()) => {}
+            Err(e) => { cx.last_error = Some(e); }
+        }
+
+        // keep going
+        return uw::_URC_NO_REASON
+    }
+}
+
+#[cfg(any(target_os = "macos", target_os = "ios"))]
+fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
+    use intrinsics;
+    #[repr(C)]
+    struct Dl_info {
+        dli_fname: *const libc::c_char,
+        dli_fbase: *mut libc::c_void,
+        dli_sname: *const libc::c_char,
+        dli_saddr: *mut libc::c_void,
+    }
+    extern {
+        fn dladdr(addr: *const libc::c_void,
+                  info: *mut Dl_info) -> libc::c_int;
+    }
+
+    let mut info: Dl_info = unsafe { intrinsics::init() };
+    if unsafe { dladdr(addr as *const libc::c_void, &mut info) == 0 } {
+        output(w, idx,addr, None)
+    } else {
+        output(w, idx, addr, Some(unsafe {
+            CString::new(info.dli_sname, false)
+        }))
+    }
+}
+
+#[cfg(not(any(target_os = "macos", target_os = "ios")))]
+fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
+    use iter::{Iterator, IteratorExt};
+    use os;
+    use path::GenericPath;
+    use ptr::RawPtr;
+    use ptr;
+    use slice::SliceExt;
+
+    ////////////////////////////////////////////////////////////////////////
+    // libbacktrace.h API
+    ////////////////////////////////////////////////////////////////////////
+    type backtrace_syminfo_callback =
+        extern "C" fn(data: *mut libc::c_void,
+                      pc: libc::uintptr_t,
+                      symname: *const libc::c_char,
+                      symval: libc::uintptr_t,
+                      symsize: libc::uintptr_t);
+    type backtrace_error_callback =
+        extern "C" fn(data: *mut libc::c_void,
+                      msg: *const libc::c_char,
+                      errnum: libc::c_int);
+    enum backtrace_state {}
+    #[link(name = "backtrace", kind = "static")]
+    #[cfg(not(test))]
+    extern {}
+
+    extern {
+        fn backtrace_create_state(filename: *const libc::c_char,
+                                  threaded: libc::c_int,
+                                  error: backtrace_error_callback,
+                                  data: *mut libc::c_void)
+                                        -> *mut backtrace_state;
+        fn backtrace_syminfo(state: *mut backtrace_state,
+                             addr: libc::uintptr_t,
+                             cb: backtrace_syminfo_callback,
+                             error: backtrace_error_callback,
+                             data: *mut libc::c_void) -> libc::c_int;
+    }
+
+    ////////////////////////////////////////////////////////////////////////
+    // helper callbacks
+    ////////////////////////////////////////////////////////////////////////
+
+    extern fn error_cb(_data: *mut libc::c_void, _msg: *const libc::c_char,
+                       _errnum: libc::c_int) {
+        // do nothing for now
+    }
+    extern fn syminfo_cb(data: *mut libc::c_void,
+                         _pc: libc::uintptr_t,
+                         symname: *const libc::c_char,
+                         _symval: libc::uintptr_t,
+                         _symsize: libc::uintptr_t) {
+        let slot = data as *mut *const libc::c_char;
+        unsafe { *slot = symname; }
+    }
+
+    // The libbacktrace API supports creating a state, but it does not
+    // support destroying a state. I personally take this to mean that a
+    // state is meant to be created and then live forever.
+    //
+    // I would love to register an at_exit() handler which cleans up this
+    // state, but libbacktrace provides no way to do so.
+    //
+    // With these constraints, this function has a statically cached state
+    // that is calculated the first time this is requested. Remember that
+    // backtracing all happens serially (one global lock).
+    //
+    // An additionally oddity in this function is that we initialize the
+    // filename via self_exe_name() to pass to libbacktrace. It turns out
+    // that on Linux libbacktrace seamlessly gets the filename of the
+    // current executable, but this fails on freebsd. by always providing
+    // it, we make sure that libbacktrace never has a reason to not look up
+    // the symbols. The libbacktrace API also states that the filename must
+    // be in "permanent memory", so we copy it to a static and then use the
+    // static as the pointer.
+    //
+    // FIXME: We also call self_exe_name() on DragonFly BSD. I haven't
+    //        tested if this is required or not.
+    unsafe fn init_state() -> *mut backtrace_state {
+        static mut STATE: *mut backtrace_state = 0 as *mut backtrace_state;
+        static mut LAST_FILENAME: [libc::c_char, ..256] = [0, ..256];
+        if !STATE.is_null() { return STATE }
+        let selfname = if cfg!(target_os = "freebsd") ||
+                          cfg!(target_os = "dragonfly") {
+            os::self_exe_name()
+        } else {
+            None
+        };
+        let filename = match selfname {
+            Some(path) => {
+                let bytes = path.as_vec();
+                if bytes.len() < LAST_FILENAME.len() {
+                    let i = bytes.iter();
+                    for (slot, val) in LAST_FILENAME.iter_mut().zip(i) {
+                        *slot = *val as libc::c_char;
+                    }
+                    LAST_FILENAME.as_ptr()
+                } else {
+                    ptr::null()
+                }
+            }
+            None => ptr::null(),
+        };
+        STATE = backtrace_create_state(filename, 0, error_cb,
+                                       ptr::null_mut());
+        return STATE
+    }
+
+    ////////////////////////////////////////////////////////////////////////
+    // translation
+    ////////////////////////////////////////////////////////////////////////
+
+    // backtrace errors are currently swept under the rug, only I/O
+    // errors are reported
+    let state = unsafe { init_state() };
+    if state.is_null() {
+        return output(w, idx, addr, None)
+    }
+    let mut data = 0 as *const libc::c_char;
+    let data_addr = &mut data as *mut *const libc::c_char;
+    let ret = unsafe {
+        backtrace_syminfo(state, addr as libc::uintptr_t,
+                          syminfo_cb, error_cb,
+                          data_addr as *mut libc::c_void)
+    };
+    if ret == 0 || data.is_null() {
+        output(w, idx, addr, None)
+    } else {
+        output(w, idx, addr, Some(unsafe { CString::new(data, false) }))
+    }
+}
+
+// Finally, after all that work above, we can emit a symbol.
+fn output(w: &mut Writer, idx: int, addr: *mut libc::c_void,
+          s: Option<CString>) -> IoResult<()> {
+    try!(write!(w, "  {:2}: {:2$} - ", idx, addr, HEX_WIDTH));
+    match s.as_ref().and_then(|c| c.as_str()) {
+        Some(string) => try!(demangle(w, string)),
+        None => try!(write!(w, "<unknown>")),
+    }
+    w.write(&['\n' as u8])
+}
+
+/// Unwind library interface used for backtraces
+///
+/// Note that dead code is allowed as here are just bindings
+/// iOS doesn't use all of them it but adding more
+/// platform-specific configs pollutes the code too much
+#[allow(non_camel_case_types)]
+#[allow(non_snake_case)]
+#[allow(dead_code)]
+mod uw {
+    pub use self::_Unwind_Reason_Code::*;
+
+    use libc;
+
+    #[repr(C)]
+    pub enum _Unwind_Reason_Code {
+        _URC_NO_REASON = 0,
+        _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
+        _URC_FATAL_PHASE2_ERROR = 2,
+        _URC_FATAL_PHASE1_ERROR = 3,
+        _URC_NORMAL_STOP = 4,
+        _URC_END_OF_STACK = 5,
+        _URC_HANDLER_FOUND = 6,
+        _URC_INSTALL_CONTEXT = 7,
+        _URC_CONTINUE_UNWIND = 8,
+        _URC_FAILURE = 9, // used only by ARM EABI
+    }
+
+    pub enum _Unwind_Context {}
+
+    pub type _Unwind_Trace_Fn =
+            extern fn(ctx: *mut _Unwind_Context,
+                      arg: *mut libc::c_void) -> _Unwind_Reason_Code;
+
+    extern {
+        // No native _Unwind_Backtrace on iOS
+        #[cfg(not(all(target_os = "ios", target_arch = "arm")))]
+        pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
+                                 trace_argument: *mut libc::c_void)
+                    -> _Unwind_Reason_Code;
+
+        #[cfg(all(not(target_os = "android"),
+                  not(all(target_os = "linux", target_arch = "arm"))))]
+        pub fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> libc::uintptr_t;
+
+        #[cfg(all(not(target_os = "android"),
+                  not(all(target_os = "linux", target_arch = "arm"))))]
+        pub fn _Unwind_FindEnclosingFunction(pc: *mut libc::c_void)
+            -> *mut libc::c_void;
+    }
+
+    // On android, the function _Unwind_GetIP is a macro, and this is the
+    // expansion of the macro. This is all copy/pasted directly from the
+    // header file with the definition of _Unwind_GetIP.
+    #[cfg(any(target_os = "android",
+              all(target_os = "linux", target_arch = "arm")))]
+    pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> libc::uintptr_t {
+        #[repr(C)]
+        enum _Unwind_VRS_Result {
+            _UVRSR_OK = 0,
+            _UVRSR_NOT_IMPLEMENTED = 1,
+            _UVRSR_FAILED = 2,
+        }
+        #[repr(C)]
+        enum _Unwind_VRS_RegClass {
+            _UVRSC_CORE = 0,
+            _UVRSC_VFP = 1,
+            _UVRSC_FPA = 2,
+            _UVRSC_WMMXD = 3,
+            _UVRSC_WMMXC = 4,
+        }
+        #[repr(C)]
+        enum _Unwind_VRS_DataRepresentation {
+            _UVRSD_UINT32 = 0,
+            _UVRSD_VFPX = 1,
+            _UVRSD_FPAX = 2,
+            _UVRSD_UINT64 = 3,
+            _UVRSD_FLOAT = 4,
+            _UVRSD_DOUBLE = 5,
+        }
+
+        type _Unwind_Word = libc::c_uint;
+        extern {
+            fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context,
+                               klass: _Unwind_VRS_RegClass,
+                               word: _Unwind_Word,
+                               repr: _Unwind_VRS_DataRepresentation,
+                               data: *mut libc::c_void)
+                -> _Unwind_VRS_Result;
+        }
+
+        let mut val: _Unwind_Word = 0;
+        let ptr = &mut val as *mut _Unwind_Word;
+        let _ = _Unwind_VRS_Get(ctx, _Unwind_VRS_RegClass::_UVRSC_CORE, 15,
+                                _Unwind_VRS_DataRepresentation::_UVRSD_UINT32,
+                                ptr as *mut libc::c_void);
+        (val & !1) as libc::uintptr_t
+    }
+
+    // This function also doesn't exist on Android or ARM/Linux, so make it
+    // a no-op
+    #[cfg(any(target_os = "android",
+              all(target_os = "linux", target_arch = "arm")))]
+    pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut libc::c_void)
+        -> *mut libc::c_void
+    {
+        pc
+    }
+}
diff --git a/src/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs
new file mode 100644
index 00000000000..f64718539ef
--- /dev/null
+++ b/src/libstd/sys/unix/condvar.rs
@@ -0,0 +1,83 @@
+// 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.
+
+use cell::UnsafeCell;
+use libc;
+use sys::mutex::{mod, Mutex};
+use sys::sync as ffi;
+use time::Duration;
+
+pub struct Condvar { inner: UnsafeCell<ffi::pthread_cond_t> }
+
+pub const CONDVAR_INIT: Condvar = Condvar {
+    inner: UnsafeCell { value: ffi::PTHREAD_COND_INITIALIZER },
+};
+
+impl Condvar {
+    #[inline]
+    pub unsafe fn new() -> Condvar {
+        // Might be moved and address is changing it is better to avoid
+        // initialization of potentially opaque OS data before it landed
+        Condvar { inner: UnsafeCell::new(ffi::PTHREAD_COND_INITIALIZER) }
+    }
+
+    #[inline]
+    pub unsafe fn notify_one(&self) {
+        let r = ffi::pthread_cond_signal(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+
+    #[inline]
+    pub unsafe fn notify_all(&self) {
+        let r = ffi::pthread_cond_broadcast(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+
+    #[inline]
+    pub unsafe fn wait(&self, mutex: &Mutex) {
+        let r = ffi::pthread_cond_wait(self.inner.get(), mutex::raw(mutex));
+        debug_assert_eq!(r, 0);
+    }
+
+    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
+        assert!(dur >= Duration::nanoseconds(0));
+
+        // First, figure out what time it currently is
+        let mut tv = libc::timeval { tv_sec: 0, tv_usec: 0 };
+        let r = ffi::gettimeofday(&mut tv, 0 as *mut _);
+        debug_assert_eq!(r, 0);
+
+        // Offset that time with the specified duration
+        let abs = Duration::seconds(tv.tv_sec as i64) +
+                  Duration::microseconds(tv.tv_usec as i64) +
+                  dur;
+        let ns = abs.num_nanoseconds().unwrap() as u64;
+        let timeout = libc::timespec {
+            tv_sec: (ns / 1000000000) as libc::time_t,
+            tv_nsec: (ns % 1000000000) as libc::c_long,
+        };
+
+        // And wait!
+        let r = ffi::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex),
+                                            &timeout);
+        if r != 0 {
+            debug_assert_eq!(r as int, libc::ETIMEDOUT as int);
+            false
+        } else {
+            true
+        }
+    }
+
+    #[inline]
+    pub unsafe fn destroy(&self) {
+        let r = ffi::pthread_cond_destroy(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+}
diff --git a/src/libstd/sys/unix/ext.rs b/src/libstd/sys/unix/ext.rs
new file mode 100644
index 00000000000..ae3c939bf78
--- /dev/null
+++ b/src/libstd/sys/unix/ext.rs
@@ -0,0 +1,107 @@
+// 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.
+
+//! Experimental extensions to `std` for Unix platforms.
+//!
+//! For now, this module is limited to extracting file descriptors,
+//! but its functionality will grow over time.
+//!
+//! # Example
+//!
+//! ```rust,ignore
+//! #![feature(globs)]
+//!
+//! use std::io::fs::File;
+//! use std::os::unix::prelude::*;
+//!
+//! fn main() {
+//!     let f = File::create(&Path::new("foo.txt")).unwrap();
+//!     let fd = f.as_raw_fd();
+//!
+//!     // use fd with native unix bindings
+//! }
+//! ```
+
+#![experimental]
+
+use sys_common::AsInner;
+use libc;
+
+use io;
+
+/// Raw file descriptors.
+pub type Fd = libc::c_int;
+
+/// Extract raw file descriptor
+pub trait AsRawFd {
+    /// Extract the raw file descriptor, without taking any ownership.
+    fn as_raw_fd(&self) -> Fd;
+}
+
+impl AsRawFd for io::fs::File {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::pipe::PipeStream {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::net::pipe::UnixStream {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::net::pipe::UnixListener {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::net::pipe::UnixAcceptor {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::net::tcp::TcpStream {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::net::tcp::TcpListener {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::net::tcp::TcpAcceptor {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::net::udp::UdpSocket {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+/// A prelude for conveniently writing platform-specific code.
+///
+/// Includes all extension traits, and some important type definitions.
+pub mod prelude {
+    pub use super::{Fd, AsRawFd};
+}
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index 816876b5e4a..98d860f9646 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -18,14 +18,11 @@ use io;
 use prelude::*;
 
 use io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode};
-use io::{IoResult, FileStat, SeekStyle, Reader};
+use io::{IoResult, FileStat, SeekStyle};
 use io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append};
-use result::{Ok, Err};
 use sys::retry;
 use sys_common::{keep_going, eof, mkerr_libc};
 
-pub use path::PosixPath as Path;
-
 pub type fd_t = libc::c_int;
 
 pub struct FileDesc {
@@ -201,7 +198,7 @@ pub fn readdir(p: &Path) -> IoResult<Vec<Path>> {
 
     let size = unsafe { rust_dirent_t_size() };
     let mut buf = Vec::<u8>::with_capacity(size as uint);
-    let ptr = buf.as_mut_slice().as_mut_ptr() as *mut dirent_t;
+    let ptr = buf.as_mut_ptr() as *mut dirent_t;
 
     let p = p.to_c_str();
     let dir_ptr = unsafe {opendir(p.as_ptr())};
@@ -305,12 +302,12 @@ fn mkstat(stat: &libc::stat) -> FileStat {
     FileStat {
         size: stat.st_size as u64,
         kind: match (stat.st_mode as libc::mode_t) & libc::S_IFMT {
-            libc::S_IFREG => io::TypeFile,
-            libc::S_IFDIR => io::TypeDirectory,
-            libc::S_IFIFO => io::TypeNamedPipe,
-            libc::S_IFBLK => io::TypeBlockSpecial,
-            libc::S_IFLNK => io::TypeSymlink,
-            _ => io::TypeUnknown,
+            libc::S_IFREG => io::FileType::RegularFile,
+            libc::S_IFDIR => io::FileType::Directory,
+            libc::S_IFIFO => io::FileType::NamedPipe,
+            libc::S_IFBLK => io::FileType::BlockSpecial,
+            libc::S_IFLNK => io::FileType::Symlink,
+            _ => io::FileType::Unknown,
         },
         perm: FilePermission::from_bits_truncate(stat.st_mode as u32),
         created: mktime(stat.st_ctime as u64, stat.st_ctime_nsec as u64),
diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs
index 664a6a1e70c..f3babca3287 100644
--- a/src/libstd/sys/unix/mod.rs
+++ b/src/libstd/sys/unix/mod.rs
@@ -23,25 +23,36 @@ use prelude::*;
 use io::{mod, IoResult, IoError};
 use sys_common::mkerr_libc;
 
-macro_rules! helper_init( (static $name:ident: Helper<$m:ty>) => (
+macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
     static $name: Helper<$m> = Helper {
-        lock: ::rustrt::mutex::NATIVE_MUTEX_INIT,
+        lock: ::sync::MUTEX_INIT,
+        cond: ::sync::CONDVAR_INIT,
         chan: ::cell::UnsafeCell { value: 0 as *mut Sender<$m> },
         signal: ::cell::UnsafeCell { value: 0 },
         initialized: ::cell::UnsafeCell { value: false },
+        shutdown: ::cell::UnsafeCell { value: false },
     };
-) )
+) }
 
+pub mod backtrace;
 pub mod c;
+pub mod ext;
+pub mod condvar;
 pub mod fs;
+pub mod helper_signal;
+pub mod mutex;
 pub mod os;
-pub mod tcp;
-pub mod udp;
 pub mod pipe;
-pub mod helper_signal;
 pub mod process;
+pub mod rwlock;
+pub mod stack_overflow;
+pub mod sync;
+pub mod tcp;
+pub mod thread;
+pub mod thread_local;
 pub mod timer;
 pub mod tty;
+pub mod udp;
 
 pub mod addrinfo {
     pub use sys_common::net::get_host_addresses;
@@ -117,7 +128,10 @@ pub fn decode_error_detailed(errno: i32) -> IoError {
 }
 
 #[inline]
-pub fn retry<T: SignedInt> (f: || -> T) -> T {
+pub fn retry<T, F> (mut f: F) -> T where
+    T: SignedInt,
+    F: FnMut() -> T,
+{
     let one: T = Int::one();
     loop {
         let n = f();
diff --git a/src/libstd/sys/unix/mutex.rs b/src/libstd/sys/unix/mutex.rs
new file mode 100644
index 00000000000..2f01c53cb2c
--- /dev/null
+++ b/src/libstd/sys/unix/mutex.rs
@@ -0,0 +1,52 @@
+// 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.
+
+use cell::UnsafeCell;
+use sys::sync as ffi;
+use sys_common::mutex;
+
+pub struct Mutex { inner: UnsafeCell<ffi::pthread_mutex_t> }
+
+#[inline]
+pub unsafe fn raw(m: &Mutex) -> *mut ffi::pthread_mutex_t {
+    m.inner.get()
+}
+
+pub const MUTEX_INIT: Mutex = Mutex {
+    inner: UnsafeCell { value: ffi::PTHREAD_MUTEX_INITIALIZER },
+};
+
+impl Mutex {
+    #[inline]
+    pub unsafe fn new() -> Mutex {
+        // Might be moved and address is changing it is better to avoid
+        // initialization of potentially opaque OS data before it landed
+        MUTEX_INIT
+    }
+    #[inline]
+    pub unsafe fn lock(&self) {
+        let r = ffi::pthread_mutex_lock(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+    #[inline]
+    pub unsafe fn unlock(&self) {
+        let r = ffi::pthread_mutex_unlock(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+    #[inline]
+    pub unsafe fn try_lock(&self) -> bool {
+        ffi::pthread_mutex_trylock(self.inner.get()) == 0
+    }
+    #[inline]
+    pub unsafe fn destroy(&self) {
+        let r = ffi::pthread_mutex_destroy(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+}
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
index 4e495f043bc..316d97064ee 100644
--- a/src/libstd/sys/unix/os.rs
+++ b/src/libstd/sys/unix/os.rs
@@ -8,14 +8,24 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use libc;
-use libc::{c_int, c_char};
+//! Implementation of `std::os` functionality for unix systems
+
 use prelude::*;
-use io::IoResult;
+
+use error::{FromError, Error};
+use fmt;
+use io::{IoError, IoResult};
+use libc::{mod, c_int, c_char, c_void};
+use path::BytesContainer;
+use ptr;
+use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst};
 use sys::fs::FileDesc;
+use os;
 
 use os::TMPBUF_SZ;
 
+const BUF_BYTES : uint = 2048u;
+
 /// Returns the platform-specific value of errno
 pub fn errno() -> int {
     #[cfg(any(target_os = "macos",
@@ -98,7 +108,7 @@ pub fn error_string(errno: i32) -> String {
             panic!("strerror_r failure");
         }
 
-        ::string::raw::from_buf(p as *const u8)
+        String::from_raw_buf(p as *const u8)
     }
 }
 
@@ -110,3 +120,122 @@ pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
         Err(super::last_error())
     }
 }
+
+pub fn getcwd() -> IoResult<Path> {
+    use c_str::CString;
+
+    let mut buf = [0 as c_char, ..BUF_BYTES];
+    unsafe {
+        if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() {
+            Err(IoError::last_error())
+        } else {
+            Ok(Path::new(CString::new(buf.as_ptr(), false)))
+        }
+    }
+}
+
+pub unsafe fn get_env_pairs() -> Vec<Vec<u8>> {
+    use c_str::CString;
+
+    extern {
+        fn rust_env_pairs() -> *const *const c_char;
+    }
+    let mut environ = rust_env_pairs();
+    if environ as uint == 0 {
+        panic!("os::env() failure getting env string from OS: {}",
+               os::last_os_error());
+    }
+    let mut result = Vec::new();
+    while *environ != 0 as *const _ {
+        let env_pair =
+            CString::new(*environ, false).as_bytes_no_nul().to_vec();
+        result.push(env_pair);
+        environ = environ.offset(1);
+    }
+    result
+}
+
+pub fn split_paths(unparsed: &[u8]) -> Vec<Path> {
+    unparsed.split(|b| *b == b':').map(Path::new).collect()
+}
+
+pub fn join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
+    let mut joined = Vec::new();
+    let sep = b':';
+
+    for (i, path) in paths.iter().map(|p| p.container_as_bytes()).enumerate() {
+        if i > 0 { joined.push(sep) }
+        if path.contains(&sep) { return Err("path segment contains separator `:`") }
+        joined.push_all(path);
+    }
+
+    Ok(joined)
+}
+
+#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+pub fn load_self() -> Option<Vec<u8>> {
+    unsafe {
+        use libc::funcs::bsd44::*;
+        use libc::consts::os::extra::*;
+        let mut mib = vec![CTL_KERN as c_int,
+                           KERN_PROC as c_int,
+                           KERN_PROC_PATHNAME as c_int,
+                           -1 as c_int];
+        let mut sz: libc::size_t = 0;
+        let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
+                         ptr::null_mut(), &mut sz, ptr::null_mut(),
+                         0u as libc::size_t);
+        if err != 0 { return None; }
+        if sz == 0 { return None; }
+        let mut v: Vec<u8> = Vec::with_capacity(sz as uint);
+        let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
+                         v.as_mut_ptr() as *mut libc::c_void, &mut sz,
+                         ptr::null_mut(), 0u as libc::size_t);
+        if err != 0 { return None; }
+        if sz == 0 { return None; }
+        v.set_len(sz as uint - 1); // chop off trailing NUL
+        Some(v)
+    }
+}
+
+#[cfg(any(target_os = "linux", target_os = "android"))]
+pub fn load_self() -> Option<Vec<u8>> {
+    use std::io;
+
+    match io::fs::readlink(&Path::new("/proc/self/exe")) {
+        Ok(path) => Some(path.into_vec()),
+        Err(..) => None
+    }
+}
+
+#[cfg(any(target_os = "macos", target_os = "ios"))]
+pub fn load_self() -> Option<Vec<u8>> {
+    unsafe {
+        use libc::funcs::extra::_NSGetExecutablePath;
+        let mut sz: u32 = 0;
+        _NSGetExecutablePath(ptr::null_mut(), &mut sz);
+        if sz == 0 { return None; }
+        let mut v: Vec<u8> = Vec::with_capacity(sz as uint);
+        let err = _NSGetExecutablePath(v.as_mut_ptr() as *mut i8, &mut sz);
+        if err != 0 { return None; }
+        v.set_len(sz as uint - 1); // chop off trailing NUL
+        Some(v)
+    }
+}
+
+pub fn chdir(p: &Path) -> IoResult<()> {
+    p.with_c_str(|buf| {
+        unsafe {
+            match libc::chdir(buf) == (0 as c_int) {
+                true => Ok(()),
+                false => Err(IoError::last_error()),
+            }
+        }
+    })
+}
+
+pub fn page_size() -> uint {
+    unsafe {
+        libc::sysconf(libc::_SC_PAGESIZE) as uint
+    }
+}
diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs
index 4d3469a9c24..348b7cfad33 100644
--- a/src/libstd/sys/unix/pipe.rs
+++ b/src/libstd/sys/unix/pipe.rs
@@ -12,14 +12,14 @@ use alloc::arc::Arc;
 use libc;
 use c_str::CString;
 use mem;
-use rustrt::mutex;
-use sync::atomic;
+use sync::{atomic, Mutex};
 use io::{mod, IoResult, IoError};
 use prelude::*;
 
 use sys::{mod, timer, retry, c, set_nonblocking, wouldblock};
 use sys::fs::{fd_t, FileDesc};
 use sys_common::net::*;
+use sys_common::net::SocketStatus::*;
 use sys_common::{eof, mkerr_libc};
 
 fn unix_socket(ty: libc::c_int) -> IoResult<fd_t> {
@@ -60,12 +60,12 @@ struct Inner {
 
     // Unused on Linux, where this lock is not necessary.
     #[allow(dead_code)]
-    lock: mutex::NativeMutex
+    lock: Mutex<()>,
 }
 
 impl Inner {
     fn new(fd: fd_t) -> Inner {
-        Inner { fd: fd, lock: unsafe { mutex::NativeMutex::new() } }
+        Inner { fd: fd, lock: Mutex::new(()) }
     }
 }
 
@@ -133,7 +133,7 @@ impl UnixStream {
         }
     }
 
-    fn fd(&self) -> fd_t { self.inner.fd }
+    pub fn fd(&self) -> fd_t { self.inner.fd }
 
     #[cfg(target_os = "linux")]
     fn lock_nonblocking(&self) {}
@@ -150,8 +150,8 @@ impl UnixStream {
 
     pub fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
         let fd = self.fd();
-        let dolock = || self.lock_nonblocking();
-        let doread = |nb| unsafe {
+        let dolock = |&:| self.lock_nonblocking();
+        let doread = |&mut: nb| unsafe {
             let flags = if nb {c::MSG_DONTWAIT} else {0};
             libc::recv(fd,
                        buf.as_mut_ptr() as *mut libc::c_void,
@@ -163,8 +163,8 @@ impl UnixStream {
 
     pub fn write(&mut self, buf: &[u8]) -> IoResult<()> {
         let fd = self.fd();
-        let dolock = || self.lock_nonblocking();
-        let dowrite = |nb: bool, buf: *const u8, len: uint| unsafe {
+        let dolock = |&: | self.lock_nonblocking();
+        let dowrite = |&: nb: bool, buf: *const u8, len: uint| unsafe {
             let flags = if nb {c::MSG_DONTWAIT} else {0};
             libc::send(fd,
                        buf as *const _,
@@ -222,7 +222,7 @@ impl UnixListener {
         })
     }
 
-    fn fd(&self) -> fd_t { self.inner.fd }
+    pub fn fd(&self) -> fd_t { self.inner.fd }
 
     pub fn listen(self) -> IoResult<UnixAcceptor> {
         match unsafe { libc::listen(self.fd(), 128) } {
@@ -260,7 +260,7 @@ struct AcceptorInner {
 }
 
 impl UnixAcceptor {
-    fn fd(&self) -> fd_t { self.inner.listener.fd() }
+    pub fn fd(&self) -> fd_t { self.inner.listener.fd() }
 
     pub fn accept(&mut self) -> IoResult<UnixStream> {
         let deadline = if self.deadline == 0 {None} else {Some(self.deadline)};
diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs
index 81bc138ca91..835f4279d9b 100644
--- a/src/libstd/sys/unix/process.rs
+++ b/src/libstd/sys/unix/process.rs
@@ -11,7 +11,7 @@ use self::Req::*;
 
 use libc::{mod, pid_t, c_void, c_int};
 use c_str::CString;
-use io::{mod, IoResult, IoError};
+use io::{mod, IoResult, IoError, EndOfFile};
 use mem;
 use os;
 use ptr;
@@ -24,11 +24,11 @@ use hash::Hash;
 use sys::{mod, retry, c, wouldblock, set_nonblocking, ms_to_timeval};
 use sys::fs::FileDesc;
 use sys_common::helper_thread::Helper;
-use sys_common::{AsFileDesc, mkerr_libc, timeout};
+use sys_common::{AsInner, mkerr_libc, timeout};
 
 pub use sys_common::ProcessConfig;
 
-helper_init!(static HELPER: Helper<Req>)
+helper_init! { static HELPER: Helper<Req> }
 
 /// The unique id of the process (this should never be negative).
 pub struct Process {
@@ -39,6 +39,8 @@ enum Req {
     NewChild(libc::pid_t, Sender<ProcessExit>, u64),
 }
 
+const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX";
+
 impl Process {
     pub fn id(&self) -> pid_t {
         self.pid
@@ -56,7 +58,7 @@ impl Process {
     pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
                               out_fd: Option<P>, err_fd: Option<P>)
                               -> IoResult<Process>
-        where C: ProcessConfig<K, V>, P: AsFileDesc,
+        where C: ProcessConfig<K, V>, P: AsInner<FileDesc>,
               K: BytesContainer + Eq + Hash, V: BytesContainer
     {
         use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
@@ -92,8 +94,8 @@ impl Process {
             mem::transmute::<&ProcessConfig<K,V>,&'static ProcessConfig<K,V>>(cfg)
         };
 
-        with_envp(cfg.env(), proc(envp) {
-            with_argv(cfg.program(), cfg.args(), proc(argv) unsafe {
+        with_envp(cfg.env(), move|: envp: *const c_void| {
+            with_argv(cfg.program(), cfg.args(), move|: argv: *const *const libc::c_char| unsafe {
                 let (input, mut output) = try!(sys::os::pipe());
 
                 // We may use this in the child, so perform allocations before the
@@ -106,18 +108,36 @@ impl Process {
                 if pid < 0 {
                     return Err(super::last_error())
                 } else if pid > 0 {
+                    #[inline]
+                    fn combine(arr: &[u8]) -> i32 {
+                        let a = arr[0] as u32;
+                        let b = arr[1] as u32;
+                        let c = arr[2] as u32;
+                        let d = arr[3] as u32;
+
+                        ((a << 24) | (b << 16) | (c << 8) | (d << 0)) as i32
+                    }
+
+                    let p = Process{ pid: pid };
                     drop(output);
-                    let mut bytes = [0, ..4];
+                    let mut bytes = [0, ..8];
                     return match input.read(&mut bytes) {
-                        Ok(4) => {
-                            let errno = (bytes[0] as i32 << 24) |
-                                        (bytes[1] as i32 << 16) |
-                                        (bytes[2] as i32 <<  8) |
-                                        (bytes[3] as i32 <<  0);
+                        Ok(8) => {
+                            assert!(combine(CLOEXEC_MSG_FOOTER) == combine(bytes.slice(4, 8)),
+                                "Validation on the CLOEXEC pipe failed: {}", bytes);
+                            let errno = combine(bytes.slice(0, 4));
+                            assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic");
                             Err(super::decode_error(errno))
                         }
-                        Err(..) => Ok(Process { pid: pid }),
-                        Ok(..) => panic!("short read on the cloexec pipe"),
+                        Err(ref e) if e.kind == EndOfFile => Ok(p),
+                        Err(e) => {
+                            assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic");
+                            panic!("the CLOEXEC pipe failed: {}", e)
+                        },
+                        Ok(..) => { // pipe I/O up to PIPE_BUF bytes should be atomic
+                            assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic");
+                            panic!("short read on the CLOEXEC pipe")
+                        }
                     };
                 }
 
@@ -154,13 +174,16 @@ impl Process {
                 let _ = libc::close(input.fd());
 
                 fn fail(output: &mut FileDesc) -> ! {
-                    let errno = sys::os::errno();
+                    let errno = sys::os::errno() as u32;
                     let bytes = [
                         (errno >> 24) as u8,
                         (errno >> 16) as u8,
                         (errno >>  8) as u8,
                         (errno >>  0) as u8,
+                        CLOEXEC_MSG_FOOTER[0], CLOEXEC_MSG_FOOTER[1],
+                        CLOEXEC_MSG_FOOTER[2], CLOEXEC_MSG_FOOTER[3]
                     ];
+                    // pipe I/O up to PIPE_BUF bytes should be atomic
                     assert!(output.write(&bytes).is_ok());
                     unsafe { libc::_exit(1) }
                 }
@@ -183,7 +206,7 @@ impl Process {
                             libc::open(devnull.as_ptr(), flags, 0)
                         }
                         Some(obj) => {
-                            let fd = obj.as_fd().fd();
+                            let fd = obj.as_inner().fd();
                             // Leak the memory and the file descriptor. We're in the
                             // child now an all our resources are going to be
                             // cleaned up very soon
@@ -356,8 +379,8 @@ impl Process {
                 // wait indefinitely for a message to arrive.
                 //
                 // FIXME: sure would be nice to not have to scan the entire array
-                let min = active.iter().map(|a| *a.ref2()).enumerate().min_by(|p| {
-                    p.val1()
+                let min = active.iter().map(|a| a.2).enumerate().min_by(|p| {
+                    p.1
                 });
                 let (p, idx) = match min {
                     Some((idx, deadline)) => {
@@ -508,8 +531,11 @@ impl Process {
     }
 }
 
-fn with_argv<T>(prog: &CString, args: &[CString],
-                cb: proc(*const *const libc::c_char) -> T) -> T {
+fn with_argv<T,F>(prog: &CString, args: &[CString],
+                  cb: F)
+                  -> T
+    where F : FnOnce(*const *const libc::c_char) -> T
+{
     let mut ptrs: Vec<*const libc::c_char> = Vec::with_capacity(args.len()+1);
 
     // Convert the CStrings into an array of pointers. Note: the
@@ -526,9 +552,12 @@ fn with_argv<T>(prog: &CString, args: &[CString],
     cb(ptrs.as_ptr())
 }
 
-fn with_envp<K, V, T>(env: Option<&collections::HashMap<K, V>>,
-                      cb: proc(*const c_void) -> T) -> T
-    where K: BytesContainer + Eq + Hash, V: BytesContainer
+fn with_envp<K,V,T,F>(env: Option<&collections::HashMap<K, V>>,
+                      cb: F)
+                      -> T
+    where F : FnOnce(*const c_void) -> T,
+          K : BytesContainer + Eq + Hash,
+          V : BytesContainer
 {
     // On posixy systems we can pass a char** for envp, which is a
     // null-terminated array of "k=v\0" strings. Since we must create
@@ -541,9 +570,9 @@ fn with_envp<K, V, T>(env: Option<&collections::HashMap<K, V>>,
 
             for pair in env.iter() {
                 let mut kv = Vec::new();
-                kv.push_all(pair.ref0().container_as_bytes());
+                kv.push_all(pair.0.container_as_bytes());
                 kv.push('=' as u8);
-                kv.push_all(pair.ref1().container_as_bytes());
+                kv.push_all(pair.1.container_as_bytes());
                 kv.push(0); // terminating null
                 tmps.push(kv);
             }
diff --git a/src/libstd/sys/unix/rwlock.rs b/src/libstd/sys/unix/rwlock.rs
new file mode 100644
index 00000000000..0d63ff14ff2
--- /dev/null
+++ b/src/libstd/sys/unix/rwlock.rs
@@ -0,0 +1,57 @@
+// 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.
+
+use cell::UnsafeCell;
+use sys::sync as ffi;
+
+pub struct RWLock { inner: UnsafeCell<ffi::pthread_rwlock_t> }
+
+pub const RWLOCK_INIT: RWLock = RWLock {
+    inner: UnsafeCell { value: ffi::PTHREAD_RWLOCK_INITIALIZER },
+};
+
+impl RWLock {
+    #[inline]
+    pub unsafe fn new() -> RWLock {
+        // Might be moved and address is changing it is better to avoid
+        // initialization of potentially opaque OS data before it landed
+        RWLOCK_INIT
+    }
+    #[inline]
+    pub unsafe fn read(&self) {
+        let r = ffi::pthread_rwlock_rdlock(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+    #[inline]
+    pub unsafe fn try_read(&self) -> bool {
+        ffi::pthread_rwlock_tryrdlock(self.inner.get()) == 0
+    }
+    #[inline]
+    pub unsafe fn write(&self) {
+        let r = ffi::pthread_rwlock_wrlock(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+    #[inline]
+    pub unsafe fn try_write(&self) -> bool {
+        ffi::pthread_rwlock_trywrlock(self.inner.get()) == 0
+    }
+    #[inline]
+    pub unsafe fn read_unlock(&self) {
+        let r = ffi::pthread_rwlock_unlock(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+    #[inline]
+    pub unsafe fn write_unlock(&self) { self.read_unlock() }
+    #[inline]
+    pub unsafe fn destroy(&self) {
+        let r = ffi::pthread_rwlock_destroy(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+}
diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs
new file mode 100644
index 00000000000..340f9514241
--- /dev/null
+++ b/src/libstd/sys/unix/stack_overflow.rs
@@ -0,0 +1,277 @@
+// 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.
+
+use libc;
+use core::prelude::*;
+use self::imp::{make_handler, drop_handler};
+
+pub use self::imp::{init, cleanup};
+
+pub struct Handler {
+    _data: *mut libc::c_void
+}
+
+impl Handler {
+    pub unsafe fn new() -> Handler {
+        make_handler()
+    }
+}
+
+impl Drop for Handler {
+    fn drop(&mut self) {
+        unsafe {
+            drop_handler(self);
+        }
+    }
+}
+
+#[cfg(any(target_os = "linux", target_os = "macos"))]
+mod imp {
+    use core::prelude::*;
+    use sys_common::stack;
+
+    use super::Handler;
+    use rt::util::report_overflow;
+    use mem;
+    use ptr;
+    use intrinsics;
+    use self::signal::{siginfo, sigaction, SIGBUS, SIG_DFL,
+                       SA_SIGINFO, SA_ONSTACK, sigaltstack,
+                       SIGSTKSZ};
+    use libc;
+    use libc::funcs::posix88::mman::{mmap, munmap};
+    use libc::consts::os::posix88::{SIGSEGV,
+                                    PROT_READ,
+                                    PROT_WRITE,
+                                    MAP_PRIVATE,
+                                    MAP_ANON,
+                                    MAP_FAILED};
+
+    use sys_common::thread_info;
+
+
+    // This is initialized in init() and only read from after
+    static mut PAGE_SIZE: uint = 0;
+
+    #[no_stack_check]
+    unsafe extern fn signal_handler(signum: libc::c_int,
+                                     info: *mut siginfo,
+                                     _data: *mut libc::c_void) {
+
+        // We can not return from a SIGSEGV or SIGBUS signal.
+        // See: https://www.gnu.org/software/libc/manual/html_node/Handler-Returns.html
+
+        unsafe fn term(signum: libc::c_int) -> ! {
+            use core::mem::transmute;
+
+            signal(signum, transmute(SIG_DFL));
+            raise(signum);
+            intrinsics::abort();
+        }
+
+        // We're calling into functions with stack checks
+        stack::record_sp_limit(0);
+
+        let guard = thread_info::stack_guard();
+        let addr = (*info).si_addr as uint;
+
+        if guard == 0 || addr < guard - PAGE_SIZE || addr >= guard {
+            term(signum);
+        }
+
+        report_overflow();
+
+        intrinsics::abort()
+    }
+
+    static mut MAIN_ALTSTACK: *mut libc::c_void = 0 as *mut libc::c_void;
+
+    pub unsafe fn init() {
+        let psize = libc::sysconf(libc::consts::os::sysconf::_SC_PAGESIZE);
+        if psize == -1 {
+            panic!("failed to get page size");
+        }
+
+        PAGE_SIZE = psize as uint;
+
+        let mut action: sigaction = mem::zeroed();
+        action.sa_flags = SA_SIGINFO | SA_ONSTACK;
+        action.sa_sigaction = signal_handler as sighandler_t;
+        sigaction(SIGSEGV, &action, ptr::null_mut());
+        sigaction(SIGBUS, &action, ptr::null_mut());
+
+        let handler = make_handler();
+        MAIN_ALTSTACK = handler._data;
+        mem::forget(handler);
+    }
+
+    pub unsafe fn cleanup() {
+        Handler { _data: MAIN_ALTSTACK };
+    }
+
+    pub unsafe fn make_handler() -> Handler {
+        let alt_stack = mmap(ptr::null_mut(),
+                             signal::SIGSTKSZ,
+                             PROT_READ | PROT_WRITE,
+                             MAP_PRIVATE | MAP_ANON,
+                             -1,
+                             0);
+        if alt_stack == MAP_FAILED {
+            panic!("failed to allocate an alternative stack");
+        }
+
+        let mut stack: sigaltstack = mem::zeroed();
+
+        stack.ss_sp = alt_stack;
+        stack.ss_flags = 0;
+        stack.ss_size = SIGSTKSZ;
+
+        sigaltstack(&stack, ptr::null_mut());
+
+        Handler { _data: alt_stack }
+    }
+
+    pub unsafe fn drop_handler(handler: &mut Handler) {
+        munmap(handler._data, SIGSTKSZ);
+    }
+
+    type sighandler_t = *mut libc::c_void;
+
+    #[cfg(any(all(target_os = "linux", target_arch = "x86"), // may not match
+              all(target_os = "linux", target_arch = "x86_64"),
+              all(target_os = "linux", target_arch = "arm"), // may not match
+              all(target_os = "linux", target_arch = "mips"), // may not match
+              all(target_os = "linux", target_arch = "mipsel"), // may not match
+              target_os = "android"))] // may not match
+    mod signal {
+        use libc;
+        use super::sighandler_t;
+
+        pub static SA_ONSTACK: libc::c_int = 0x08000000;
+        pub static SA_SIGINFO: libc::c_int = 0x00000004;
+        pub static SIGBUS: libc::c_int = 7;
+
+        pub static SIGSTKSZ: libc::size_t = 8192;
+
+        pub static SIG_DFL: sighandler_t = 0i as sighandler_t;
+
+        // This definition is not as accurate as it could be, {si_addr} is
+        // actually a giant union. Currently we're only interested in that field,
+        // however.
+        #[repr(C)]
+        pub struct siginfo {
+            si_signo: libc::c_int,
+            si_errno: libc::c_int,
+            si_code: libc::c_int,
+            pub si_addr: *mut libc::c_void
+        }
+
+        #[repr(C)]
+        pub struct sigaction {
+            pub sa_sigaction: sighandler_t,
+            pub sa_mask: sigset_t,
+            pub sa_flags: libc::c_int,
+            sa_restorer: *mut libc::c_void,
+        }
+
+        #[cfg(target_word_size = "32")]
+        #[repr(C)]
+        pub struct sigset_t {
+            __val: [libc::c_ulong, ..32],
+        }
+        #[cfg(target_word_size = "64")]
+        #[repr(C)]
+        pub struct sigset_t {
+            __val: [libc::c_ulong, ..16],
+        }
+
+        #[repr(C)]
+        pub struct sigaltstack {
+            pub ss_sp: *mut libc::c_void,
+            pub ss_flags: libc::c_int,
+            pub ss_size: libc::size_t
+        }
+
+    }
+
+    #[cfg(target_os = "macos")]
+    mod signal {
+        use libc;
+        use super::sighandler_t;
+
+        pub const SA_ONSTACK: libc::c_int = 0x0001;
+        pub const SA_SIGINFO: libc::c_int = 0x0040;
+        pub const SIGBUS: libc::c_int = 10;
+
+        pub const SIGSTKSZ: libc::size_t = 131072;
+
+        pub const SIG_DFL: sighandler_t = 0i as sighandler_t;
+
+        pub type sigset_t = u32;
+
+        // This structure has more fields, but we're not all that interested in
+        // them.
+        #[repr(C)]
+        pub struct siginfo {
+            pub si_signo: libc::c_int,
+            pub si_errno: libc::c_int,
+            pub si_code: libc::c_int,
+            pub pid: libc::pid_t,
+            pub uid: libc::uid_t,
+            pub status: libc::c_int,
+            pub si_addr: *mut libc::c_void
+        }
+
+        #[repr(C)]
+        pub struct sigaltstack {
+            pub ss_sp: *mut libc::c_void,
+            pub ss_size: libc::size_t,
+            pub ss_flags: libc::c_int
+        }
+
+        #[repr(C)]
+        pub struct sigaction {
+            pub sa_sigaction: sighandler_t,
+            pub sa_mask: sigset_t,
+            pub sa_flags: libc::c_int,
+        }
+    }
+
+    extern {
+        pub fn signal(signum: libc::c_int, handler: sighandler_t) -> sighandler_t;
+        pub fn raise(signum: libc::c_int) -> libc::c_int;
+
+        pub fn sigaction(signum: libc::c_int,
+                         act: *const sigaction,
+                         oldact: *mut sigaction) -> libc::c_int;
+
+        pub fn sigaltstack(ss: *const sigaltstack,
+                           oss: *mut sigaltstack) -> libc::c_int;
+    }
+}
+
+#[cfg(not(any(target_os = "linux",
+              target_os = "macos")))]
+mod imp {
+    use libc;
+
+    pub unsafe fn init() {
+    }
+
+    pub unsafe fn cleanup() {
+    }
+
+    pub unsafe fn make_handler() -> super::Handler {
+        super::Handler { _data: 0i as *mut libc::c_void }
+    }
+
+    pub unsafe fn drop_handler(_handler: &mut super::Handler) {
+    }
+}
diff --git a/src/libstd/sys/unix/sync.rs b/src/libstd/sys/unix/sync.rs
new file mode 100644
index 00000000000..007826b4b9d
--- /dev/null
+++ b/src/libstd/sys/unix/sync.rs
@@ -0,0 +1,208 @@
+// 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.
+
+#![allow(bad_style)]
+
+use libc;
+
+pub use self::os::{PTHREAD_MUTEX_INITIALIZER, pthread_mutex_t};
+pub use self::os::{PTHREAD_COND_INITIALIZER, pthread_cond_t};
+pub use self::os::{PTHREAD_RWLOCK_INITIALIZER, pthread_rwlock_t};
+
+extern {
+    // mutexes
+    pub fn pthread_mutex_destroy(lock: *mut pthread_mutex_t) -> libc::c_int;
+    pub fn pthread_mutex_lock(lock: *mut pthread_mutex_t) -> libc::c_int;
+    pub fn pthread_mutex_trylock(lock: *mut pthread_mutex_t) -> libc::c_int;
+    pub fn pthread_mutex_unlock(lock: *mut pthread_mutex_t) -> libc::c_int;
+
+    // cvars
+    pub fn pthread_cond_wait(cond: *mut pthread_cond_t,
+                             lock: *mut pthread_mutex_t) -> libc::c_int;
+    pub fn pthread_cond_timedwait(cond: *mut pthread_cond_t,
+                              lock: *mut pthread_mutex_t,
+                              abstime: *const libc::timespec) -> libc::c_int;
+    pub fn pthread_cond_signal(cond: *mut pthread_cond_t) -> libc::c_int;
+    pub fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> libc::c_int;
+    pub fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> libc::c_int;
+    pub fn gettimeofday(tp: *mut libc::timeval,
+                        tz: *mut libc::c_void) -> libc::c_int;
+
+    // rwlocks
+    pub fn pthread_rwlock_destroy(lock: *mut pthread_rwlock_t) -> libc::c_int;
+    pub fn pthread_rwlock_rdlock(lock: *mut pthread_rwlock_t) -> libc::c_int;
+    pub fn pthread_rwlock_tryrdlock(lock: *mut pthread_rwlock_t) -> libc::c_int;
+    pub fn pthread_rwlock_wrlock(lock: *mut pthread_rwlock_t) -> libc::c_int;
+    pub fn pthread_rwlock_trywrlock(lock: *mut pthread_rwlock_t) -> libc::c_int;
+    pub fn pthread_rwlock_unlock(lock: *mut pthread_rwlock_t) -> libc::c_int;
+}
+
+#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+mod os {
+    use libc;
+
+    pub type pthread_mutex_t = *mut libc::c_void;
+    pub type pthread_cond_t = *mut libc::c_void;
+    pub type pthread_rwlock_t = *mut libc::c_void;
+
+    pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = 0 as *mut _;
+    pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = 0 as *mut _;
+    pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = 0 as *mut _;
+}
+
+#[cfg(any(target_os = "macos", target_os = "ios"))]
+mod os {
+    use libc;
+
+    #[cfg(target_arch = "x86_64")]
+    const __PTHREAD_MUTEX_SIZE__: uint = 56;
+    #[cfg(any(target_arch = "x86",
+              target_arch = "arm"))]
+    const __PTHREAD_MUTEX_SIZE__: uint = 40;
+
+    #[cfg(target_arch = "x86_64")]
+    const __PTHREAD_COND_SIZE__: uint = 40;
+    #[cfg(any(target_arch = "x86",
+              target_arch = "arm"))]
+    const __PTHREAD_COND_SIZE__: uint = 24;
+
+    #[cfg(target_arch = "x86_64")]
+    const __PTHREAD_RWLOCK_SIZE__: uint = 192;
+    #[cfg(any(target_arch = "x86",
+              target_arch = "arm"))]
+    const __PTHREAD_RWLOCK_SIZE__: uint = 124;
+
+    const _PTHREAD_MUTEX_SIG_INIT: libc::c_long = 0x32AAABA7;
+    const _PTHREAD_COND_SIG_INIT: libc::c_long = 0x3CB0B1BB;
+    const _PTHREAD_RWLOCK_SIG_INIT: libc::c_long = 0x2DA8B3B4;
+
+    #[repr(C)]
+    pub struct pthread_mutex_t {
+        __sig: libc::c_long,
+        __opaque: [u8, ..__PTHREAD_MUTEX_SIZE__],
+    }
+    #[repr(C)]
+    pub struct pthread_cond_t {
+        __sig: libc::c_long,
+        __opaque: [u8, ..__PTHREAD_COND_SIZE__],
+    }
+    #[repr(C)]
+    pub struct pthread_rwlock_t {
+        __sig: libc::c_long,
+        __opaque: [u8, ..__PTHREAD_RWLOCK_SIZE__],
+    }
+
+    pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
+        __sig: _PTHREAD_MUTEX_SIG_INIT,
+        __opaque: [0, ..__PTHREAD_MUTEX_SIZE__],
+    };
+    pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
+        __sig: _PTHREAD_COND_SIG_INIT,
+        __opaque: [0, ..__PTHREAD_COND_SIZE__],
+    };
+    pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
+        __sig: _PTHREAD_RWLOCK_SIG_INIT,
+        __opaque: [0, ..__PTHREAD_RWLOCK_SIZE__],
+    };
+}
+
+#[cfg(target_os = "linux")]
+mod os {
+    use libc;
+
+    // minus 8 because we have an 'align' field
+    #[cfg(target_arch = "x86_64")]
+    const __SIZEOF_PTHREAD_MUTEX_T: uint = 40 - 8;
+    #[cfg(any(target_arch = "x86",
+              target_arch = "arm",
+              target_arch = "mips",
+              target_arch = "mipsel"))]
+    const __SIZEOF_PTHREAD_MUTEX_T: uint = 24 - 8;
+
+    #[cfg(any(target_arch = "x86_64",
+              target_arch = "x86",
+              target_arch = "arm",
+              target_arch = "mips",
+              target_arch = "mipsel"))]
+    const __SIZEOF_PTHREAD_COND_T: uint = 48 - 8;
+
+    #[cfg(target_arch = "x86_64")]
+    const __SIZEOF_PTHREAD_RWLOCK_T: uint = 56 - 8;
+
+    #[cfg(any(target_arch = "x86",
+              target_arch = "arm",
+              target_arch = "mips",
+              target_arch = "mipsel"))]
+    const __SIZEOF_PTHREAD_RWLOCK_T: uint = 32 - 8;
+
+    #[repr(C)]
+    pub struct pthread_mutex_t {
+        __align: libc::c_longlong,
+        size: [u8, ..__SIZEOF_PTHREAD_MUTEX_T],
+    }
+    #[repr(C)]
+    pub struct pthread_cond_t {
+        __align: libc::c_longlong,
+        size: [u8, ..__SIZEOF_PTHREAD_COND_T],
+    }
+    #[repr(C)]
+    pub struct pthread_rwlock_t {
+        __align: libc::c_longlong,
+        size: [u8, ..__SIZEOF_PTHREAD_RWLOCK_T],
+    }
+
+    pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
+        __align: 0,
+        size: [0, ..__SIZEOF_PTHREAD_MUTEX_T],
+    };
+    pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
+        __align: 0,
+        size: [0, ..__SIZEOF_PTHREAD_COND_T],
+    };
+    pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
+        __align: 0,
+        size: [0, ..__SIZEOF_PTHREAD_RWLOCK_T],
+    };
+}
+#[cfg(target_os = "android")]
+mod os {
+    use libc;
+
+    #[repr(C)]
+    pub struct pthread_mutex_t { value: libc::c_int }
+    #[repr(C)]
+    pub struct pthread_cond_t { value: libc::c_int }
+    #[repr(C)]
+    pub struct pthread_rwlock_t {
+        lock: pthread_mutex_t,
+        cond: pthread_cond_t,
+        numLocks: libc::c_int,
+        writerThreadId: libc::c_int,
+        pendingReaders: libc::c_int,
+        pendingWriters: libc::c_int,
+        reserved: [*mut libc::c_void, ..4],
+    }
+
+    pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
+        value: 0,
+    };
+    pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
+        value: 0,
+    };
+    pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
+        lock: PTHREAD_MUTEX_INITIALIZER,
+        cond: PTHREAD_COND_INITIALIZER,
+        numLocks: 0,
+        writerThreadId: 0,
+        pendingReaders: 0,
+        pendingWriters: 0,
+        reserved: [0 as *mut _, ..4],
+    };
+}
diff --git a/src/libstd/sys/unix/tcp.rs b/src/libstd/sys/unix/tcp.rs
index 00643ac0a79..5c99ad1e0ce 100644
--- a/src/libstd/sys/unix/tcp.rs
+++ b/src/libstd/sys/unix/tcp.rs
@@ -20,7 +20,8 @@ use sys::fs::FileDesc;
 use sys::{set_nonblocking, wouldblock};
 use sys;
 use sys_common;
-use sys_common::net::*;
+use sys_common::net;
+use sys_common::net::SocketStatus::Readable;
 
 pub use sys_common::net::TcpStream;
 
@@ -34,17 +35,19 @@ pub struct TcpListener {
 
 impl TcpListener {
     pub fn bind(addr: ip::SocketAddr) -> IoResult<TcpListener> {
-        let fd = try!(socket(addr, libc::SOCK_STREAM));
+        let fd = try!(net::socket(addr, libc::SOCK_STREAM));
         let ret = TcpListener { inner: FileDesc::new(fd, true) };
 
         let mut storage = unsafe { mem::zeroed() };
-        let len = addr_to_sockaddr(addr, &mut storage);
+        let len = net::addr_to_sockaddr(addr, &mut storage);
         let addrp = &storage as *const _ as *const libc::sockaddr;
 
         // On platforms with Berkeley-derived sockets, this allows
         // to quickly rebind a socket, without needing to wait for
         // the OS to clean up the previous one.
-        try!(setsockopt(fd, libc::SOL_SOCKET, libc::SO_REUSEADDR, 1 as libc::c_int));
+        try!(net::setsockopt(fd, libc::SOL_SOCKET,
+                             libc::SO_REUSEADDR,
+                             1 as libc::c_int));
 
 
         match unsafe { libc::bind(fd, addrp, len) } {
@@ -77,7 +80,7 @@ impl TcpListener {
     }
 
     pub fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
-        sockname(self.fd(), libc::getsockname)
+        net::sockname(self.fd(), libc::getsockname)
     }
 }
 
@@ -121,7 +124,7 @@ impl TcpAcceptor {
                 -1 => return Err(last_net_error()),
                 fd => return Ok(TcpStream::new(fd as sock_t)),
             }
-            try!(await(&[self.fd(), self.inner.reader.fd()],
+            try!(net::await(&[self.fd(), self.inner.reader.fd()],
                        deadline, Readable));
         }
 
@@ -129,7 +132,7 @@ impl TcpAcceptor {
     }
 
     pub fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
-        sockname(self.fd(), libc::getsockname)
+        net::sockname(self.fd(), libc::getsockname)
     }
 
     pub fn set_timeout(&mut self, timeout: Option<u64>) {
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
new file mode 100644
index 00000000000..2416b64f98f
--- /dev/null
+++ b/src/libstd/sys/unix/thread.rs
@@ -0,0 +1,271 @@
+// 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.
+
+use core::prelude::*;
+
+use boxed::Box;
+use cmp;
+use mem;
+use ptr;
+use libc::consts::os::posix01::{PTHREAD_CREATE_JOINABLE, PTHREAD_STACK_MIN};
+use libc;
+use thunk::Thunk;
+
+use sys_common::stack::RED_ZONE;
+use sys_common::thread::*;
+
+pub type rust_thread = libc::pthread_t;
+pub type rust_thread_return = *mut u8;
+pub type StartFn = extern "C" fn(*mut libc::c_void) -> rust_thread_return;
+
+#[no_stack_check]
+pub extern fn thread_start(main: *mut libc::c_void) -> rust_thread_return {
+    return start_thread(main);
+}
+
+#[cfg(all(not(target_os = "linux"), not(target_os = "macos")))]
+pub mod guard {
+    pub unsafe fn current() -> uint {
+        0
+    }
+
+    pub unsafe fn main() -> uint {
+        0
+    }
+
+    pub unsafe fn init() {
+    }
+}
+
+#[cfg(any(target_os = "linux", target_os = "macos"))]
+pub mod guard {
+    use super::*;
+    #[cfg(any(target_os = "linux", target_os = "android"))]
+    use mem;
+    #[cfg(any(target_os = "linux", target_os = "android"))]
+    use ptr;
+    use libc;
+    use libc::funcs::posix88::mman::{mmap};
+    use libc::consts::os::posix88::{PROT_NONE,
+                                    MAP_PRIVATE,
+                                    MAP_ANON,
+                                    MAP_FAILED,
+                                    MAP_FIXED};
+
+    // These are initialized in init() and only read from after
+    static mut PAGE_SIZE: uint = 0;
+    static mut GUARD_PAGE: uint = 0;
+
+    #[cfg(target_os = "macos")]
+    unsafe fn get_stack_start() -> *mut libc::c_void {
+        current() as *mut libc::c_void
+    }
+
+    #[cfg(any(target_os = "linux", target_os = "android"))]
+    unsafe fn get_stack_start() -> *mut libc::c_void {
+        let mut attr: libc::pthread_attr_t = mem::zeroed();
+        if pthread_getattr_np(pthread_self(), &mut attr) != 0 {
+            panic!("failed to get thread attributes");
+        }
+        let mut stackaddr = ptr::null_mut();
+        let mut stacksize = 0;
+        if pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize) != 0 {
+            panic!("failed to get stack information");
+        }
+        if pthread_attr_destroy(&mut attr) != 0 {
+            panic!("failed to destroy thread attributes");
+        }
+        stackaddr
+    }
+
+    pub unsafe fn init() {
+        let psize = libc::sysconf(libc::consts::os::sysconf::_SC_PAGESIZE);
+        if psize == -1 {
+            panic!("failed to get page size");
+        }
+
+        PAGE_SIZE = psize as uint;
+
+        let stackaddr = get_stack_start();
+
+        // Rellocate the last page of the stack.
+        // This ensures SIGBUS will be raised on
+        // stack overflow.
+        let result = mmap(stackaddr,
+                          PAGE_SIZE as libc::size_t,
+                          PROT_NONE,
+                          MAP_PRIVATE | MAP_ANON | MAP_FIXED,
+                          -1,
+                          0);
+
+        if result != stackaddr || result == MAP_FAILED {
+            panic!("failed to allocate a guard page");
+        }
+
+        let offset = if cfg!(target_os = "linux") {
+            2
+        } else {
+            1
+        };
+
+        GUARD_PAGE = stackaddr as uint + offset * PAGE_SIZE;
+    }
+
+    pub unsafe fn main() -> uint {
+        GUARD_PAGE
+    }
+
+    #[cfg(target_os = "macos")]
+    pub unsafe fn current() -> uint {
+        (pthread_get_stackaddr_np(pthread_self()) as libc::size_t -
+         pthread_get_stacksize_np(pthread_self())) as uint
+    }
+
+    #[cfg(any(target_os = "linux", target_os = "android"))]
+    pub unsafe fn current() -> uint {
+        let mut attr: libc::pthread_attr_t = mem::zeroed();
+        if pthread_getattr_np(pthread_self(), &mut attr) != 0 {
+            panic!("failed to get thread attributes");
+        }
+        let mut guardsize = 0;
+        if pthread_attr_getguardsize(&attr, &mut guardsize) != 0 {
+            panic!("failed to get stack guard page");
+        }
+        if guardsize == 0 {
+            panic!("there is no guard page");
+        }
+        let mut stackaddr = ptr::null_mut();
+        let mut stacksize = 0;
+        if pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize) != 0 {
+            panic!("failed to get stack information");
+        }
+        if pthread_attr_destroy(&mut attr) != 0 {
+            panic!("failed to destroy thread attributes");
+        }
+
+        stackaddr as uint + guardsize as uint
+    }
+}
+
+pub unsafe fn create(stack: uint, p: Thunk) -> rust_thread {
+    let mut native: libc::pthread_t = mem::zeroed();
+    let mut attr: libc::pthread_attr_t = mem::zeroed();
+    assert_eq!(pthread_attr_init(&mut attr), 0);
+    assert_eq!(pthread_attr_setdetachstate(&mut attr,
+                                           PTHREAD_CREATE_JOINABLE), 0);
+
+    // Reserve room for the red zone, the runtime's stack of last resort.
+    let stack_size = cmp::max(stack, RED_ZONE + min_stack_size(&attr) as uint);
+    match pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t) {
+        0 => {
+        },
+        libc::EINVAL => {
+            // EINVAL means |stack_size| is either too small or not a
+            // multiple of the system page size.  Because it's definitely
+            // >= PTHREAD_STACK_MIN, it must be an alignment issue.
+            // Round up to the nearest page and try again.
+            let page_size = libc::sysconf(libc::_SC_PAGESIZE) as uint;
+            let stack_size = (stack_size + page_size - 1) &
+                             (-(page_size as int - 1) as uint - 1);
+            assert_eq!(pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t), 0);
+        },
+        errno => {
+            // This cannot really happen.
+            panic!("pthread_attr_setstacksize() error: {}", errno);
+        },
+    };
+
+    let arg: *mut libc::c_void = mem::transmute(box p); // must box since sizeof(p)=2*uint
+    let ret = pthread_create(&mut native, &attr, thread_start, arg);
+    assert_eq!(pthread_attr_destroy(&mut attr), 0);
+
+    if ret != 0 {
+        // be sure to not leak the closure
+        let _p: Box<Box<FnOnce()+Send>> = mem::transmute(arg);
+        panic!("failed to spawn native thread: {}", ret);
+    }
+    native
+}
+
+pub unsafe fn join(native: rust_thread) {
+    assert_eq!(pthread_join(native, ptr::null_mut()), 0);
+}
+
+pub unsafe fn detach(native: rust_thread) {
+    assert_eq!(pthread_detach(native), 0);
+}
+
+pub unsafe fn yield_now() { assert_eq!(sched_yield(), 0); }
+// glibc >= 2.15 has a __pthread_get_minstack() function that returns
+// PTHREAD_STACK_MIN plus however many bytes are needed for thread-local
+// storage.  We need that information to avoid blowing up when a small stack
+// is created in an application with big thread-local storage requirements.
+// See #6233 for rationale and details.
+//
+// Link weakly to the symbol for compatibility with older versions of glibc.
+// Assumes that we've been dynamically linked to libpthread but that is
+// currently always the case.  Note that you need to check that the symbol
+// is non-null before calling it!
+#[cfg(target_os = "linux")]
+fn min_stack_size(attr: *const libc::pthread_attr_t) -> libc::size_t {
+    type F = unsafe extern "C" fn(*const libc::pthread_attr_t) -> libc::size_t;
+    extern {
+        #[linkage = "extern_weak"]
+        static __pthread_get_minstack: *const ();
+    }
+    if __pthread_get_minstack.is_null() {
+        PTHREAD_STACK_MIN
+    } else {
+        unsafe { mem::transmute::<*const (), F>(__pthread_get_minstack)(attr) }
+    }
+}
+
+// __pthread_get_minstack() is marked as weak but extern_weak linkage is
+// not supported on OS X, hence this kludge...
+#[cfg(not(target_os = "linux"))]
+fn min_stack_size(_: *const libc::pthread_attr_t) -> libc::size_t {
+    PTHREAD_STACK_MIN
+}
+
+#[cfg(any(target_os = "linux"))]
+extern {
+    pub fn pthread_self() -> libc::pthread_t;
+    pub fn pthread_getattr_np(native: libc::pthread_t,
+                              attr: *mut libc::pthread_attr_t) -> libc::c_int;
+    pub fn pthread_attr_getguardsize(attr: *const libc::pthread_attr_t,
+                                     guardsize: *mut libc::size_t) -> libc::c_int;
+    pub fn pthread_attr_getstack(attr: *const libc::pthread_attr_t,
+                                 stackaddr: *mut *mut libc::c_void,
+                                 stacksize: *mut libc::size_t) -> libc::c_int;
+}
+
+#[cfg(target_os = "macos")]
+extern {
+    pub fn pthread_self() -> libc::pthread_t;
+    pub fn pthread_get_stackaddr_np(thread: libc::pthread_t) -> *mut libc::c_void;
+    pub fn pthread_get_stacksize_np(thread: libc::pthread_t) -> libc::size_t;
+}
+
+extern {
+    fn pthread_create(native: *mut libc::pthread_t,
+                      attr: *const libc::pthread_attr_t,
+                      f: StartFn,
+                      value: *mut libc::c_void) -> libc::c_int;
+    fn pthread_join(native: libc::pthread_t,
+                    value: *mut *mut libc::c_void) -> libc::c_int;
+    fn pthread_attr_init(attr: *mut libc::pthread_attr_t) -> libc::c_int;
+    pub fn pthread_attr_destroy(attr: *mut libc::pthread_attr_t) -> libc::c_int;
+    fn pthread_attr_setstacksize(attr: *mut libc::pthread_attr_t,
+                                 stack_size: libc::size_t) -> libc::c_int;
+    fn pthread_attr_setdetachstate(attr: *mut libc::pthread_attr_t,
+                                   state: libc::c_int) -> libc::c_int;
+    fn pthread_detach(thread: libc::pthread_t) -> libc::c_int;
+    fn sched_yield() -> libc::c_int;
+}
diff --git a/src/libstd/sys/unix/thread_local.rs b/src/libstd/sys/unix/thread_local.rs
new file mode 100644
index 00000000000..b300e93eeb6
--- /dev/null
+++ b/src/libstd/sys/unix/thread_local.rs
@@ -0,0 +1,52 @@
+// 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.
+
+use prelude::*;
+use libc::c_int;
+
+pub type Key = pthread_key_t;
+
+#[inline]
+pub unsafe fn create(dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
+    let mut key = 0;
+    assert_eq!(pthread_key_create(&mut key, dtor), 0);
+    return key;
+}
+
+#[inline]
+pub unsafe fn set(key: Key, value: *mut u8) {
+    let r = pthread_setspecific(key, value);
+    debug_assert_eq!(r, 0);
+}
+
+#[inline]
+pub unsafe fn get(key: Key) -> *mut u8 {
+    pthread_getspecific(key)
+}
+
+#[inline]
+pub unsafe fn destroy(key: Key) {
+    let r = pthread_key_delete(key);
+    debug_assert_eq!(r, 0);
+}
+
+#[cfg(target_os = "macos")]
+type pthread_key_t = ::libc::c_ulong;
+
+#[cfg(not(target_os = "macos"))]
+type pthread_key_t = ::libc::c_uint;
+
+extern {
+    fn pthread_key_create(key: *mut pthread_key_t,
+                          dtor: Option<unsafe extern fn(*mut u8)>) -> c_int;
+    fn pthread_key_delete(key: pthread_key_t) -> c_int;
+    fn pthread_getspecific(key: pthread_key_t) -> *mut u8;
+    fn pthread_setspecific(key: pthread_key_t, value: *mut u8) -> c_int;
+}
diff --git a/src/libstd/sys/unix/timer.rs b/src/libstd/sys/unix/timer.rs
index 6ebbedb8e90..fe393b81e3d 100644
--- a/src/libstd/sys/unix/timer.rs
+++ b/src/libstd/sys/unix/timer.rs
@@ -46,7 +46,7 @@
 //!
 //! Note that all time units in this file are in *milliseconds*.
 
-pub use self::Req::*;
+use self::Req::*;
 
 use libc;
 use mem;
@@ -60,7 +60,7 @@ use sys_common::helper_thread::Helper;
 use prelude::*;
 use io::IoResult;
 
-helper_init!(static HELPER: Helper<Req>)
+helper_init! { static HELPER: Helper<Req> }
 
 pub trait Callback {
     fn call(&mut self);
diff --git a/src/libstd/sys/windows/backtrace.rs b/src/libstd/sys/windows/backtrace.rs
new file mode 100644
index 00000000000..42c8f7705e1
--- /dev/null
+++ b/src/libstd/sys/windows/backtrace.rs
@@ -0,0 +1,371 @@
+// 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.
+/// As always, windows has something very different than unix, we mainly want
+/// to avoid having to depend too much on libunwind for windows.
+///
+/// If you google around, you'll find a fair bit of references to built-in
+/// functions to get backtraces on windows. It turns out that most of these are
+/// in an external library called dbghelp. I was unable to find this library
+/// via `-ldbghelp`, but it is apparently normal to do the `dlopen` equivalent
+/// of it.
+///
+/// You'll also find that there's a function called CaptureStackBackTrace
+/// mentioned frequently (which is also easy to use), but sadly I didn't have a
+/// copy of that function in my mingw install (maybe it was broken?). Instead,
+/// this takes the route of using StackWalk64 in order to walk the stack.
+
+use c_str::CString;
+use intrinsics;
+use io::{IoResult, Writer};
+use libc;
+use mem;
+use ops::Drop;
+use option::Option::{Some, None};
+use path::Path;
+use result::Result::{Ok, Err};
+use sync::{StaticMutex, MUTEX_INIT};
+use slice::SliceExt;
+use str::StrExt;
+use dynamic_lib::DynamicLibrary;
+
+use sys_common::backtrace::*;
+
+#[allow(non_snake_case)]
+extern "system" {
+    fn GetCurrentProcess() -> libc::HANDLE;
+    fn GetCurrentThread() -> libc::HANDLE;
+    fn RtlCaptureContext(ctx: *mut arch::CONTEXT);
+}
+
+type SymFromAddrFn =
+    extern "system" fn(libc::HANDLE, u64, *mut u64,
+                       *mut SYMBOL_INFO) -> libc::BOOL;
+type SymInitializeFn =
+    extern "system" fn(libc::HANDLE, *mut libc::c_void,
+                       libc::BOOL) -> libc::BOOL;
+type SymCleanupFn =
+    extern "system" fn(libc::HANDLE) -> libc::BOOL;
+
+type StackWalk64Fn =
+    extern "system" fn(libc::DWORD, libc::HANDLE, libc::HANDLE,
+                       *mut STACKFRAME64, *mut arch::CONTEXT,
+                       *mut libc::c_void, *mut libc::c_void,
+                       *mut libc::c_void, *mut libc::c_void) -> libc::BOOL;
+
+const MAX_SYM_NAME: uint = 2000;
+const IMAGE_FILE_MACHINE_I386: libc::DWORD = 0x014c;
+const IMAGE_FILE_MACHINE_IA64: libc::DWORD = 0x0200;
+const IMAGE_FILE_MACHINE_AMD64: libc::DWORD = 0x8664;
+
+#[repr(C)]
+struct SYMBOL_INFO {
+    SizeOfStruct: libc::c_ulong,
+    TypeIndex: libc::c_ulong,
+    Reserved: [u64, ..2],
+    Index: libc::c_ulong,
+    Size: libc::c_ulong,
+    ModBase: u64,
+    Flags: libc::c_ulong,
+    Value: u64,
+    Address: u64,
+    Register: libc::c_ulong,
+    Scope: libc::c_ulong,
+    Tag: libc::c_ulong,
+    NameLen: libc::c_ulong,
+    MaxNameLen: libc::c_ulong,
+    // note that windows has this as 1, but it basically just means that
+    // the name is inline at the end of the struct. For us, we just bump
+    // the struct size up to MAX_SYM_NAME.
+    Name: [libc::c_char, ..MAX_SYM_NAME],
+}
+
+
+#[repr(C)]
+enum ADDRESS_MODE {
+    AddrMode1616,
+    AddrMode1632,
+    AddrModeReal,
+    AddrModeFlat,
+}
+
+struct ADDRESS64 {
+    Offset: u64,
+    Segment: u16,
+    Mode: ADDRESS_MODE,
+}
+
+struct STACKFRAME64 {
+    AddrPC: ADDRESS64,
+    AddrReturn: ADDRESS64,
+    AddrFrame: ADDRESS64,
+    AddrStack: ADDRESS64,
+    AddrBStore: ADDRESS64,
+    FuncTableEntry: *mut libc::c_void,
+    Params: [u64, ..4],
+    Far: libc::BOOL,
+    Virtual: libc::BOOL,
+    Reserved: [u64, ..3],
+    KdHelp: KDHELP64,
+}
+
+struct KDHELP64 {
+    Thread: u64,
+    ThCallbackStack: libc::DWORD,
+    ThCallbackBStore: libc::DWORD,
+    NextCallback: libc::DWORD,
+    FramePointer: libc::DWORD,
+    KiCallUserMode: u64,
+    KeUserCallbackDispatcher: u64,
+    SystemRangeStart: u64,
+    KiUserExceptionDispatcher: u64,
+    StackBase: u64,
+    StackLimit: u64,
+    Reserved: [u64, ..5],
+}
+
+#[cfg(target_arch = "x86")]
+mod arch {
+    use libc;
+
+    const MAXIMUM_SUPPORTED_EXTENSION: uint = 512;
+
+    #[repr(C)]
+    pub struct CONTEXT {
+        ContextFlags: libc::DWORD,
+        Dr0: libc::DWORD,
+        Dr1: libc::DWORD,
+        Dr2: libc::DWORD,
+        Dr3: libc::DWORD,
+        Dr6: libc::DWORD,
+        Dr7: libc::DWORD,
+        FloatSave: FLOATING_SAVE_AREA,
+        SegGs: libc::DWORD,
+        SegFs: libc::DWORD,
+        SegEs: libc::DWORD,
+        SegDs: libc::DWORD,
+        Edi: libc::DWORD,
+        Esi: libc::DWORD,
+        Ebx: libc::DWORD,
+        Edx: libc::DWORD,
+        Ecx: libc::DWORD,
+        Eax: libc::DWORD,
+        Ebp: libc::DWORD,
+        Eip: libc::DWORD,
+        SegCs: libc::DWORD,
+        EFlags: libc::DWORD,
+        Esp: libc::DWORD,
+        SegSs: libc::DWORD,
+        ExtendedRegisters: [u8, ..MAXIMUM_SUPPORTED_EXTENSION],
+    }
+
+    #[repr(C)]
+    pub struct FLOATING_SAVE_AREA {
+        ControlWord: libc::DWORD,
+        StatusWord: libc::DWORD,
+        TagWord: libc::DWORD,
+        ErrorOffset: libc::DWORD,
+        ErrorSelector: libc::DWORD,
+        DataOffset: libc::DWORD,
+        DataSelector: libc::DWORD,
+        RegisterArea: [u8, ..80],
+        Cr0NpxState: libc::DWORD,
+    }
+
+    pub fn init_frame(frame: &mut super::STACKFRAME64,
+                      ctx: &CONTEXT) -> libc::DWORD {
+        frame.AddrPC.Offset = ctx.Eip as u64;
+        frame.AddrPC.Mode = super::ADDRESS_MODE::AddrModeFlat;
+        frame.AddrStack.Offset = ctx.Esp as u64;
+        frame.AddrStack.Mode = super::ADDRESS_MODE::AddrModeFlat;
+        frame.AddrFrame.Offset = ctx.Ebp as u64;
+        frame.AddrFrame.Mode = super::ADDRESS_MODE::AddrModeFlat;
+        super::IMAGE_FILE_MACHINE_I386
+    }
+}
+
+#[cfg(target_arch = "x86_64")]
+mod arch {
+    use libc::{c_longlong, c_ulonglong};
+    use libc::types::os::arch::extra::{WORD, DWORD, DWORDLONG};
+    use simd;
+
+    #[repr(C)]
+    pub struct CONTEXT {
+        _align_hack: [simd::u64x2, ..0], // FIXME align on 16-byte
+        P1Home: DWORDLONG,
+        P2Home: DWORDLONG,
+        P3Home: DWORDLONG,
+        P4Home: DWORDLONG,
+        P5Home: DWORDLONG,
+        P6Home: DWORDLONG,
+
+        ContextFlags: DWORD,
+        MxCsr: DWORD,
+
+        SegCs: WORD,
+        SegDs: WORD,
+        SegEs: WORD,
+        SegFs: WORD,
+        SegGs: WORD,
+        SegSs: WORD,
+        EFlags: DWORD,
+
+        Dr0: DWORDLONG,
+        Dr1: DWORDLONG,
+        Dr2: DWORDLONG,
+        Dr3: DWORDLONG,
+        Dr6: DWORDLONG,
+        Dr7: DWORDLONG,
+
+        Rax: DWORDLONG,
+        Rcx: DWORDLONG,
+        Rdx: DWORDLONG,
+        Rbx: DWORDLONG,
+        Rsp: DWORDLONG,
+        Rbp: DWORDLONG,
+        Rsi: DWORDLONG,
+        Rdi: DWORDLONG,
+        R8:  DWORDLONG,
+        R9:  DWORDLONG,
+        R10: DWORDLONG,
+        R11: DWORDLONG,
+        R12: DWORDLONG,
+        R13: DWORDLONG,
+        R14: DWORDLONG,
+        R15: DWORDLONG,
+
+        Rip: DWORDLONG,
+
+        FltSave: FLOATING_SAVE_AREA,
+
+        VectorRegister: [M128A, .. 26],
+        VectorControl: DWORDLONG,
+
+        DebugControl: DWORDLONG,
+        LastBranchToRip: DWORDLONG,
+        LastBranchFromRip: DWORDLONG,
+        LastExceptionToRip: DWORDLONG,
+        LastExceptionFromRip: DWORDLONG,
+    }
+
+    #[repr(C)]
+    pub struct M128A {
+        _align_hack: [simd::u64x2, ..0], // FIXME align on 16-byte
+        Low:  c_ulonglong,
+        High: c_longlong
+    }
+
+    #[repr(C)]
+    pub struct FLOATING_SAVE_AREA {
+        _align_hack: [simd::u64x2, ..0], // FIXME align on 16-byte
+        _Dummy: [u8, ..512] // FIXME: Fill this out
+    }
+
+    pub fn init_frame(frame: &mut super::STACKFRAME64,
+                      ctx: &CONTEXT) -> DWORD {
+        frame.AddrPC.Offset = ctx.Rip as u64;
+        frame.AddrPC.Mode = super::ADDRESS_MODE::AddrModeFlat;
+        frame.AddrStack.Offset = ctx.Rsp as u64;
+        frame.AddrStack.Mode = super::ADDRESS_MODE::AddrModeFlat;
+        frame.AddrFrame.Offset = ctx.Rbp as u64;
+        frame.AddrFrame.Mode = super::ADDRESS_MODE::AddrModeFlat;
+        super::IMAGE_FILE_MACHINE_AMD64
+    }
+}
+
+#[repr(C)]
+struct Cleanup {
+    handle: libc::HANDLE,
+    SymCleanup: SymCleanupFn,
+}
+
+impl Drop for Cleanup {
+    fn drop(&mut self) { (self.SymCleanup)(self.handle); }
+}
+
+pub fn write(w: &mut Writer) -> IoResult<()> {
+    // According to windows documentation, all dbghelp functions are
+    // single-threaded.
+    static LOCK: StaticMutex = MUTEX_INIT;
+    let _g = unsafe { LOCK.lock() };
+
+    // Open up dbghelp.dll, we don't link to it explicitly because it can't
+    // always be found. Additionally, it's nice having fewer dependencies.
+    let path = Path::new("dbghelp.dll");
+    let lib = match DynamicLibrary::open(Some(&path)) {
+        Ok(lib) => lib,
+        Err(..) => return Ok(()),
+    };
+
+    macro_rules! sym{ ($e:expr, $t:ident) => (unsafe {
+        match lib.symbol($e) {
+            Ok(f) => mem::transmute::<*mut u8, $t>(f),
+            Err(..) => return Ok(())
+        }
+    }) }
+
+    // Fetch the symbols necessary from dbghelp.dll
+    let SymFromAddr = sym!("SymFromAddr", SymFromAddrFn);
+    let SymInitialize = sym!("SymInitialize", SymInitializeFn);
+    let SymCleanup = sym!("SymCleanup", SymCleanupFn);
+    let StackWalk64 = sym!("StackWalk64", StackWalk64Fn);
+
+    // Allocate necessary structures for doing the stack walk
+    let process = unsafe { GetCurrentProcess() };
+    let thread = unsafe { GetCurrentThread() };
+    let mut context: arch::CONTEXT = unsafe { intrinsics::init() };
+    unsafe { RtlCaptureContext(&mut context); }
+    let mut frame: STACKFRAME64 = unsafe { intrinsics::init() };
+    let image = arch::init_frame(&mut frame, &context);
+
+    // Initialize this process's symbols
+    let ret = SymInitialize(process, 0 as *mut libc::c_void, libc::TRUE);
+    if ret != libc::TRUE { return Ok(()) }
+    let _c = Cleanup { handle: process, SymCleanup: SymCleanup };
+
+    // And now that we're done with all the setup, do the stack walking!
+    let mut i = 0i;
+    try!(write!(w, "stack backtrace:\n"));
+    while StackWalk64(image, process, thread, &mut frame, &mut context,
+                      0 as *mut libc::c_void,
+                      0 as *mut libc::c_void,
+                      0 as *mut libc::c_void,
+                      0 as *mut libc::c_void) == libc::TRUE{
+        let addr = frame.AddrPC.Offset;
+        if addr == frame.AddrReturn.Offset || addr == 0 ||
+           frame.AddrReturn.Offset == 0 { break }
+
+        i += 1;
+        try!(write!(w, "  {:2}: {:#2$x}", i, addr, HEX_WIDTH));
+        let mut info: SYMBOL_INFO = unsafe { intrinsics::init() };
+        info.MaxNameLen = MAX_SYM_NAME as libc::c_ulong;
+        // the struct size in C.  the value is different to
+        // `size_of::<SYMBOL_INFO>() - MAX_SYM_NAME + 1` (== 81)
+        // due to struct alignment.
+        info.SizeOfStruct = 88;
+
+        let mut displacement = 0u64;
+        let ret = SymFromAddr(process, addr as u64, &mut displacement,
+                              &mut info);
+
+        if ret == libc::TRUE {
+            try!(write!(w, " - "));
+            let cstr = unsafe { CString::new(info.Name.as_ptr(), false) };
+            let bytes = cstr.as_bytes();
+            match cstr.as_str() {
+                Some(s) => try!(demangle(w, s)),
+                None => try!(w.write(bytes[..bytes.len()-1])),
+            }
+        }
+        try!(w.write(&['\n' as u8]));
+    }
+
+    Ok(())
+}
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index b8e9b1dca3a..d1cb91bcdb3 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -131,7 +131,7 @@ extern "system" {
 
 pub mod compat {
     use intrinsics::{atomic_store_relaxed, transmute};
-    use iter::Iterator;
+    use iter::IteratorExt;
     use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
     use prelude::*;
 
@@ -169,7 +169,7 @@ pub mod compat {
     ///
     /// Note that arguments unused by the fallback implementation should not be called `_` as
     /// they are used to be passed to the real function if available.
-    macro_rules! compat_fn(
+    macro_rules! compat_fn {
         ($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*)
                                       -> $rettype:ty $fallback:block) => (
             #[inline(always)]
@@ -195,7 +195,7 @@ pub mod compat {
         ($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*) $fallback:block) => (
             compat_fn!($module::$symbol($($argname: $argtype),*) -> () $fallback)
         )
-    )
+    }
 
     /// Compatibility layer for functions in `kernel32.dll`
     ///
@@ -211,20 +211,20 @@ pub mod compat {
             fn SetLastError(dwErrCode: DWORD);
         }
 
-        compat_fn!(kernel32::CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR,
+        compat_fn! { kernel32::CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR,
                                                  _lpTargetFileName: LPCWSTR,
                                                  _dwFlags: DWORD) -> BOOLEAN {
             unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); }
             0
-        })
+        } }
 
-        compat_fn!(kernel32::GetFinalPathNameByHandleW(_hFile: HANDLE,
+        compat_fn! { kernel32::GetFinalPathNameByHandleW(_hFile: HANDLE,
                                                        _lpszFilePath: LPCWSTR,
                                                        _cchFilePath: DWORD,
                                                        _dwFlags: DWORD) -> DWORD {
             unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); }
             0
-        })
+        } }
     }
 }
 
diff --git a/src/libstd/sys/windows/condvar.rs b/src/libstd/sys/windows/condvar.rs
new file mode 100644
index 00000000000..7f9d669c447
--- /dev/null
+++ b/src/libstd/sys/windows/condvar.rs
@@ -0,0 +1,62 @@
+// 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.
+
+use cell::UnsafeCell;
+use libc::{mod, DWORD};
+use os;
+use sys::mutex::{mod, Mutex};
+use sys::sync as ffi;
+use time::Duration;
+
+pub struct Condvar { inner: UnsafeCell<ffi::CONDITION_VARIABLE> }
+
+pub const CONDVAR_INIT: Condvar = Condvar {
+    inner: UnsafeCell { value: ffi::CONDITION_VARIABLE_INIT }
+};
+
+impl Condvar {
+    #[inline]
+    pub unsafe fn new() -> Condvar { CONDVAR_INIT }
+
+    #[inline]
+    pub unsafe fn wait(&self, mutex: &Mutex) {
+        let r = ffi::SleepConditionVariableCS(self.inner.get(),
+                                              mutex::raw(mutex),
+                                              libc::INFINITE);
+        debug_assert!(r != 0);
+    }
+
+    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
+        let r = ffi::SleepConditionVariableCS(self.inner.get(),
+                                              mutex::raw(mutex),
+                                              dur.num_milliseconds() as DWORD);
+        if r == 0 {
+            const ERROR_TIMEOUT: DWORD = 0x5B4;
+            debug_assert_eq!(os::errno() as uint, ERROR_TIMEOUT as uint);
+            false
+        } else {
+            true
+        }
+    }
+
+    #[inline]
+    pub unsafe fn notify_one(&self) {
+        ffi::WakeConditionVariable(self.inner.get())
+    }
+
+    #[inline]
+    pub unsafe fn notify_all(&self) {
+        ffi::WakeAllConditionVariable(self.inner.get())
+    }
+
+    pub unsafe fn destroy(&self) {
+        // ...
+    }
+}
diff --git a/src/libstd/sys/windows/ext.rs b/src/libstd/sys/windows/ext.rs
new file mode 100644
index 00000000000..049aca3f590
--- /dev/null
+++ b/src/libstd/sys/windows/ext.rs
@@ -0,0 +1,100 @@
+// 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.
+
+//! Experimental extensions to `std` for Windows.
+//!
+//! For now, this module is limited to extracting handles, file
+//! descriptors, and sockets, but its functionality will grow over
+//! time.
+
+#![experimental]
+
+use sys_common::AsInner;
+use libc;
+
+use io;
+
+/// Raw HANDLEs.
+pub type Handle = libc::HANDLE;
+
+/// Raw SOCKETs.
+pub type Socket = libc::SOCKET;
+
+/// Extract raw handles.
+pub trait AsRawHandle {
+    /// Extract the raw handle, without taking any ownership.
+    fn as_raw_handle(&self) -> Handle;
+}
+
+impl AsRawHandle for io::fs::File {
+    fn as_raw_handle(&self) -> Handle {
+        self.as_inner().handle()
+    }
+}
+
+impl AsRawHandle for io::pipe::PipeStream {
+    fn as_raw_handle(&self) -> Handle {
+        self.as_inner().handle()
+    }
+}
+
+impl AsRawHandle for io::net::pipe::UnixStream {
+    fn as_raw_handle(&self) -> Handle {
+        self.as_inner().handle()
+    }
+}
+
+impl AsRawHandle for io::net::pipe::UnixListener {
+    fn as_raw_handle(&self) -> Handle {
+        self.as_inner().handle()
+    }
+}
+
+impl AsRawHandle for io::net::pipe::UnixAcceptor {
+    fn as_raw_handle(&self) -> Handle {
+        self.as_inner().handle()
+    }
+}
+
+/// Extract raw sockets.
+pub trait AsRawSocket {
+    fn as_raw_socket(&self) -> Socket;
+}
+
+impl AsRawSocket for io::net::tcp::TcpStream {
+    fn as_raw_socket(&self) -> Socket {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawSocket for io::net::tcp::TcpListener {
+    fn as_raw_socket(&self) -> Socket {
+        self.as_inner().socket()
+    }
+}
+
+impl AsRawSocket for io::net::tcp::TcpAcceptor {
+    fn as_raw_socket(&self) -> Socket {
+        self.as_inner().socket()
+    }
+}
+
+impl AsRawSocket for io::net::udp::UdpSocket {
+    fn as_raw_socket(&self) -> Socket {
+        self.as_inner().fd()
+    }
+}
+
+/// A prelude for conveniently writing platform-specific code.
+///
+/// Includes all extension traits, and some important type definitions.
+pub mod prelude {
+    pub use super::{Socket, Handle, AsRawSocket, AsRawHandle};
+}
diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs
index b881eb2d495..15eddd569be 100644
--- a/src/libstd/sys/windows/fs.rs
+++ b/src/libstd/sys/windows/fs.rs
@@ -15,7 +15,7 @@ use libc::{mod, c_int};
 
 use c_str::CString;
 use mem;
-use os::windows::fill_utf16_buf_and_decode;
+use sys::os::fill_utf16_buf_and_decode;
 use path;
 use ptr;
 use str;
@@ -23,13 +23,13 @@ use io;
 
 use prelude::*;
 use sys;
+use sys::os;
 use sys_common::{keep_going, eof, mkerr_libc};
 
 use io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode};
-use io::{IoResult, IoError, FileStat, SeekStyle, Seek, Writer, Reader};
+use io::{IoResult, IoError, FileStat, SeekStyle};
 use io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append};
 
-pub use path::WindowsPath as Path;
 pub type fd_t = libc::c_int;
 
 pub struct FileDesc {
@@ -131,7 +131,7 @@ impl FileDesc {
         return ret;
     }
 
-    pub fn fstat(&mut self) -> IoResult<io::FileStat> {
+    pub fn fstat(&self) -> IoResult<io::FileStat> {
         let mut stat: libc::stat = unsafe { mem::zeroed() };
         match unsafe { libc::fstat(self.fd(), &mut stat) } {
             0 => Ok(mkstat(&stat)),
@@ -263,7 +263,7 @@ pub fn readdir(p: &Path) -> IoResult<Vec<Path>> {
             let mut more_files = 1 as libc::BOOL;
             while more_files != 0 {
                 {
-                    let filename = str::truncate_utf16_at_nul(&wfd.cFileName);
+                    let filename = os::truncate_utf16_at_nul(&wfd.cFileName);
                     match String::from_utf16(filename) {
                         Some(filename) => paths.push(Path::new(filename)),
                         None => {
@@ -376,8 +376,8 @@ pub fn readlink(p: &Path) -> IoResult<Path> {
                                   libc::VOLUME_NAME_DOS)
     });
     let ret = match ret {
-        Some(ref s) if s.as_slice().starts_with(r"\\?\") => { // "
-            Ok(Path::new(s.as_slice().slice_from(4)))
+        Some(ref s) if s.starts_with(r"\\?\") => { // "
+            Ok(Path::new(s.slice_from(4)))
         }
         Some(s) => Ok(Path::new(s)),
         None => Err(super::last_error()),
@@ -407,12 +407,12 @@ fn mkstat(stat: &libc::stat) -> FileStat {
     FileStat {
         size: stat.st_size as u64,
         kind: match (stat.st_mode as libc::c_int) & libc::S_IFMT {
-            libc::S_IFREG => io::TypeFile,
-            libc::S_IFDIR => io::TypeDirectory,
-            libc::S_IFIFO => io::TypeNamedPipe,
-            libc::S_IFBLK => io::TypeBlockSpecial,
-            libc::S_IFLNK => io::TypeSymlink,
-            _ => io::TypeUnknown,
+            libc::S_IFREG => io::FileType::RegularFile,
+            libc::S_IFDIR => io::FileType::Directory,
+            libc::S_IFIFO => io::FileType::NamedPipe,
+            libc::S_IFBLK => io::FileType::BlockSpecial,
+            libc::S_IFLNK => io::FileType::Symlink,
+            _ => io::FileType::Unknown,
         },
         perm: FilePermission::from_bits_truncate(stat.st_mode as u32),
         created: stat.st_ctime as u64,
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs
index 815ace21f87..6924687d8c4 100644
--- a/src/libstd/sys/windows/mod.rs
+++ b/src/libstd/sys/windows/mod.rs
@@ -24,25 +24,36 @@ use prelude::*;
 use io::{mod, IoResult, IoError};
 use sync::{Once, ONCE_INIT};
 
-macro_rules! helper_init( (static $name:ident: Helper<$m:ty>) => (
+macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
     static $name: Helper<$m> = Helper {
-        lock: ::rustrt::mutex::NATIVE_MUTEX_INIT,
+        lock: ::sync::MUTEX_INIT,
+        cond: ::sync::CONDVAR_INIT,
         chan: ::cell::UnsafeCell { value: 0 as *mut Sender<$m> },
         signal: ::cell::UnsafeCell { value: 0 },
         initialized: ::cell::UnsafeCell { value: false },
+        shutdown: ::cell::UnsafeCell { value: false },
     };
-) )
+) }
 
+pub mod backtrace;
 pub mod c;
+pub mod ext;
+pub mod condvar;
 pub mod fs;
+pub mod helper_signal;
+pub mod mutex;
 pub mod os;
-pub mod tcp;
-pub mod udp;
 pub mod pipe;
-pub mod helper_signal;
 pub mod process;
+pub mod rwlock;
+pub mod sync;
+pub mod stack_overflow;
+pub mod tcp;
+pub mod thread;
+pub mod thread_local;
 pub mod timer;
 pub mod tty;
+pub mod udp;
 
 pub mod addrinfo {
     pub use sys_common::net::get_host_addresses;
@@ -130,7 +141,7 @@ pub fn decode_error_detailed(errno: i32) -> IoError {
 }
 
 #[inline]
-pub fn retry<I> (f: || -> I) -> I { f() } // PR rust-lang/rust/#17020
+pub fn retry<I, F>(f: F) -> I where F: FnOnce() -> I { f() } // PR rust-lang/rust/#17020
 
 pub fn ms_to_timeval(ms: u64) -> libc::timeval {
     libc::timeval {
diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs
new file mode 100644
index 00000000000..ddd89070ed5
--- /dev/null
+++ b/src/libstd/sys/windows/mutex.rs
@@ -0,0 +1,78 @@
+// 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.
+
+use prelude::*;
+
+use sync::atomic;
+use alloc::{mod, heap};
+
+use libc::DWORD;
+use sys::sync as ffi;
+
+const SPIN_COUNT: DWORD = 4000;
+
+pub struct Mutex { inner: atomic::AtomicUint }
+
+pub const MUTEX_INIT: Mutex = Mutex { inner: atomic::INIT_ATOMIC_UINT };
+
+#[inline]
+pub unsafe fn raw(m: &Mutex) -> ffi::LPCRITICAL_SECTION {
+    m.get()
+}
+
+impl Mutex {
+    #[inline]
+    pub unsafe fn new() -> Mutex {
+        Mutex { inner: atomic::AtomicUint::new(init_lock() as uint) }
+    }
+    #[inline]
+    pub unsafe fn lock(&self) {
+        ffi::EnterCriticalSection(self.get())
+    }
+    #[inline]
+    pub unsafe fn try_lock(&self) -> bool {
+        ffi::TryEnterCriticalSection(self.get()) != 0
+    }
+    #[inline]
+    pub unsafe fn unlock(&self) {
+        ffi::LeaveCriticalSection(self.get())
+    }
+    pub unsafe fn destroy(&self) {
+        let lock = self.inner.swap(0, atomic::SeqCst);
+        if lock != 0 { free_lock(lock as ffi::LPCRITICAL_SECTION) }
+    }
+
+    unsafe fn get(&self) -> ffi::LPCRITICAL_SECTION {
+        match self.inner.load(atomic::SeqCst) {
+            0 => {}
+            n => return n as ffi::LPCRITICAL_SECTION
+        }
+        let lock = init_lock();
+        match self.inner.compare_and_swap(0, lock as uint, atomic::SeqCst) {
+            0 => return lock as ffi::LPCRITICAL_SECTION,
+            _ => {}
+        }
+        free_lock(lock);
+        return self.inner.load(atomic::SeqCst) as ffi::LPCRITICAL_SECTION;
+    }
+}
+
+unsafe fn init_lock() -> ffi::LPCRITICAL_SECTION {
+    let block = heap::allocate(ffi::CRITICAL_SECTION_SIZE, 8)
+                        as ffi::LPCRITICAL_SECTION;
+    if block.is_null() { alloc::oom() }
+    ffi::InitializeCriticalSectionAndSpinCount(block, SPIN_COUNT);
+    return block;
+}
+
+unsafe fn free_lock(h: ffi::LPCRITICAL_SECTION) {
+    ffi::DeleteCriticalSection(h);
+    heap::deallocate(h as *mut _, ffi::CRITICAL_SECTION_SIZE, 8);
+}
diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs
index aa43b42e746..e007b46b261 100644
--- a/src/libstd/sys/windows/os.rs
+++ b/src/libstd/sys/windows/os.rs
@@ -8,17 +8,38 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+//! Implementation of `std::os` functionality for Windows
+
 // FIXME: move various extern bindings from here into liblibc or
 // something similar
 
-use libc;
-use libc::{c_int, c_char, c_void};
 use prelude::*;
+
+use fmt;
 use io::{IoResult, IoError};
-use sys::fs::FileDesc;
+use libc::{c_int, c_char, c_void};
+use libc;
+use os;
+use path::BytesContainer;
 use ptr;
+use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst};
+use sys::fs::FileDesc;
+use slice;
 
 use os::TMPBUF_SZ;
+use libc::types::os::arch::extra::DWORD;
+
+const BUF_BYTES : uint = 2048u;
+
+/// Return a slice of `v` ending at (and not including) the first NUL
+/// (0).
+pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] {
+    match v.iter().position(|c| *c == 0) {
+        // don't include the 0
+        Some(i) => v[..i],
+        None => v
+    }
+}
 
 pub fn errno() -> uint {
     use libc::types::os::arch::extra::DWORD;
@@ -76,7 +97,7 @@ pub fn error_string(errnum: i32) -> String {
             return format!("OS Error {} (FormatMessageW() returned error {})", errnum, fm_err);
         }
 
-        let msg = String::from_utf16(::str::truncate_utf16_at_nul(&buf));
+        let msg = String::from_utf16(truncate_utf16_at_nul(&buf));
         match msg {
             Some(msg) => format!("OS Error {}: {}", errnum, msg),
             None => format!("OS Error {} (FormatMessageW() returned invalid UTF-16)", errnum),
@@ -101,3 +122,212 @@ pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
         _ => Err(IoError::last_error()),
     }
 }
+
+pub fn fill_utf16_buf_and_decode(f: |*mut u16, DWORD| -> DWORD) -> Option<String> {
+    unsafe {
+        let mut n = TMPBUF_SZ as DWORD;
+        let mut res = None;
+        let mut done = false;
+        while !done {
+            let mut buf = Vec::from_elem(n as uint, 0u16);
+            let k = f(buf.as_mut_ptr(), n);
+            if k == (0 as DWORD) {
+                done = true;
+            } else if k == n &&
+                      libc::GetLastError() ==
+                      libc::ERROR_INSUFFICIENT_BUFFER as DWORD {
+                n *= 2 as DWORD;
+            } else if k >= n {
+                n = k;
+            } else {
+                done = true;
+            }
+            if k != 0 && done {
+                let sub = buf.slice(0, k as uint);
+                // We want to explicitly catch the case when the
+                // closure returned invalid UTF-16, rather than
+                // set `res` to None and continue.
+                let s = String::from_utf16(sub)
+                    .expect("fill_utf16_buf_and_decode: closure created invalid UTF-16");
+                res = Some(s)
+            }
+        }
+        return res;
+    }
+}
+
+pub fn getcwd() -> IoResult<Path> {
+    use libc::DWORD;
+    use libc::GetCurrentDirectoryW;
+    use io::OtherIoError;
+
+    let mut buf = [0 as u16, ..BUF_BYTES];
+    unsafe {
+        if libc::GetCurrentDirectoryW(buf.len() as DWORD, buf.as_mut_ptr()) == 0 as DWORD {
+            return Err(IoError::last_error());
+        }
+    }
+
+    match String::from_utf16(truncate_utf16_at_nul(&buf)) {
+        Some(ref cwd) => Ok(Path::new(cwd)),
+        None => Err(IoError {
+            kind: OtherIoError,
+            desc: "GetCurrentDirectoryW returned invalid UTF-16",
+            detail: None,
+        }),
+    }
+}
+
+pub unsafe fn get_env_pairs() -> Vec<Vec<u8>> {
+    use libc::funcs::extra::kernel32::{
+        GetEnvironmentStringsW,
+        FreeEnvironmentStringsW
+    };
+    let ch = GetEnvironmentStringsW();
+    if ch as uint == 0 {
+        panic!("os::env() failure getting env string from OS: {}",
+               os::last_os_error());
+    }
+    // Here, we lossily decode the string as UTF16.
+    //
+    // The docs suggest that the result should be in Unicode, but
+    // Windows doesn't guarantee it's actually UTF16 -- it doesn't
+    // validate the environment string passed to CreateProcess nor
+    // SetEnvironmentVariable.  Yet, it's unlikely that returning a
+    // raw u16 buffer would be of practical use since the result would
+    // be inherently platform-dependent and introduce additional
+    // complexity to this code.
+    //
+    // Using the non-Unicode version of GetEnvironmentStrings is even
+    // worse since the result is in an OEM code page.  Characters that
+    // can't be encoded in the code page would be turned into question
+    // marks.
+    let mut result = Vec::new();
+    let mut i = 0;
+    while *ch.offset(i) != 0 {
+        let p = &*ch.offset(i);
+        let mut len = 0;
+        while *(p as *const _).offset(len) != 0 {
+            len += 1;
+        }
+        let p = p as *const u16;
+        let s = slice::from_raw_buf(&p, len as uint);
+        result.push(String::from_utf16_lossy(s).into_bytes());
+        i += len as int + 1;
+    }
+    FreeEnvironmentStringsW(ch);
+    result
+}
+
+pub fn split_paths(unparsed: &[u8]) -> Vec<Path> {
+    // On Windows, the PATH environment variable is semicolon separated.  Double
+    // quotes are used as a way of introducing literal semicolons (since
+    // c:\some;dir is a valid Windows path). Double quotes are not themselves
+    // permitted in path names, so there is no way to escape a double quote.
+    // Quoted regions can appear in arbitrary locations, so
+    //
+    //   c:\foo;c:\som"e;di"r;c:\bar
+    //
+    // Should parse as [c:\foo, c:\some;dir, c:\bar].
+    //
+    // (The above is based on testing; there is no clear reference available
+    // for the grammar.)
+
+    let mut parsed = Vec::new();
+    let mut in_progress = Vec::new();
+    let mut in_quote = false;
+
+    for b in unparsed.iter() {
+        match *b {
+            b';' if !in_quote => {
+                parsed.push(Path::new(in_progress.as_slice()));
+                in_progress.truncate(0)
+            }
+            b'"' => {
+                in_quote = !in_quote;
+            }
+            _  => {
+                in_progress.push(*b);
+            }
+        }
+    }
+    parsed.push(Path::new(in_progress));
+    parsed
+}
+
+pub fn join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
+    let mut joined = Vec::new();
+    let sep = b';';
+
+    for (i, path) in paths.iter().map(|p| p.container_as_bytes()).enumerate() {
+        if i > 0 { joined.push(sep) }
+        if path.contains(&b'"') {
+            return Err("path segment contains `\"`");
+        } else if path.contains(&sep) {
+            joined.push(b'"');
+            joined.push_all(path);
+            joined.push(b'"');
+        } else {
+            joined.push_all(path);
+        }
+    }
+
+    Ok(joined)
+}
+
+pub fn load_self() -> Option<Vec<u8>> {
+    unsafe {
+        fill_utf16_buf_and_decode(|buf, sz| {
+            libc::GetModuleFileNameW(0u as libc::DWORD, buf, sz)
+        }).map(|s| s.to_string().into_bytes())
+    }
+}
+
+pub fn chdir(p: &Path) -> IoResult<()> {
+    let mut p = p.as_str().unwrap().utf16_units().collect::<Vec<u16>>();
+    p.push(0);
+
+    unsafe {
+        match libc::SetCurrentDirectoryW(p.as_ptr()) != (0 as libc::BOOL) {
+            true => Ok(()),
+            false => Err(IoError::last_error()),
+        }
+    }
+}
+
+pub fn page_size() -> uint {
+    use mem;
+    unsafe {
+        let mut info = mem::zeroed();
+        libc::GetSystemInfo(&mut info);
+
+        return info.dwPageSize as uint;
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::truncate_utf16_at_nul;
+
+    #[test]
+    fn test_truncate_utf16_at_nul() {
+        let v = [];
+        let b: &[u16] = &[];
+        assert_eq!(truncate_utf16_at_nul(&v), b);
+
+        let v = [0, 2, 3];
+        assert_eq!(truncate_utf16_at_nul(&v), b);
+
+        let v = [1, 0, 3];
+        let b: &[u16] = &[1];
+        assert_eq!(truncate_utf16_at_nul(&v), b);
+
+        let v = [1, 2, 0];
+        let b: &[u16] = &[1, 2];
+        assert_eq!(truncate_utf16_at_nul(&v), b);
+
+        let v = [1, 2, 3];
+        let b: &[u16] = &[1, 2, 3];
+        assert_eq!(truncate_utf16_at_nul(&v), b);
+    }
+}
diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs
index a623c2cd8e2..bf658d0efd0 100644
--- a/src/libstd/sys/windows/pipe.rs
+++ b/src/libstd/sys/windows/pipe.rs
@@ -89,8 +89,7 @@ use libc;
 use c_str::CString;
 use mem;
 use ptr;
-use sync::atomic;
-use rustrt::mutex;
+use sync::{atomic, Mutex};
 use io::{mod, IoError, IoResult};
 use prelude::*;
 
@@ -126,7 +125,7 @@ impl Drop for Event {
 
 struct Inner {
     handle: libc::HANDLE,
-    lock: mutex::NativeMutex,
+    lock: Mutex<()>,
     read_closed: atomic::AtomicBool,
     write_closed: atomic::AtomicBool,
 }
@@ -135,7 +134,7 @@ impl Inner {
     fn new(handle: libc::HANDLE) -> Inner {
         Inner {
             handle: handle,
-            lock: unsafe { mutex::NativeMutex::new() },
+            lock: Mutex::new(()),
             read_closed: atomic::AtomicBool::new(false),
             write_closed: atomic::AtomicBool::new(false),
         }
@@ -329,7 +328,7 @@ impl UnixStream {
         }
     }
 
-    fn handle(&self) -> libc::HANDLE { self.inner.handle }
+    pub fn handle(&self) -> libc::HANDLE { self.inner.handle }
 
     fn read_closed(&self) -> bool {
         self.inner.read_closed.load(atomic::SeqCst)
@@ -585,6 +584,10 @@ impl UnixListener {
             }),
         })
     }
+
+    pub fn handle(&self) -> libc::HANDLE {
+        self.handle
+    }
 }
 
 impl Drop for UnixListener {
@@ -729,6 +732,10 @@ impl UnixAcceptor {
             Ok(())
         }
     }
+
+    pub fn handle(&self) -> libc::HANDLE {
+        self.listener.handle()
+    }
 }
 
 impl Clone for UnixAcceptor {
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index 3fb5ee34356..0c2c76077dd 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -26,20 +26,17 @@ use sys::fs;
 use sys::{mod, retry, c, wouldblock, set_nonblocking, ms_to_timeval, timer};
 use sys::fs::FileDesc;
 use sys_common::helper_thread::Helper;
-use sys_common::{AsFileDesc, mkerr_libc, timeout};
+use sys_common::{AsInner, mkerr_libc, timeout};
 
 use io::fs::PathExtensions;
-use string::String;
 
 pub use sys_common::ProcessConfig;
 
-/**
- * A value representing a child process.
- *
- * The lifetime of this value is linked to the lifetime of the actual
- * process - the Process destructor calls self.finish() which waits
- * for the process to terminate.
- */
+/// A value representing a child process.
+///
+/// The lifetime of this value is linked to the lifetime of the actual
+/// process - the Process destructor calls self.finish() which waits
+/// for the process to terminate.
 pub struct Process {
     /// The unique id of the process (this should never be negative).
     pid: pid_t,
@@ -105,7 +102,7 @@ impl Process {
     pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
                               out_fd: Option<P>, err_fd: Option<P>)
                               -> IoResult<Process>
-        where C: ProcessConfig<K, V>, P: AsFileDesc,
+        where C: ProcessConfig<K, V>, P: AsInner<FileDesc>,
               K: BytesContainer + Eq + Hash, V: BytesContainer
     {
         use libc::types::os::arch::extra::{DWORD, HANDLE, STARTUPINFO};
@@ -124,8 +121,8 @@ impl Process {
         use libc::funcs::extra::msvcrt::get_osfhandle;
 
         use mem;
-        use iter::Iterator;
-        use str::StrPrelude;
+        use iter::{Iterator, IteratorExt};
+        use str::StrExt;
 
         if cfg.gid().is_some() || cfg.uid().is_some() {
             return Err(IoError {
@@ -195,7 +192,7 @@ impl Process {
                         }
                     }
                     Some(ref fd) => {
-                        let orig = get_osfhandle(fd.as_fd().fd()) as HANDLE;
+                        let orig = get_osfhandle(fd.as_inner().fd()) as HANDLE;
                         if orig == INVALID_HANDLE_VALUE {
                             return Err(super::last_error())
                         }
@@ -225,7 +222,7 @@ impl Process {
 
             with_envp(cfg.env(), |envp| {
                 with_dirp(cfg.cwd(), |dirp| {
-                    let mut cmd_str: Vec<u16> = cmd_str.as_slice().utf16_units().collect();
+                    let mut cmd_str: Vec<u16> = cmd_str.utf16_units().collect();
                     cmd_str.push(0);
                     let created = CreateProcessW(ptr::null(),
                                                  cmd_str.as_mut_ptr(),
@@ -263,16 +260,14 @@ impl Process {
         }
     }
 
-    /**
-     * Waits for a process to exit and returns the exit code, failing
-     * if there is no process with the specified id.
-     *
-     * Note that this is private to avoid race conditions on unix where if
-     * a user calls waitpid(some_process.get_id()) then some_process.finish()
-     * and some_process.destroy() and some_process.finalize() will then either
-     * operate on a none-existent process or, even worse, on a newer process
-     * with the same id.
-     */
+    /// Waits for a process to exit and returns the exit code, failing
+    /// if there is no process with the specified id.
+    ///
+    /// Note that this is private to avoid race conditions on unix where if
+    /// a user calls waitpid(some_process.get_id()) then some_process.finish()
+    /// and some_process.destroy() and some_process.finalize() will then either
+    /// operate on a none-existent process or, even worse, on a newer process
+    /// with the same id.
     pub fn wait(&self, deadline: u64) -> IoResult<ProcessExit> {
         use libc::types::os::arch::extra::DWORD;
         use libc::consts::os::extra::{
@@ -422,9 +417,8 @@ fn make_command_line(prog: &CString, args: &[CString]) -> String {
     }
 }
 
-fn with_envp<K, V, T>(env: Option<&collections::HashMap<K, V>>,
-                      cb: |*mut c_void| -> T) -> T
-    where K: BytesContainer + Eq + Hash, V: BytesContainer
+fn with_envp<K, V, T, F>(env: Option<&collections::HashMap<K, V>>, cb: F) -> T where
+    K: BytesContainer + Eq + Hash, V: BytesContainer, F: FnOnce(*mut c_void) -> T,
 {
     // On Windows we pass an "environment block" which is not a char**, but
     // rather a concatenation of null-terminated k=v\0 sequences, with a final
@@ -435,9 +429,9 @@ fn with_envp<K, V, T>(env: Option<&collections::HashMap<K, V>>,
 
             for pair in env.iter() {
                 let kv = format!("{}={}",
-                                 pair.ref0().container_as_str().unwrap(),
-                                 pair.ref1().container_as_str().unwrap());
-                blk.extend(kv.as_slice().utf16_units());
+                                 pair.0.container_as_str().unwrap(),
+                                 pair.1.container_as_str().unwrap());
+                blk.extend(kv.utf16_units());
                 blk.push(0);
             }
 
@@ -449,7 +443,9 @@ fn with_envp<K, V, T>(env: Option<&collections::HashMap<K, V>>,
     }
 }
 
-fn with_dirp<T>(d: Option<&CString>, cb: |*const u16| -> T) -> T {
+fn with_dirp<T, F>(d: Option<&CString>, cb: F) -> T where
+    F: FnOnce(*const u16) -> T,
+{
     match d {
       Some(dir) => {
           let dir_str = dir.as_str()
@@ -488,24 +484,24 @@ mod tests {
 
         assert_eq!(
             test_wrapper("prog", &["aaa", "bbb", "ccc"]),
-            "prog aaa bbb ccc".to_string()
+            "prog aaa bbb ccc"
         );
 
         assert_eq!(
             test_wrapper("C:\\Program Files\\blah\\blah.exe", &["aaa"]),
-            "\"C:\\Program Files\\blah\\blah.exe\" aaa".to_string()
+            "\"C:\\Program Files\\blah\\blah.exe\" aaa"
         );
         assert_eq!(
             test_wrapper("C:\\Program Files\\test", &["aa\"bb"]),
-            "\"C:\\Program Files\\test\" aa\\\"bb".to_string()
+            "\"C:\\Program Files\\test\" aa\\\"bb"
         );
         assert_eq!(
             test_wrapper("echo", &["a b c"]),
-            "echo \"a b c\"".to_string()
+            "echo \"a b c\""
         );
         assert_eq!(
-            test_wrapper("\u03c0\u042f\u97f3\u00e6\u221e", &[]),
-            "\u03c0\u042f\u97f3\u00e6\u221e".to_string()
+            test_wrapper("\u{03c0}\u{042f}\u{97f3}\u{00e6}\u{221e}", &[]),
+            "\u{03c0}\u{042f}\u{97f3}\u{00e6}\u{221e}"
         );
     }
 }
diff --git a/src/libstd/sys/windows/rwlock.rs b/src/libstd/sys/windows/rwlock.rs
new file mode 100644
index 00000000000..88ce85c39f6
--- /dev/null
+++ b/src/libstd/sys/windows/rwlock.rs
@@ -0,0 +1,53 @@
+// 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.
+
+use cell::UnsafeCell;
+use sys::sync as ffi;
+
+pub struct RWLock { inner: UnsafeCell<ffi::SRWLOCK> }
+
+pub const RWLOCK_INIT: RWLock = RWLock {
+    inner: UnsafeCell { value: ffi::SRWLOCK_INIT }
+};
+
+impl RWLock {
+    #[inline]
+    pub unsafe fn new() -> RWLock { RWLOCK_INIT }
+
+    #[inline]
+    pub unsafe fn read(&self) {
+        ffi::AcquireSRWLockShared(self.inner.get())
+    }
+    #[inline]
+    pub unsafe fn try_read(&self) -> bool {
+        ffi::TryAcquireSRWLockShared(self.inner.get()) != 0
+    }
+    #[inline]
+    pub unsafe fn write(&self) {
+        ffi::AcquireSRWLockExclusive(self.inner.get())
+    }
+    #[inline]
+    pub unsafe fn try_write(&self) -> bool {
+        ffi::TryAcquireSRWLockExclusive(self.inner.get()) != 0
+    }
+    #[inline]
+    pub unsafe fn read_unlock(&self) {
+        ffi::ReleaseSRWLockShared(self.inner.get())
+    }
+    #[inline]
+    pub unsafe fn write_unlock(&self) {
+        ffi::ReleaseSRWLockExclusive(self.inner.get())
+    }
+
+    #[inline]
+    pub unsafe fn destroy(&self) {
+        // ...
+    }
+}
diff --git a/src/libstd/sys/windows/stack_overflow.rs b/src/libstd/sys/windows/stack_overflow.rs
new file mode 100644
index 00000000000..bdf2e0bccb1
--- /dev/null
+++ b/src/libstd/sys/windows/stack_overflow.rs
@@ -0,0 +1,115 @@
+// 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.
+
+use rt::util::report_overflow;
+use core::prelude::*;
+use ptr;
+use mem;
+use libc;
+use libc::types::os::arch::extra::{LPVOID, DWORD, LONG, BOOL};
+use sys_common::{stack, thread_info};
+
+pub struct Handler {
+    _data: *mut libc::c_void
+}
+
+impl Handler {
+    pub unsafe fn new() -> Handler {
+        make_handler()
+    }
+}
+
+impl Drop for Handler {
+    fn drop(&mut self) {}
+}
+
+// get_task_info is called from an exception / signal handler.
+// It returns the guard page of the current task or 0 if that
+// guard page doesn't exist. None is returned if there's currently
+// no local task.
+unsafe fn get_task_guard_page() -> uint {
+    thread_info::stack_guard()
+}
+
+// This is initialized in init() and only read from after
+static mut PAGE_SIZE: uint = 0;
+
+#[no_stack_check]
+extern "system" fn vectored_handler(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG {
+    unsafe {
+        let rec = &(*(*ExceptionInfo).ExceptionRecord);
+        let code = rec.ExceptionCode;
+
+        if code != EXCEPTION_STACK_OVERFLOW {
+            return EXCEPTION_CONTINUE_SEARCH;
+        }
+
+        // We're calling into functions with stack checks,
+        // however stack checks by limit should be disabled on Windows
+        stack::record_sp_limit(0);
+
+        report_overflow();
+
+        EXCEPTION_CONTINUE_SEARCH
+    }
+}
+
+pub unsafe fn init() {
+    let mut info = mem::zeroed();
+    libc::GetSystemInfo(&mut info);
+    PAGE_SIZE = info.dwPageSize as uint;
+
+    if AddVectoredExceptionHandler(0, vectored_handler) == ptr::null_mut() {
+        panic!("failed to install exception handler");
+    }
+
+    mem::forget(make_handler());
+}
+
+pub unsafe fn cleanup() {
+}
+
+pub unsafe fn make_handler() -> Handler {
+    if SetThreadStackGuarantee(&mut 0x5000) == 0 {
+        panic!("failed to reserve stack space for exception handling");
+    }
+
+    Handler { _data: 0i as *mut libc::c_void }
+}
+
+pub struct EXCEPTION_RECORD {
+    pub ExceptionCode: DWORD,
+    pub ExceptionFlags: DWORD,
+    pub ExceptionRecord: *mut EXCEPTION_RECORD,
+    pub ExceptionAddress: LPVOID,
+    pub NumberParameters: DWORD,
+    pub ExceptionInformation: [LPVOID, ..EXCEPTION_MAXIMUM_PARAMETERS]
+}
+
+pub struct EXCEPTION_POINTERS {
+    pub ExceptionRecord: *mut EXCEPTION_RECORD,
+    pub ContextRecord: LPVOID
+}
+
+pub type PVECTORED_EXCEPTION_HANDLER = extern "system"
+        fn(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG;
+
+pub type ULONG = libc::c_ulong;
+
+const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
+const EXCEPTION_MAXIMUM_PARAMETERS: uint = 15;
+const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
+
+extern "system" {
+    fn AddVectoredExceptionHandler(FirstHandler: ULONG,
+                                   VectoredHandler: PVECTORED_EXCEPTION_HANDLER)
+                                  -> LPVOID;
+    fn SetThreadStackGuarantee(StackSizeInBytes: *mut ULONG) -> BOOL;
+}
diff --git a/src/libstd/sys/windows/sync.rs b/src/libstd/sys/windows/sync.rs
new file mode 100644
index 00000000000..cbca47912b5
--- /dev/null
+++ b/src/libstd/sys/windows/sync.rs
@@ -0,0 +1,58 @@
+// 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.
+
+use libc::{BOOL, DWORD, c_void, LPVOID};
+use libc::types::os::arch::extra::BOOLEAN;
+
+pub type LPCRITICAL_SECTION = *mut c_void;
+pub type LPCONDITION_VARIABLE = *mut CONDITION_VARIABLE;
+pub type LPSRWLOCK = *mut SRWLOCK;
+
+#[cfg(target_arch = "x86")]
+pub const CRITICAL_SECTION_SIZE: uint = 24;
+#[cfg(target_arch = "x86_64")]
+pub const CRITICAL_SECTION_SIZE: uint = 40;
+
+#[repr(C)]
+pub struct CONDITION_VARIABLE { pub ptr: LPVOID }
+#[repr(C)]
+pub struct SRWLOCK { pub ptr: LPVOID }
+
+pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE {
+    ptr: 0 as *mut _,
+};
+pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { ptr: 0 as *mut _ };
+
+extern "system" {
+    // critical sections
+    pub fn InitializeCriticalSectionAndSpinCount(
+                    lpCriticalSection: LPCRITICAL_SECTION,
+                    dwSpinCount: DWORD) -> BOOL;
+    pub fn DeleteCriticalSection(lpCriticalSection: LPCRITICAL_SECTION);
+    pub fn EnterCriticalSection(lpCriticalSection: LPCRITICAL_SECTION);
+    pub fn LeaveCriticalSection(lpCriticalSection: LPCRITICAL_SECTION);
+    pub fn TryEnterCriticalSection(lpCriticalSection: LPCRITICAL_SECTION) -> BOOL;
+
+    // condition variables
+    pub fn SleepConditionVariableCS(ConditionVariable: LPCONDITION_VARIABLE,
+                                    CriticalSection: LPCRITICAL_SECTION,
+                                    dwMilliseconds: DWORD) -> BOOL;
+    pub fn WakeConditionVariable(ConditionVariable: LPCONDITION_VARIABLE);
+    pub fn WakeAllConditionVariable(ConditionVariable: LPCONDITION_VARIABLE);
+
+    // slim rwlocks
+    pub fn AcquireSRWLockExclusive(SRWLock: LPSRWLOCK);
+    pub fn AcquireSRWLockShared(SRWLock: LPSRWLOCK);
+    pub fn ReleaseSRWLockExclusive(SRWLock: LPSRWLOCK);
+    pub fn ReleaseSRWLockShared(SRWLock: LPSRWLOCK);
+    pub fn TryAcquireSRWLockExclusive(SRWLock: LPSRWLOCK) -> BOOLEAN;
+    pub fn TryAcquireSRWLockShared(SRWLock: LPSRWLOCK) -> BOOLEAN;
+}
+
diff --git a/src/libstd/sys/windows/tcp.rs b/src/libstd/sys/windows/tcp.rs
index 3baf2be08d2..505e6137bf9 100644
--- a/src/libstd/sys/windows/tcp.rs
+++ b/src/libstd/sys/windows/tcp.rs
@@ -18,8 +18,7 @@ use super::{last_error, last_net_error, retry, sock_t};
 use sync::{Arc, atomic};
 use sys::fs::FileDesc;
 use sys::{mod, c, set_nonblocking, wouldblock, timer};
-use sys_common::{mod, timeout, eof};
-use sys_common::net::*;
+use sys_common::{mod, timeout, eof, net};
 
 pub use sys_common::net::TcpStream;
 
@@ -48,37 +47,35 @@ impl Drop for Event {
 // TCP listeners
 ////////////////////////////////////////////////////////////////////////////////
 
-pub struct TcpListener {
-    inner: FileDesc,
-}
+pub struct TcpListener { sock: sock_t }
 
 impl TcpListener {
     pub fn bind(addr: ip::SocketAddr) -> IoResult<TcpListener> {
         sys::init_net();
 
-        let fd = try!(socket(addr, libc::SOCK_STREAM));
-        let ret = TcpListener { inner: FileDesc::new(fd as libc::c_int, true) };
+        let sock = try!(net::socket(addr, libc::SOCK_STREAM));
+        let ret = TcpListener { sock: sock };
 
         let mut storage = unsafe { mem::zeroed() };
-        let len = addr_to_sockaddr(addr, &mut storage);
+        let len = net::addr_to_sockaddr(addr, &mut storage);
         let addrp = &storage as *const _ as *const libc::sockaddr;
 
-        match unsafe { libc::bind(fd, addrp, len) } {
+        match unsafe { libc::bind(sock, addrp, len) } {
             -1 => Err(last_net_error()),
             _ => Ok(ret),
         }
     }
 
-    pub fn fd(&self) -> sock_t { self.inner.fd as sock_t }
+    pub fn socket(&self) -> sock_t { self.sock }
 
     pub fn listen(self, backlog: int) -> IoResult<TcpAcceptor> {
-        match unsafe { libc::listen(self.fd(), backlog as libc::c_int) } {
+        match unsafe { libc::listen(self.socket(), backlog as libc::c_int) } {
             -1 => Err(last_net_error()),
 
             _ => {
                 let accept = try!(Event::new());
                 let ret = unsafe {
-                    c::WSAEventSelect(self.fd(), accept.handle(), c::FD_ACCEPT)
+                    c::WSAEventSelect(self.socket(), accept.handle(), c::FD_ACCEPT)
                 };
                 if ret != 0 {
                     return Err(last_net_error())
@@ -97,7 +94,13 @@ impl TcpListener {
     }
 
     pub fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
-        sockname(self.fd(), libc::getsockname)
+        net::sockname(self.socket(), libc::getsockname)
+    }
+}
+
+impl Drop for TcpListener {
+    fn drop(&mut self) {
+        unsafe { super::close_sock(self.sock); }
     }
 }
 
@@ -114,7 +117,7 @@ struct AcceptorInner {
 }
 
 impl TcpAcceptor {
-    pub fn fd(&self) -> sock_t { self.inner.listener.fd() }
+    pub fn socket(&self) -> sock_t { self.inner.listener.socket() }
 
     pub fn accept(&mut self) -> IoResult<TcpStream> {
         // Unlink unix, windows cannot invoke `select` on arbitrary file
@@ -161,13 +164,13 @@ impl TcpAcceptor {
 
             let mut wsaevents: c::WSANETWORKEVENTS = unsafe { mem::zeroed() };
             let ret = unsafe {
-                c::WSAEnumNetworkEvents(self.fd(), events[1], &mut wsaevents)
+                c::WSAEnumNetworkEvents(self.socket(), events[1], &mut wsaevents)
             };
             if ret != 0 { return Err(last_net_error()) }
 
             if wsaevents.lNetworkEvents & c::FD_ACCEPT == 0 { continue }
             match unsafe {
-                libc::accept(self.fd(), ptr::null_mut(), ptr::null_mut())
+                libc::accept(self.socket(), ptr::null_mut(), ptr::null_mut())
             } {
                 -1 if wouldblock() => {}
                 -1 => return Err(last_net_error()),
@@ -175,13 +178,13 @@ impl TcpAcceptor {
                 // Accepted sockets inherit the same properties as the caller,
                 // so we need to deregister our event and switch the socket back
                 // to blocking mode
-                fd => {
-                    let stream = TcpStream::new(fd);
+                socket => {
+                    let stream = TcpStream::new(socket);
                     let ret = unsafe {
-                        c::WSAEventSelect(fd, events[1], 0)
+                        c::WSAEventSelect(socket, events[1], 0)
                     };
                     if ret != 0 { return Err(last_net_error()) }
-                    try!(set_nonblocking(fd, false));
+                    try!(set_nonblocking(socket, false));
                     return Ok(stream)
                 }
             }
@@ -191,7 +194,7 @@ impl TcpAcceptor {
     }
 
     pub fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
-        sockname(self.fd(), libc::getsockname)
+        net::sockname(self.socket(), libc::getsockname)
     }
 
     pub fn set_timeout(&mut self, timeout: Option<u64>) {
diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs
new file mode 100644
index 00000000000..4498f56c00a
--- /dev/null
+++ b/src/libstd/sys/windows/thread.rs
@@ -0,0 +1,96 @@
+// 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.
+
+use core::prelude::*;
+
+use boxed::Box;
+use cmp;
+use mem;
+use ptr;
+use libc;
+use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES, SIZE_T, BOOL,
+                                   LPVOID, DWORD, LPDWORD, HANDLE};
+use thunk::Thunk;
+use sys_common::stack::RED_ZONE;
+use sys_common::thread::*;
+
+pub type rust_thread = HANDLE;
+pub type rust_thread_return = DWORD;
+
+pub type StartFn = extern "system" fn(*mut libc::c_void) -> rust_thread_return;
+
+#[no_stack_check]
+pub extern "system" fn thread_start(main: *mut libc::c_void) -> rust_thread_return {
+    return start_thread(main);
+}
+
+pub mod guard {
+    pub unsafe fn main() -> uint {
+        0
+    }
+
+    pub unsafe fn current() -> uint {
+        0
+    }
+
+    pub unsafe fn init() {
+    }
+}
+
+pub unsafe fn create(stack: uint, p: Thunk) -> rust_thread {
+    let arg: *mut libc::c_void = mem::transmute(box p);
+    // FIXME On UNIX, we guard against stack sizes that are too small but
+    // that's because pthreads enforces that stacks are at least
+    // PTHREAD_STACK_MIN bytes big.  Windows has no such lower limit, it's
+    // just that below a certain threshold you can't do anything useful.
+    // That threshold is application and architecture-specific, however.
+    // For now, the only requirement is that it's big enough to hold the
+    // red zone.  Round up to the next 64 kB because that's what the NT
+    // kernel does, might as well make it explicit.  With the current
+    // 20 kB red zone, that makes for a 64 kB minimum stack.
+    let stack_size = (cmp::max(stack, RED_ZONE) + 0xfffe) & (-0xfffe - 1);
+    let ret = CreateThread(ptr::null_mut(), stack_size as libc::size_t,
+                           thread_start, arg, 0, ptr::null_mut());
+
+    if ret as uint == 0 {
+        // be sure to not leak the closure
+        let _p: Box<Thunk> = mem::transmute(arg);
+        panic!("failed to spawn native thread: {}", ret);
+    }
+    return ret;
+}
+
+pub unsafe fn join(native: rust_thread) {
+    use libc::consts::os::extra::INFINITE;
+    WaitForSingleObject(native, INFINITE);
+}
+
+pub unsafe fn detach(native: rust_thread) {
+    assert!(libc::CloseHandle(native) != 0);
+}
+
+pub unsafe fn yield_now() {
+    // This function will return 0 if there are no other threads to execute,
+    // but this also means that the yield was useless so this isn't really a
+    // case that needs to be worried about.
+    SwitchToThread();
+}
+
+#[allow(non_snake_case)]
+extern "system" {
+    fn CreateThread(lpThreadAttributes: LPSECURITY_ATTRIBUTES,
+                    dwStackSize: SIZE_T,
+                    lpStartAddress: StartFn,
+                    lpParameter: LPVOID,
+                    dwCreationFlags: DWORD,
+                    lpThreadId: LPDWORD) -> HANDLE;
+    fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
+    fn SwitchToThread() -> BOOL;
+}
diff --git a/src/libstd/sys/windows/thread_local.rs b/src/libstd/sys/windows/thread_local.rs
new file mode 100644
index 00000000000..60b0d584db3
--- /dev/null
+++ b/src/libstd/sys/windows/thread_local.rs
@@ -0,0 +1,259 @@
+// 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.
+
+use prelude::*;
+
+use libc::types::os::arch::extra::{DWORD, LPVOID, BOOL};
+
+use mem;
+use rt;
+use sys_common::mutex::{MUTEX_INIT, Mutex};
+
+pub type Key = DWORD;
+pub type Dtor = unsafe extern fn(*mut u8);
+
+// Turns out, like pretty much everything, Windows is pretty close the
+// functionality that Unix provides, but slightly different! In the case of
+// TLS, Windows does not provide an API to provide a destructor for a TLS
+// variable. This ends up being pretty crucial to this implementation, so we
+// need a way around this.
+//
+// The solution here ended up being a little obscure, but fear not, the
+// internet has informed me [1][2] that this solution is not unique (no way
+// I could have thought of it as well!). The key idea is to insert some hook
+// somewhere to run arbitrary code on thread termination. With this in place
+// we'll be able to run anything we like, including all TLS destructors!
+//
+// To accomplish this feat, we perform a number of tasks, all contained
+// within this module:
+//
+// * All TLS destructors are tracked by *us*, not the windows runtime. This
+//   means that we have a global list of destructors for each TLS key that
+//   we know about.
+// * When a TLS key is destroyed, we're sure to remove it from the dtor list
+//   if it's in there.
+// * When a thread exits, we run over the entire list and run dtors for all
+//   non-null keys. This attempts to match Unix semantics in this regard.
+//
+// This ends up having the overhead of using a global list, having some
+// locks here and there, and in general just adding some more code bloat. We
+// attempt to optimize runtime by forgetting keys that don't have
+// destructors, but this only gets us so far.
+//
+// For more details and nitty-gritty, see the code sections below!
+//
+// [1]: http://www.codeproject.com/Articles/8113/Thread-Local-Storage-The-C-Way
+// [2]: https://github.com/ChromiumWebApps/chromium/blob/master/base
+//                        /threading/thread_local_storage_win.cc#L42
+
+// NB these are specifically not types from `std::sync` as they currently rely
+// on poisoning and this module needs to operate at a lower level than requiring
+// the thread infrastructure to be in place (useful on the borders of
+// initialization/destruction).
+static DTOR_LOCK: Mutex = MUTEX_INIT;
+static mut DTORS: *mut Vec<(Key, Dtor)> = 0 as *mut _;
+
+// -------------------------------------------------------------------------
+// Native bindings
+//
+// This section is just raw bindings to the native functions that Windows
+// provides, There's a few extra calls to deal with destructors.
+
+#[inline]
+pub unsafe fn create(dtor: Option<Dtor>) -> Key {
+    const TLS_OUT_OF_INDEXES: DWORD = 0xFFFFFFFF;
+    let key = TlsAlloc();
+    assert!(key != TLS_OUT_OF_INDEXES);
+    match dtor {
+        Some(f) => register_dtor(key, f),
+        None => {}
+    }
+    return key;
+}
+
+#[inline]
+pub unsafe fn set(key: Key, value: *mut u8) {
+    let r = TlsSetValue(key, value as LPVOID);
+    debug_assert!(r != 0);
+}
+
+#[inline]
+pub unsafe fn get(key: Key) -> *mut u8 {
+    TlsGetValue(key) as *mut u8
+}
+
+#[inline]
+pub unsafe fn destroy(key: Key) {
+    if unregister_dtor(key) {
+        // FIXME: Currently if a key has a destructor associated with it we
+        // can't actually ever unregister it. If we were to
+        // unregister it, then any key destruction would have to be
+        // serialized with respect to actually running destructors.
+        //
+        // We want to avoid a race where right before run_dtors runs
+        // some destructors TlsFree is called. Allowing the call to
+        // TlsFree would imply that the caller understands that *all
+        // known threads* are not exiting, which is quite a difficult
+        // thing to know!
+        //
+        // For now we just leak all keys with dtors to "fix" this.
+        // Note that source [2] above shows precedent for this sort
+        // of strategy.
+    } else {
+        let r = TlsFree(key);
+        debug_assert!(r != 0);
+    }
+}
+
+extern "system" {
+    fn TlsAlloc() -> DWORD;
+    fn TlsFree(dwTlsIndex: DWORD) -> BOOL;
+    fn TlsGetValue(dwTlsIndex: DWORD) -> LPVOID;
+    fn TlsSetValue(dwTlsIndex: DWORD, lpTlsvalue: LPVOID) -> BOOL;
+}
+
+// -------------------------------------------------------------------------
+// Dtor registration
+//
+// These functions are associated with registering and unregistering
+// destructors. They're pretty simple, they just push onto a vector and scan
+// a vector currently.
+//
+// FIXME: This could probably be at least a little faster with a BTree.
+
+unsafe fn init_dtors() {
+    if !DTORS.is_null() { return }
+
+    let dtors = box Vec::<(Key, Dtor)>::new();
+    DTORS = mem::transmute(dtors);
+
+    rt::at_exit(move|| {
+        DTOR_LOCK.lock();
+        let dtors = DTORS;
+        DTORS = 0 as *mut _;
+        mem::transmute::<_, Box<Vec<(Key, Dtor)>>>(dtors);
+        assert!(DTORS.is_null()); // can't re-init after destructing
+        DTOR_LOCK.unlock();
+    });
+}
+
+unsafe fn register_dtor(key: Key, dtor: Dtor) {
+    DTOR_LOCK.lock();
+    init_dtors();
+    (*DTORS).push((key, dtor));
+    DTOR_LOCK.unlock();
+}
+
+unsafe fn unregister_dtor(key: Key) -> bool {
+    DTOR_LOCK.lock();
+    init_dtors();
+    let ret = {
+        let dtors = &mut *DTORS;
+        let before = dtors.len();
+        dtors.retain(|&(k, _)| k != key);
+        dtors.len() != before
+    };
+    DTOR_LOCK.unlock();
+    ret
+}
+
+// -------------------------------------------------------------------------
+// Where the Magic (TM) Happens
+//
+// If you're looking at this code, and wondering "what is this doing?",
+// you're not alone! I'll try to break this down step by step:
+//
+// # What's up with CRT$XLB?
+//
+// For anything about TLS destructors to work on Windows, we have to be able
+// to run *something* when a thread exits. To do so, we place a very special
+// static in a very special location. If this is encoded in just the right
+// way, the kernel's loader is apparently nice enough to run some function
+// of ours whenever a thread exits! How nice of the kernel!
+//
+// Lots of detailed information can be found in source [1] above, but the
+// gist of it is that this is leveraging a feature of Microsoft's PE format
+// (executable format) which is not actually used by any compilers today.
+// This apparently translates to any callbacks in the ".CRT$XLB" section
+// being run on certain events.
+//
+// So after all that, we use the compiler's #[link_section] feature to place
+// a callback pointer into the magic section so it ends up being called.
+//
+// # What's up with this callback?
+//
+// The callback specified receives a number of parameters from... someone!
+// (the kernel? the runtime? I'm not qute sure!) There are a few events that
+// this gets invoked for, but we're currentl only interested on when a
+// thread or a process "detaches" (exits). The process part happens for the
+// last thread and the thread part happens for any normal thread.
+//
+// # Ok, what's up with running all these destructors?
+//
+// This will likely need to be improved over time, but this function
+// attempts a "poor man's" destructor callback system. To do this we clone a
+// local copy of the dtor list to start out with. This is our fudgy attempt
+// to not hold the lock while destructors run and not worry about the list
+// changing while we're looking at it.
+//
+// Once we've got a list of what to run, we iterate over all keys, check
+// their values, and then run destructors if the values turn out to be non
+// null (setting them to null just beforehand). We do this a few times in a
+// loop to basically match Unix semantics. If we don't reach a fixed point
+// after a short while then we just inevitably leak something most likely.
+//
+// # The article mentions crazy stuff about "/INCLUDE"?
+//
+// It sure does! This seems to work for now, so maybe we'll just run into
+// that if we start linking with msvc?
+
+#[link_section = ".CRT$XLB"]
+#[linkage = "external"]
+#[allow(warnings)]
+pub static p_thread_callback: unsafe extern "system" fn(LPVOID, DWORD,
+                                                        LPVOID) =
+        on_tls_callback;
+
+#[allow(warnings)]
+unsafe extern "system" fn on_tls_callback(h: LPVOID,
+                                          dwReason: DWORD,
+                                          pv: LPVOID) {
+    const DLL_THREAD_DETACH: DWORD = 3;
+    const DLL_PROCESS_DETACH: DWORD = 0;
+    if dwReason == DLL_THREAD_DETACH || dwReason == DLL_PROCESS_DETACH {
+        run_dtors();
+    }
+}
+
+unsafe fn run_dtors() {
+    let mut any_run = true;
+    for _ in range(0, 5i) {
+        if !any_run { break }
+        any_run = false;
+        let dtors = {
+            DTOR_LOCK.lock();
+            let ret = if DTORS.is_null() {
+                Vec::new()
+            } else {
+                (*DTORS).iter().map(|s| *s).collect()
+            };
+            DTOR_LOCK.unlock();
+            ret
+        };
+        for &(key, dtor) in dtors.iter() {
+            let ptr = TlsGetValue(key);
+            if !ptr.is_null() {
+                TlsSetValue(key, 0 as *mut _);
+                dtor(ptr as *mut _);
+                any_run = true;
+            }
+        }
+    }
+}
diff --git a/src/libstd/sys/windows/timer.rs b/src/libstd/sys/windows/timer.rs
index 9af3a7c8b6e..7e4dd768aa9 100644
--- a/src/libstd/sys/windows/timer.rs
+++ b/src/libstd/sys/windows/timer.rs
@@ -20,7 +20,7 @@
 //! Other than that, the implementation is pretty straightforward in terms of
 //! the other two implementations of timers with nothing *that* new showing up.
 
-pub use self::Req::*;
+use self::Req::*;
 
 use libc;
 use ptr;
@@ -32,7 +32,7 @@ use sys_common::helper_thread::Helper;
 use prelude::*;
 use io::IoResult;
 
-helper_init!(static HELPER: Helper<Req>)
+helper_init! { static HELPER: Helper<Req> }
 
 pub trait Callback {
     fn call(&mut self);
diff --git a/src/libstd/sys/windows/tty.rs b/src/libstd/sys/windows/tty.rs
index 0e7b06cbb94..f793de5bb57 100644
--- a/src/libstd/sys/windows/tty.rs
+++ b/src/libstd/sys/windows/tty.rs
@@ -111,9 +111,9 @@ impl TTY {
     }
 
     pub fn write(&mut self, buf: &[u8]) -> IoResult<()> {
-        let utf16 = match from_utf8(buf) {
+        let utf16 = match from_utf8(buf).ok() {
             Some(utf8) => {
-                utf8.as_slice().utf16_units().collect::<Vec<u16>>()
+                utf8.utf16_units().collect::<Vec<u16>>()
             }
             None => return Err(invalid_encoding()),
         };
diff --git a/src/libstd/task.rs b/src/libstd/task.rs
index 4f5f47e980c..0f08108fee5 100644
--- a/src/libstd/task.rs
+++ b/src/libstd/task.rs
@@ -8,520 +8,37 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Task creation
-//!
-//! An executing Rust program consists of a collection of tasks, each
-//! with their own stack and local state.
-//!
-//! Tasks generally have their memory *isolated* from each other by
-//! virtue of Rust's owned types (which of course may only be owned by
-//! a single task at a time). Communication between tasks is primarily
-//! done through [channels](../../std/comm/index.html), Rust's
-//! message-passing types, though [other forms of task
-//! synchronization](../../std/sync/index.html) are often employed to
-//! achieve particular performance goals. In particular, types that
-//! are guaranteed to be threadsafe are easily shared between threads
-//! using the atomically-reference-counted container,
-//! [`Arc`](../../std/sync/struct.Arc.html).
-//!
-//! Fatal logic errors in Rust cause *task panic*, during which
-//! a task will unwind the stack, running destructors and freeing
-//! owned resources. Task panic is unrecoverable from within
-//! the panicking task (i.e. there is no 'try/catch' in Rust), but
-//! panic may optionally be detected from a different task. If
-//! the main task panics the application will exit with a non-zero
-//! exit code.
-//!
-//! ## Example
-//!
-//! ```rust
-//! spawn(proc() {
-//!     println!("Hello, World!");
-//! })
-//! ```
+//! Deprecated in favor of `thread`.
 
-#![unstable = "The task spawning model will be changed as part of runtime reform, and the module \
-               will likely be renamed from `task` to `thread`."]
+#![deprecated = "use std::thread instead"]
 
 use any::Any;
-use comm::channel;
-use io::{Writer, stdio};
-use kinds::{Send, marker};
-use option::{None, Some, Option};
 use boxed::Box;
+use thread;
+use kinds::Send;
 use result::Result;
-use rustrt::local::Local;
-use rustrt::task;
-use rustrt::task::Task;
-use str::{Str, SendStr, IntoMaybeOwned};
-use string::{String, ToString};
-use sync::Future;
+use ops::FnOnce;
 
-/// The task builder type.
-///
-/// Provides detailed control over the properties and behavior of new tasks.
+/// Deprecate: use `std::thread::Builder` instead.
+#[deprecated = "use std::thread::Builder instead"]
+pub type TaskBuilder = thread::Builder;
 
-// NB: Builders are designed to be single-use because they do stateful
-// things that get weird when reusing - e.g. if you create a result future
-// it only applies to a single task, so then you have to maintain Some
-// potentially tricky state to ensure that everything behaves correctly
-// when you try to reuse the builder to spawn a new task. We'll just
-// sidestep that whole issue by making builders uncopyable and making
-// the run function move them in.
-pub struct TaskBuilder {
-    // A name for the task-to-be, for identification in panic messages
-    name: Option<SendStr>,
-    // The size of the stack for the spawned task
-    stack_size: Option<uint>,
-    // Task-local stdout
-    stdout: Option<Box<Writer + Send>>,
-    // Task-local stderr
-    stderr: Option<Box<Writer + Send>>,
-    // Optionally wrap the eventual task body
-    gen_body: Option<proc(v: proc():Send):Send -> proc():Send>,
-    nocopy: marker::NoCopy,
+/// Deprecated: use `std::thread::Thread::spawn` and `detach` instead.
+#[deprecated = "use std::thread::Thread::spawn and detach instead"]
+pub fn spawn<F>(f: F) where F: FnOnce(), F: Send {
+    thread::Thread::spawn(f).detach();
 }
 
-impl TaskBuilder {
-    /// Generate the base configuration for spawning a task, off of which more
-    /// configuration methods can be chained.
-    pub fn new() -> TaskBuilder {
-        TaskBuilder {
-            name: None,
-            stack_size: None,
-            stdout: None,
-            stderr: None,
-            gen_body: None,
-            nocopy: marker::NoCopy,
-        }
-    }
+/// Deprecated: use `std::thread::Thread::spawn` and `join` instead.
+#[deprecated = "use std::thread::Thread::spawn and join instead"]
+pub fn try<T, F>(f: F) -> Result<T, Box<Any + Send>> where
+    T: Send, F: FnOnce() -> T, F: Send
+{
+    thread::Thread::spawn(f).join()
 }
 
-impl TaskBuilder {
-    /// Name the task-to-be. Currently the name is used for identification
-    /// only in panic messages.
-    #[unstable = "IntoMaybeOwned will probably change."]
-    pub fn named<T: IntoMaybeOwned<'static>>(mut self, name: T) -> TaskBuilder {
-        self.name = Some(name.into_maybe_owned());
-        self
-    }
-
-    /// Set the size of the stack for the new task.
-    pub fn stack_size(mut self, size: uint) -> TaskBuilder {
-        self.stack_size = Some(size);
-        self
-    }
-
-    /// Redirect task-local stdout.
-    #[experimental = "May not want to make stdio overridable here."]
-    pub fn stdout(mut self, stdout: Box<Writer + Send>) -> TaskBuilder {
-        self.stdout = Some(stdout);
-        self
-    }
-
-    /// Redirect task-local stderr.
-    #[experimental = "May not want to make stdio overridable here."]
-    pub fn stderr(mut self, stderr: Box<Writer + Send>) -> TaskBuilder {
-        self.stderr = Some(stderr);
-        self
-    }
-
-    // Where spawning actually happens (whether yielding a future or not)
-    fn spawn_internal(self, f: proc():Send,
-                      on_exit: Option<proc(Result<(), Box<Any + Send>>):Send>) {
-        let TaskBuilder {
-            name, stack_size, stdout, stderr, mut gen_body, nocopy: _
-        } = self;
-        let f = match gen_body.take() {
-            Some(gen) => gen(f),
-            None => f
-        };
-        let opts = task::TaskOpts {
-            on_exit: on_exit,
-            name: name,
-            stack_size: stack_size,
-        };
-        if stdout.is_some() || stderr.is_some() {
-            Task::spawn(opts, proc() {
-                let _ = stdout.map(stdio::set_stdout);
-                let _ = stderr.map(stdio::set_stderr);
-                f();
-            })
-        } else {
-            Task::spawn(opts, f)
-        }
-    }
-
-    /// Creates and executes a new child task.
-    ///
-    /// Sets up a new task with its own call stack and schedules it to run
-    /// the provided proc. The task has the properties and behavior
-    /// specified by the `TaskBuilder`.
-    pub fn spawn(self, f: proc():Send) {
-        self.spawn_internal(f, None)
-    }
-
-    /// Execute a proc in a newly-spawned task and return a future representing
-    /// the task's result. The task has the properties and behavior
-    /// specified by the `TaskBuilder`.
-    ///
-    /// Taking the value of the future will block until the child task
-    /// terminates.
-    ///
-    /// # Return value
-    ///
-    /// If the child task executes successfully (without panicking) then the
-    /// future returns `result::Ok` containing the value returned by the
-    /// function. If the child task panics then the future returns `result::Err`
-    /// containing the argument to `panic!(...)` as an `Any` trait object.
-    #[experimental = "Futures are experimental."]
-    pub fn try_future<T:Send>(self, f: proc():Send -> T)
-                              -> Future<Result<T, Box<Any + Send>>> {
-        // currently, the on_exit proc provided by librustrt only works for unit
-        // results, so we use an additional side-channel to communicate the
-        // result.
-
-        let (tx_done, rx_done) = channel(); // signal that task has exited
-        let (tx_retv, rx_retv) = channel(); // return value from task
-
-        let on_exit = proc(res) { let _ = tx_done.send_opt(res); };
-        self.spawn_internal(proc() { let _ = tx_retv.send_opt(f()); },
-                            Some(on_exit));
-
-        Future::from_fn(proc() {
-            rx_done.recv().map(|_| rx_retv.recv())
-        })
-    }
-
-    /// Execute a function in a newly-spawnedtask and block until the task
-    /// completes or panics. Equivalent to `.try_future(f).unwrap()`.
-    #[unstable = "Error type may change."]
-    pub fn try<T:Send>(self, f: proc():Send -> T) -> Result<T, Box<Any + Send>> {
-        self.try_future(f).unwrap()
-    }
-}
-
-/* Convenience functions */
-
-/// Creates and executes a new child task
-///
-/// Sets up a new task with its own call stack and schedules it to run
-/// the provided unique closure.
-///
-/// This function is equivalent to `TaskBuilder::new().spawn(f)`.
-pub fn spawn(f: proc(): Send) {
-    TaskBuilder::new().spawn(f)
-}
-
-/// Execute a function in a newly-spawned task and return either the return
-/// value of the function or an error if the task panicked.
-///
-/// This is equivalent to `TaskBuilder::new().try`.
-#[unstable = "Error type may change."]
-pub fn try<T: Send>(f: proc(): Send -> T) -> Result<T, Box<Any + Send>> {
-    TaskBuilder::new().try(f)
-}
-
-/// Execute a function in another task and return a future representing the
-/// task's result.
-///
-/// This is equivalent to `TaskBuilder::new().try_future`.
-#[experimental = "Futures are experimental."]
-pub fn try_future<T:Send>(f: proc():Send -> T) -> Future<Result<T, Box<Any + Send>>> {
-    TaskBuilder::new().try_future(f)
-}
-
-
-/* Lifecycle functions */
-
-/// Read the name of the current task.
-#[stable]
-pub fn name() -> Option<String> {
-    use rustrt::task::Task;
-
-    let task = Local::borrow(None::<Task>);
-    match task.name {
-        Some(ref name) => Some(name.as_slice().to_string()),
-        None => None
-    }
-}
-
-/// Yield control to the task scheduler.
-#[unstable = "Name will change."]
+/// Deprecated: use `std::thread::Thread::yield_now instead`.
+#[deprecated = "use std::thread::Thread::yield_now instead"]
 pub fn deschedule() {
-    use rustrt::task::Task;
-    Task::yield_now();
-}
-
-/// True if the running task is currently panicking (e.g. will return `true` inside a
-/// destructor that is run while unwinding the stack after a call to `panic!()`).
-#[unstable = "May move to a different module."]
-pub fn failing() -> bool {
-    use rustrt::task::Task;
-    Local::borrow(None::<Task>).unwinder.unwinding()
-}
-
-#[cfg(test)]
-mod test {
-    use any::{Any, AnyRefExt};
-    use boxed::BoxAny;
-    use result;
-    use result::{Ok, Err};
-    use string::String;
-    use std::io::{ChanReader, ChanWriter};
-    use prelude::*;
-    use super::*;
-
-    // !!! These tests are dangerous. If something is buggy, they will hang, !!!
-    // !!! instead of exiting cleanly. This might wedge the buildbots.       !!!
-
-    #[test]
-    fn test_unnamed_task() {
-        try(proc() {
-            assert!(name().is_none());
-        }).map_err(|_| ()).unwrap();
-    }
-
-    #[test]
-    fn test_owned_named_task() {
-        TaskBuilder::new().named("ada lovelace".to_string()).try(proc() {
-            assert!(name().unwrap() == "ada lovelace".to_string());
-        }).map_err(|_| ()).unwrap();
-    }
-
-    #[test]
-    fn test_static_named_task() {
-        TaskBuilder::new().named("ada lovelace").try(proc() {
-            assert!(name().unwrap() == "ada lovelace".to_string());
-        }).map_err(|_| ()).unwrap();
-    }
-
-    #[test]
-    fn test_send_named_task() {
-        TaskBuilder::new().named("ada lovelace".into_maybe_owned()).try(proc() {
-            assert!(name().unwrap() == "ada lovelace".to_string());
-        }).map_err(|_| ()).unwrap();
-    }
-
-    #[test]
-    fn test_run_basic() {
-        let (tx, rx) = channel();
-        TaskBuilder::new().spawn(proc() {
-            tx.send(());
-        });
-        rx.recv();
-    }
-
-    #[test]
-    fn test_try_future() {
-        let result = TaskBuilder::new().try_future(proc() {});
-        assert!(result.unwrap().is_ok());
-
-        let result = TaskBuilder::new().try_future(proc() -> () {
-            panic!();
-        });
-        assert!(result.unwrap().is_err());
-    }
-
-    #[test]
-    fn test_try_success() {
-        match try(proc() {
-            "Success!".to_string()
-        }).as_ref().map(|s| s.as_slice()) {
-            result::Ok("Success!") => (),
-            _ => panic!()
-        }
-    }
-
-    #[test]
-    fn test_try_panic() {
-        match try(proc() {
-            panic!()
-        }) {
-            result::Err(_) => (),
-            result::Ok(()) => panic!()
-        }
-    }
-
-    #[test]
-    fn test_spawn_sched() {
-        use clone::Clone;
-
-        let (tx, rx) = channel();
-
-        fn f(i: int, tx: Sender<()>) {
-            let tx = tx.clone();
-            spawn(proc() {
-                if i == 0 {
-                    tx.send(());
-                } else {
-                    f(i - 1, tx);
-                }
-            });
-
-        }
-        f(10, tx);
-        rx.recv();
-    }
-
-    #[test]
-    fn test_spawn_sched_childs_on_default_sched() {
-        let (tx, rx) = channel();
-
-        spawn(proc() {
-            spawn(proc() {
-                tx.send(());
-            });
-        });
-
-        rx.recv();
-    }
-
-    fn avoid_copying_the_body(spawnfn: |v: proc():Send|) {
-        let (tx, rx) = channel::<uint>();
-
-        let x = box 1;
-        let x_in_parent = (&*x) as *const int as uint;
-
-        spawnfn(proc() {
-            let x_in_child = (&*x) as *const int as uint;
-            tx.send(x_in_child);
-        });
-
-        let x_in_child = rx.recv();
-        assert_eq!(x_in_parent, x_in_child);
-    }
-
-    #[test]
-    fn test_avoid_copying_the_body_spawn() {
-        avoid_copying_the_body(spawn);
-    }
-
-    #[test]
-    fn test_avoid_copying_the_body_task_spawn() {
-        avoid_copying_the_body(|f| {
-            let builder = TaskBuilder::new();
-            builder.spawn(proc() {
-                f();
-            });
-        })
-    }
-
-    #[test]
-    fn test_avoid_copying_the_body_try() {
-        avoid_copying_the_body(|f| {
-            let _ = try(proc() {
-                f()
-            });
-        })
-    }
-
-    #[test]
-    fn test_child_doesnt_ref_parent() {
-        // If the child refcounts the parent task, this will stack overflow when
-        // climbing the task tree to dereference each ancestor. (See #1789)
-        // (well, it would if the constant were 8000+ - I lowered it to be more
-        // valgrind-friendly. try this at home, instead..!)
-        static GENERATIONS: uint = 16;
-        fn child_no(x: uint) -> proc(): Send {
-            return proc() {
-                if x < GENERATIONS {
-                    TaskBuilder::new().spawn(child_no(x+1));
-                }
-            }
-        }
-        TaskBuilder::new().spawn(child_no(0));
-    }
-
-    #[test]
-    fn test_simple_newsched_spawn() {
-        spawn(proc()())
-    }
-
-    #[test]
-    fn test_try_panic_message_static_str() {
-        match try(proc() {
-            panic!("static string");
-        }) {
-            Err(e) => {
-                type T = &'static str;
-                assert!(e.is::<T>());
-                assert_eq!(*e.downcast::<T>().unwrap(), "static string");
-            }
-            Ok(()) => panic!()
-        }
-    }
-
-    #[test]
-    fn test_try_panic_message_owned_str() {
-        match try(proc() {
-            panic!("owned string".to_string());
-        }) {
-            Err(e) => {
-                type T = String;
-                assert!(e.is::<T>());
-                assert_eq!(*e.downcast::<T>().unwrap(), "owned string".to_string());
-            }
-            Ok(()) => panic!()
-        }
-    }
-
-    #[test]
-    fn test_try_panic_message_any() {
-        match try(proc() {
-            panic!(box 413u16 as Box<Any + Send>);
-        }) {
-            Err(e) => {
-                type T = Box<Any + Send>;
-                assert!(e.is::<T>());
-                let any = e.downcast::<T>().unwrap();
-                assert!(any.is::<u16>());
-                assert_eq!(*any.downcast::<u16>().unwrap(), 413u16);
-            }
-            Ok(()) => panic!()
-        }
-    }
-
-    #[test]
-    fn test_try_panic_message_unit_struct() {
-        struct Juju;
-
-        match try(proc() {
-            panic!(Juju)
-        }) {
-            Err(ref e) if e.is::<Juju>() => {}
-            Err(_) | Ok(()) => panic!()
-        }
-    }
-
-    #[test]
-    fn test_stdout() {
-        let (tx, rx) = channel();
-        let mut reader = ChanReader::new(rx);
-        let stdout = ChanWriter::new(tx);
-
-        let r = TaskBuilder::new().stdout(box stdout as Box<Writer + Send>)
-                                  .try(proc() {
-                print!("Hello, world!");
-            });
-        assert!(r.is_ok());
-
-        let output = reader.read_to_string().unwrap();
-        assert_eq!(output, "Hello, world!".to_string());
-    }
-
-    // NOTE: the corresponding test for stderr is in run-pass/task-stderr, due
-    // to the test harness apparently interfering with stderr configuration.
-}
-
-#[test]
-fn task_abort_no_kill_runtime() {
-    use std::io::timer;
-    use time::Duration;
-    use mem;
-
-    let tb = TaskBuilder::new();
-    let rx = tb.try_future(proc() {});
-    mem::drop(rx);
-    timer::sleep(Duration::milliseconds(1000));
+    thread::Thread::yield_now()
 }
diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs
new file mode 100644
index 00000000000..89773207347
--- /dev/null
+++ b/src/libstd/thread.rs
@@ -0,0 +1,654 @@
+// 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.
+
+//! Native threads
+//!
+//! ## The threading model
+//!
+//! An executing Rust program consists of a collection of native OS threads,
+//! each with their own stack and local state.
+//!
+//! Communication between threads can be done through
+//! [channels](../../std/comm/index.html), Rust's message-passing
+//! types, along with [other forms of thread
+//! synchronization](../../std/sync/index.html) and shared-memory data
+//! structures. In particular, types that are guaranteed to be
+//! threadsafe are easily shared between threads using the
+//! atomically-reference-counted container,
+//! [`Arc`](../../std/sync/struct.Arc.html).
+//!
+//! Fatal logic errors in Rust cause *thread panic*, during which
+//! a thread will unwind the stack, running destructors and freeing
+//! owned resources. Thread panic is unrecoverable from within
+//! the panicking thread (i.e. there is no 'try/catch' in Rust), but
+//! panic may optionally be detected from a different thread. If
+//! the main thread panics the application will exit with a non-zero
+//! exit code.
+//!
+//! When the main thread of a Rust program terminates, the entire program shuts
+//! down, even if other threads are still running. However, this module provides
+//! convenient facilities for automatically waiting for the termination of a
+//! child thread (i.e., join), described below.
+//!
+//! ## The `Thread` type
+//!
+//! Already-running threads are represented via the `Thread` type, which you can
+//! get in one of two ways:
+//!
+//! * By spawning a new thread, e.g. using the `Thread::spawn` constructor;
+//! * By requesting the current thread, using the `Thread::current` function.
+//!
+//! Threads can be named, and provide some built-in support for low-level
+//! synchronization described below.
+//!
+//! The `Thread::current()` function is available even for threads not spawned
+//! by the APIs of this module.
+//!
+//! ## Spawning a thread
+//!
+//! A new thread can be spawned using the `Thread::spawn` function:
+//!
+//! ```rust
+//! use std::thread::Thread;
+//!
+//! let guard = Thread::spawn(move || {
+//!     println!("Hello, World!");
+//!     // some computation here
+//! });
+//! let result = guard.join();
+//! ```
+//!
+//! The `spawn` function doesn't return a `Thread` directly; instead, it returns
+//! a *join guard* from which a `Thread` can be extracted. The join guard is an
+//! RAII-style guard that will automatically join the child thread (block until
+//! it terminates) when it is dropped. You can join the child thread in advance
+//! by calling the `join` method on the guard, which will also return the result
+//! produced by the thread.
+//!
+//! If you instead wish to *detach* the child thread, allowing it to outlive its
+//! parent, you can use the `detach` method on the guard,
+//!
+//! A handle to the thread itself is available via the `thread` method on the
+//! join guard.
+//!
+//! ## Configuring threads
+//!
+//! A new thread can be configured before it is spawned via the `Builder` type,
+//! which currently allows you to set the name, stack size, and writers for
+//! `println!` and `panic!` for the child thread:
+//!
+//! ```rust
+//! use std::thread;
+//!
+//! thread::Builder::new().name("child1".to_string()).spawn(move || {
+//!     println!("Hello, world!")
+//! }).detach();
+//! ```
+//!
+//! ## Blocking support: park and unpark
+//!
+//! Every thread is equipped with some basic low-level blocking support, via the
+//! `park` and `unpark` functions.
+//!
+//! Conceptually, each `Thread` handle has an associated token, which is
+//! initially not present:
+//!
+//! * The `Thread::park()` function blocks the current thread unless or until
+//!   the token is available for its thread handle, at which point It atomically
+//!   consumes the token. It may also return *spuriously*, without consuming the
+//!   token.
+//!
+//! * The `unpark()` method on a `Thread` atomically makes the token available
+//!   if it wasn't already.
+//!
+//! In other words, each `Thread` acts a bit like a semaphore with initial count
+//! 0, except that the semaphore is *saturating* (the count cannot go above 1),
+//! and can return spuriously.
+//!
+//! The API is typically used by acquiring a handle to the current thread,
+//! placing that handle in a shared data structure so that other threads can
+//! find it, and then `park`ing. When some desired condition is met, another
+//! thread calls `unpark` on the handle.
+//!
+//! The motivation for this design is twofold:
+//!
+//! * It avoids the need to allocate mutexes and condvars when building new
+//!   synchronization primitives; the threads already provide basic blocking/signaling.
+//!
+//! * It can be implemented highly efficiently on many platforms.
+
+use any::Any;
+use borrow::IntoCow;
+use boxed::Box;
+use cell::UnsafeCell;
+use clone::Clone;
+use kinds::Send;
+use ops::{Drop, FnOnce};
+use option::Option::{mod, Some, None};
+use result::Result::{Err, Ok};
+use sync::{Mutex, Condvar, Arc};
+use str::Str;
+use string::String;
+use rt::{mod, unwind};
+use io::{Writer, stdio};
+use thunk::Thunk;
+
+use sys::thread as imp;
+use sys_common::{stack, thread_info};
+
+/// Thread configuation. Provides detailed control over the properties
+/// and behavior of new threads.
+pub struct Builder {
+    // A name for the thread-to-be, for identification in panic messages
+    name: Option<String>,
+    // The size of the stack for the spawned thread
+    stack_size: Option<uint>,
+    // Thread-local stdout
+    stdout: Option<Box<Writer + Send>>,
+    // Thread-local stderr
+    stderr: Option<Box<Writer + Send>>,
+}
+
+impl Builder {
+    /// Generate the base configuration for spawning a thread, from which
+    /// configuration methods can be chained.
+    pub fn new() -> Builder {
+        Builder {
+            name: None,
+            stack_size: None,
+            stdout: None,
+            stderr: None,
+        }
+    }
+
+    /// Name the thread-to-be. Currently the name is used for identification
+    /// only in panic messages.
+    pub fn name(mut self, name: String) -> Builder {
+        self.name = Some(name);
+        self
+    }
+
+    /// Deprecated: use `name` instead
+    #[deprecated = "use name instead"]
+    pub fn named<T: IntoCow<'static, String, str>>(self, name: T) -> Builder {
+        self.name(name.into_cow().into_owned())
+    }
+
+    /// Set the size of the stack for the new thread.
+    pub fn stack_size(mut self, size: uint) -> Builder {
+        self.stack_size = Some(size);
+        self
+    }
+
+    /// Redirect thread-local stdout.
+    #[experimental = "Will likely go away after proc removal"]
+    pub fn stdout(mut self, stdout: Box<Writer + Send>) -> Builder {
+        self.stdout = Some(stdout);
+        self
+    }
+
+    /// Redirect thread-local stderr.
+    #[experimental = "Will likely go away after proc removal"]
+    pub fn stderr(mut self, stderr: Box<Writer + Send>) -> Builder {
+        self.stderr = Some(stderr);
+        self
+    }
+
+    /// Spawn a new joinable thread, and return a JoinGuard guard for it.
+    ///
+    /// See `Thead::spawn` and the module doc for more details.
+    pub fn spawn<T, F>(self, f: F) -> JoinGuard<T> where
+        T: Send, F: FnOnce() -> T, F: Send
+    {
+        self.spawn_inner(Thunk::new(f))
+    }
+
+    fn spawn_inner<T: Send>(self, f: Thunk<(), T>) -> JoinGuard<T> {
+        let my_packet = Arc::new(UnsafeCell::new(None));
+        let their_packet = my_packet.clone();
+
+        let Builder { name, stack_size, stdout, stderr } = self;
+
+        let stack_size = stack_size.unwrap_or(rt::min_stack());
+        let my_thread = Thread::new(name);
+        let their_thread = my_thread.clone();
+
+        // Spawning a new OS thread guarantees that __morestack will never get
+        // triggered, but we must manually set up the actual stack bounds once
+        // this function starts executing. This raises the lower limit by a bit
+        // because by the time that this function is executing we've already
+        // consumed at least a little bit of stack (we don't know the exact byte
+        // address at which our stack started).
+        let main = move |:| {
+            let something_around_the_top_of_the_stack = 1;
+            let addr = &something_around_the_top_of_the_stack as *const int;
+            let my_stack_top = addr as uint;
+            let my_stack_bottom = my_stack_top - stack_size + 1024;
+            unsafe {
+                stack::record_os_managed_stack_bounds(my_stack_bottom, my_stack_top);
+            }
+            thread_info::set(
+                (my_stack_bottom, my_stack_top),
+                unsafe { imp::guard::current() },
+                their_thread
+            );
+
+            let mut output = None;
+            let f: Thunk<(), T> = if stdout.is_some() || stderr.is_some() {
+                Thunk::new(move |:| {
+                    let _ = stdout.map(stdio::set_stdout);
+                    let _ = stderr.map(stdio::set_stderr);
+                    f.invoke(())
+                })
+            } else {
+                f
+            };
+
+            let try_result = {
+                let ptr = &mut output;
+
+                // There are two primary reasons that general try/catch is
+                // unsafe. The first is that we do not support nested
+                // try/catch. The fact that this is happening in a newly-spawned
+                // thread suffices. The second is that unwinding while unwinding
+                // is not defined.  We take care of that by having an
+                // 'unwinding' flag in the thread itself. For these reasons,
+                // this unsafety should be ok.
+                unsafe {
+                    unwind::try(move || *ptr = Some(f.invoke(())))
+                }
+            };
+            unsafe {
+                *their_packet.get() = Some(match (output, try_result) {
+                    (Some(data), Ok(_)) => Ok(data),
+                    (None, Err(cause)) => Err(cause),
+                    _ => unreachable!()
+                });
+            }
+        };
+
+        JoinGuard {
+            native: unsafe { imp::create(stack_size, Thunk::new(main)) },
+            joined: false,
+            packet: my_packet,
+            thread: my_thread,
+        }
+    }
+}
+
+struct Inner {
+    name: Option<String>,
+    lock: Mutex<bool>,          // true when there is a buffered unpark
+    cvar: Condvar,
+}
+
+#[deriving(Clone)]
+/// A handle to a thread.
+pub struct Thread {
+    inner: Arc<Inner>,
+}
+
+impl Thread {
+    // Used only internally to construct a thread object without spawning
+    fn new(name: Option<String>) -> Thread {
+        Thread {
+            inner: Arc::new(Inner {
+                name: name,
+                lock: Mutex::new(false),
+                cvar: Condvar::new(),
+            })
+        }
+    }
+
+    /// Spawn a new joinable thread, returning a `JoinGuard` for it.
+    ///
+    /// The join guard can be used to explicitly join the child thead (via
+    /// `join`), returning `Result<T>`, or it will implicitly join the child
+    /// upon being dropped. To detach the child, allowing it to outlive the
+    /// current thread, use `detach`.  See the module documentation for additional details.
+    pub fn spawn<T, F>(f: F) -> JoinGuard<T> where
+        T: Send, F: FnOnce() -> T, F: Send
+    {
+        Builder::new().spawn(f)
+    }
+
+    /// Gets a handle to the thread that invokes it.
+    pub fn current() -> Thread {
+        thread_info::current_thread()
+    }
+
+    /// Cooperatively give up a timeslice to the OS scheduler.
+    pub fn yield_now() {
+        unsafe { imp::yield_now() }
+    }
+
+    /// Determines whether the current thread is panicking.
+    pub fn panicking() -> bool {
+        unwind::panicking()
+    }
+
+    /// Block unless or until the current thread's token is made available (may wake spuriously).
+    ///
+    /// See the module doc for more detail.
+    //
+    // The implementation currently uses the trivial strategy of a Mutex+Condvar
+    // with wakeup flag, which does not actually allow spurious wakeups. In the
+    // future, this will be implemented in a more efficient way, perhaps along the lines of
+    //   http://cr.openjdk.java.net/~stefank/6989984.1/raw_files/new/src/os/linux/vm/os_linux.cpp
+    // or futuxes, and in either case may allow spurious wakeups.
+    pub fn park() {
+        let thread = Thread::current();
+        let mut guard = thread.inner.lock.lock();
+        while !*guard {
+            thread.inner.cvar.wait(&guard);
+        }
+        *guard = false;
+    }
+
+    /// Atomically makes the handle's token available if it is not already.
+    ///
+    /// See the module doc for more detail.
+    pub fn unpark(&self) {
+        let mut guard = self.inner.lock.lock();
+        if !*guard {
+            *guard = true;
+            self.inner.cvar.notify_one();
+        }
+    }
+
+    /// Get the thread's name.
+    pub fn name(&self) -> Option<&str> {
+        self.inner.name.as_ref().map(|s| s.as_slice())
+    }
+}
+
+// a hack to get around privacy restrictions
+impl thread_info::NewThread for Thread {
+    fn new(name: Option<String>) -> Thread { Thread::new(name) }
+}
+
+/// Indicates the manner in which a thread exited.
+///
+/// A thread that completes without panicking is considered to exit successfully.
+pub type Result<T> = ::result::Result<T, Box<Any + Send>>;
+
+#[must_use]
+/// An RAII-style guard that will block until thread termination when dropped.
+///
+/// The type `T` is the return type for the thread's main function.
+pub struct JoinGuard<T> {
+    native: imp::rust_thread,
+    thread: Thread,
+    joined: bool,
+    packet: Arc<UnsafeCell<Option<Result<T>>>>,
+}
+
+impl<T: Send> JoinGuard<T> {
+    /// Extract a handle to the thread this guard will join on.
+    pub fn thread(&self) -> &Thread {
+        &self.thread
+    }
+
+    /// Wait for the associated thread to finish, returning the result of the thread's
+    /// calculation.
+    ///
+    /// If the child thread panics, `Err` is returned with the parameter given
+    /// to `panic`.
+    pub fn join(mut self) -> Result<T> {
+        assert!(!self.joined);
+        unsafe { imp::join(self.native) };
+        self.joined = true;
+        unsafe {
+            (*self.packet.get()).take().unwrap()
+        }
+    }
+
+    /// Detaches the child thread, allowing it to outlive its parent.
+    pub fn detach(mut self) {
+        unsafe { imp::detach(self.native) };
+        self.joined = true; // avoid joining in the destructor
+    }
+}
+
+#[unsafe_destructor]
+impl<T: Send> Drop for JoinGuard<T> {
+    fn drop(&mut self) {
+        if !self.joined {
+            unsafe { imp::join(self.native) };
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use prelude::*;
+    use any::{Any, AnyRefExt};
+    use boxed::BoxAny;
+    use result;
+    use std::io::{ChanReader, ChanWriter};
+    use thunk::Thunk;
+    use super::{Thread, Builder};
+
+    // !!! These tests are dangerous. If something is buggy, they will hang, !!!
+    // !!! instead of exiting cleanly. This might wedge the buildbots.       !!!
+
+    #[test]
+    fn test_unnamed_thread() {
+        Thread::spawn(move|| {
+            assert!(Thread::current().name().is_none());
+        }).join().map_err(|_| ()).unwrap();
+    }
+
+    #[test]
+    fn test_named_thread() {
+        Builder::new().name("ada lovelace".to_string()).spawn(move|| {
+            assert!(Thread::current().name().unwrap() == "ada lovelace".to_string());
+        }).join().map_err(|_| ()).unwrap();
+    }
+
+    #[test]
+    fn test_run_basic() {
+        let (tx, rx) = channel();
+        Thread::spawn(move|| {
+            tx.send(());
+        }).detach();
+        rx.recv();
+    }
+
+    #[test]
+    fn test_join_success() {
+        match Thread::spawn(move|| -> String {
+            "Success!".to_string()
+        }).join().as_ref().map(|s| s.as_slice()) {
+            result::Result::Ok("Success!") => (),
+            _ => panic!()
+        }
+    }
+
+    #[test]
+    fn test_join_panic() {
+        match Thread::spawn(move|| {
+            panic!()
+        }).join() {
+            result::Result::Err(_) => (),
+            result::Result::Ok(()) => panic!()
+        }
+    }
+
+    #[test]
+    fn test_spawn_sched() {
+        use clone::Clone;
+
+        let (tx, rx) = channel();
+
+        fn f(i: int, tx: Sender<()>) {
+            let tx = tx.clone();
+            Thread::spawn(move|| {
+                if i == 0 {
+                    tx.send(());
+                } else {
+                    f(i - 1, tx);
+                }
+            }).detach();
+
+        }
+        f(10, tx);
+        rx.recv();
+    }
+
+    #[test]
+    fn test_spawn_sched_childs_on_default_sched() {
+        let (tx, rx) = channel();
+
+        Thread::spawn(move|| {
+            Thread::spawn(move|| {
+                tx.send(());
+            }).detach();
+        }).detach();
+
+        rx.recv();
+    }
+
+    fn avoid_copying_the_body<F>(spawnfn: F) where F: FnOnce(Thunk) {
+        let (tx, rx) = channel::<uint>();
+
+        let x = box 1;
+        let x_in_parent = (&*x) as *const int as uint;
+
+        spawnfn(Thunk::new(move|| {
+            let x_in_child = (&*x) as *const int as uint;
+            tx.send(x_in_child);
+        }));
+
+        let x_in_child = rx.recv();
+        assert_eq!(x_in_parent, x_in_child);
+    }
+
+    #[test]
+    fn test_avoid_copying_the_body_spawn() {
+        avoid_copying_the_body(|v| {
+            Thread::spawn(move || v.invoke(())).detach();
+        });
+    }
+
+    #[test]
+    fn test_avoid_copying_the_body_thread_spawn() {
+        avoid_copying_the_body(|f| {
+            Thread::spawn(move|| {
+                f.invoke(());
+            }).detach();
+        })
+    }
+
+    #[test]
+    fn test_avoid_copying_the_body_join() {
+        avoid_copying_the_body(|f| {
+            let _ = Thread::spawn(move|| {
+                f.invoke(())
+            }).join();
+        })
+    }
+
+    #[test]
+    fn test_child_doesnt_ref_parent() {
+        // If the child refcounts the parent task, this will stack overflow when
+        // climbing the task tree to dereference each ancestor. (See #1789)
+        // (well, it would if the constant were 8000+ - I lowered it to be more
+        // valgrind-friendly. try this at home, instead..!)
+        static GENERATIONS: uint = 16;
+        fn child_no(x: uint) -> Thunk {
+            return Thunk::new(move|| {
+                if x < GENERATIONS {
+                    Thread::spawn(move|| child_no(x+1).invoke(())).detach();
+                }
+            });
+        }
+        Thread::spawn(|| child_no(0).invoke(())).detach();
+    }
+
+    #[test]
+    fn test_simple_newsched_spawn() {
+        Thread::spawn(move || {}).detach();
+    }
+
+    #[test]
+    fn test_try_panic_message_static_str() {
+        match Thread::spawn(move|| {
+            panic!("static string");
+        }).join() {
+            Err(e) => {
+                type T = &'static str;
+                assert!(e.is::<T>());
+                assert_eq!(*e.downcast::<T>().unwrap(), "static string");
+            }
+            Ok(()) => panic!()
+        }
+    }
+
+    #[test]
+    fn test_try_panic_message_owned_str() {
+        match Thread::spawn(move|| {
+            panic!("owned string".to_string());
+        }).join() {
+            Err(e) => {
+                type T = String;
+                assert!(e.is::<T>());
+                assert_eq!(*e.downcast::<T>().unwrap(), "owned string".to_string());
+            }
+            Ok(()) => panic!()
+        }
+    }
+
+    #[test]
+    fn test_try_panic_message_any() {
+        match Thread::spawn(move|| {
+            panic!(box 413u16 as Box<Any + Send>);
+        }).join() {
+            Err(e) => {
+                type T = Box<Any + Send>;
+                assert!(e.is::<T>());
+                let any = e.downcast::<T>().unwrap();
+                assert!(any.is::<u16>());
+                assert_eq!(*any.downcast::<u16>().unwrap(), 413u16);
+            }
+            Ok(()) => panic!()
+        }
+    }
+
+    #[test]
+    fn test_try_panic_message_unit_struct() {
+        struct Juju;
+
+        match Thread::spawn(move|| {
+            panic!(Juju)
+        }).join() {
+            Err(ref e) if e.is::<Juju>() => {}
+            Err(_) | Ok(()) => panic!()
+        }
+    }
+
+    #[test]
+    fn test_stdout() {
+        let (tx, rx) = channel();
+        let mut reader = ChanReader::new(rx);
+        let stdout = ChanWriter::new(tx);
+
+        let r = Builder::new().stdout(box stdout as Box<Writer + Send>).spawn(move|| {
+            print!("Hello, world!");
+        }).join();
+        assert!(r.is_ok());
+
+        let output = reader.read_to_string().unwrap();
+        assert_eq!(output, "Hello, world!".to_string());
+    }
+
+    // NOTE: the corresponding test for stderr is in run-pass/task-stderr, due
+    // to the test harness apparently interfering with stderr configuration.
+}
diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread_local/mod.rs
new file mode 100644
index 00000000000..04718dcc6ae
--- /dev/null
+++ b/src/libstd/thread_local/mod.rs
@@ -0,0 +1,653 @@
+// 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.
+
+//! Thread local storage
+//!
+//! This module provides an implementation of thread local storage for Rust
+//! programs. Thread local storage is a method of storing data into a global
+//! variable which each thread in the program will have its own copy of.
+//! Threads do not share this data, so accesses do not need to be synchronized.
+//!
+//! At a high level, this module provides two variants of storage:
+//!
+//! * Owning thread local storage. This is a type of thread local key which
+//!   owns the value that it contains, and will destroy the value when the
+//!   thread exits. This variant is created with the `thread_local!` macro and
+//!   can contain any value which is `'static` (no borrowed pointers.
+//!
+//! * Scoped thread local storage. This type of key is used to store a reference
+//!   to a value into local storage temporarily for the scope of a function
+//!   call. There are no restrictions on what types of values can be placed
+//!   into this key.
+//!
+//! Both forms of thread local storage provide an accessor function, `with`,
+//! which will yield a shared reference to the value to the specified
+//! closure. Thread local keys only allow shared access to values as there is no
+//! way to guarantee uniqueness if a mutable borrow was allowed. Most values
+//! will want to make use of some form of **interior mutability** through the
+//! `Cell` or `RefCell` types.
+
+#![macro_escape]
+#![experimental]
+
+use prelude::*;
+
+use cell::UnsafeCell;
+
+// Sure wish we had macro hygiene, no?
+#[doc(hidden)] pub use self::imp::Key as KeyInner;
+#[doc(hidden)] pub use self::imp::destroy_value;
+#[doc(hidden)] pub use sys_common::thread_local::INIT_INNER as OS_INIT_INNER;
+#[doc(hidden)] pub use sys_common::thread_local::StaticKey as OsStaticKey;
+
+pub mod scoped;
+
+/// A thread local storage key which owns its contents.
+///
+/// This key uses the fastest possible implementation available to it for the
+/// target platform. It is instantiated with the `thread_local!` macro and the
+/// primary method is the `with` method.
+///
+/// The `with` method yields a reference to the contained value which cannot be
+/// sent across tasks or escape the given closure.
+///
+/// # Initialization and Destruction
+///
+/// Initialization is dynamically performed on the first call to `with()`
+/// within a thread, and values support destructors which will be run when a
+/// thread exits.
+///
+/// # Example
+///
+/// ```
+/// use std::cell::RefCell;
+/// use std::thread::Thread;
+///
+/// thread_local!(static FOO: RefCell<uint> = RefCell::new(1));
+///
+/// FOO.with(|f| {
+///     assert_eq!(*f.borrow(), 1);
+///     *f.borrow_mut() = 2;
+/// });
+///
+/// // each thread starts out with the initial value of 1
+/// Thread::spawn(move|| {
+///     FOO.with(|f| {
+///         assert_eq!(*f.borrow(), 1);
+///         *f.borrow_mut() = 3;
+///     });
+/// }).detach();
+///
+/// // we retain our original value of 2 despite the child thread
+/// FOO.with(|f| {
+///     assert_eq!(*f.borrow(), 2);
+/// });
+/// ```
+pub struct Key<T> {
+    // The key itself may be tagged with #[thread_local], and this `Key` is
+    // stored as a `static`, and it's not valid for a static to reference the
+    // address of another thread_local static. For this reason we kinda wonkily
+    // work around this by generating a shim function which will give us the
+    // address of the inner TLS key at runtime.
+    //
+    // This is trivially devirtualizable by LLVM because we never store anything
+    // to this field and rustc can declare the `static` as constant as well.
+    #[doc(hidden)]
+    pub inner: fn() -> &'static KeyInner<UnsafeCell<Option<T>>>,
+
+    // initialization routine to invoke to create a value
+    #[doc(hidden)]
+    pub init: fn() -> T,
+}
+
+/// Declare a new thread local storage key of type `std::thread_local::Key`.
+#[macro_export]
+#[doc(hidden)]
+macro_rules! thread_local {
+    (static $name:ident: $t:ty = $init:expr) => (
+        static $name: ::std::thread_local::Key<$t> = {
+            use std::cell::UnsafeCell as __UnsafeCell;
+            use std::thread_local::KeyInner as __KeyInner;
+            use std::option::Option as __Option;
+            use std::option::Option::None as __None;
+
+            __thread_local_inner!(static __KEY: __UnsafeCell<__Option<$t>> = {
+                __UnsafeCell { value: __None }
+            });
+            fn __init() -> $t { $init }
+            fn __getit() -> &'static __KeyInner<__UnsafeCell<__Option<$t>>> {
+                &__KEY
+            }
+            ::std::thread_local::Key { inner: __getit, init: __init }
+        };
+    );
+    (pub static $name:ident: $t:ty = $init:expr) => (
+        pub static $name: ::std::thread_local::Key<$t> = {
+            use std::cell::UnsafeCell as __UnsafeCell;
+            use std::thread_local::KeyInner as __KeyInner;
+            use std::option::Option as __Option;
+            use std::option::Option::None as __None;
+
+            __thread_local_inner!(static __KEY: __UnsafeCell<__Option<$t>> = {
+                __UnsafeCell { value: __None }
+            });
+            fn __init() -> $t { $init }
+            fn __getit() -> &'static __KeyInner<__UnsafeCell<__Option<$t>>> {
+                &__KEY
+            }
+            ::std::thread_local::Key { inner: __getit, init: __init }
+        };
+    );
+}
+
+// Macro pain #4586:
+//
+// When cross compiling, rustc will load plugins and macros from the *host*
+// platform before search for macros from the target platform. This is primarily
+// done to detect, for example, plugins. Ideally the macro below would be
+// defined once per module below, but unfortunately this means we have the
+// following situation:
+//
+// 1. We compile libstd for x86_64-unknown-linux-gnu, this thread_local!() macro
+//    will inject #[thread_local] statics.
+// 2. We then try to compile a program for arm-linux-androideabi
+// 3. The compiler has a host of linux and a target of android, so it loads
+//    macros from the *linux* libstd.
+// 4. The macro generates a #[thread_local] field, but the android libstd does
+//    not use #[thread_local]
+// 5. Compile error about structs with wrong fields.
+//
+// To get around this, we're forced to inject the #[cfg] logic into the macro
+// itself. Woohoo.
+
+#[macro_export]
+macro_rules! __thread_local_inner {
+    (static $name:ident: $t:ty = $init:expr) => (
+        #[cfg_attr(any(target_os = "macos", target_os = "linux"), thread_local)]
+        static $name: ::std::thread_local::KeyInner<$t> =
+            __thread_local_inner!($init, $t);
+    );
+    (pub static $name:ident: $t:ty = $init:expr) => (
+        #[cfg_attr(any(target_os = "macos", target_os = "linux"), thread_local)]
+        pub static $name: ::std::thread_local::KeyInner<$t> =
+            __thread_local_inner!($init, $t);
+    );
+    ($init:expr, $t:ty) => ({
+        #[cfg(any(target_os = "macos", target_os = "linux"))]
+        const INIT: ::std::thread_local::KeyInner<$t> = {
+            ::std::thread_local::KeyInner {
+                inner: ::std::cell::UnsafeCell { value: $init },
+                dtor_registered: ::std::cell::UnsafeCell { value: false },
+                dtor_running: ::std::cell::UnsafeCell { value: false },
+            }
+        };
+
+        #[cfg(all(stage0, not(any(target_os = "macos", target_os = "linux"))))]
+        const INIT: ::std::thread_local::KeyInner<$t> = {
+            unsafe extern fn __destroy(ptr: *mut u8) {
+                ::std::thread_local::destroy_value::<$t>(ptr);
+            }
+
+            ::std::thread_local::KeyInner {
+                inner: ::std::cell::UnsafeCell { value: $init },
+                os: ::std::thread_local::OsStaticKey {
+                    inner: ::std::thread_local::OS_INIT_INNER,
+                    dtor: ::std::option::Option::Some(__destroy),
+                },
+            }
+        };
+
+        #[cfg(all(not(stage0), not(any(target_os = "macos", target_os = "linux"))))]
+        const INIT: ::std::thread_local::KeyInner<$t> = {
+            unsafe extern fn __destroy(ptr: *mut u8) {
+                ::std::thread_local::destroy_value::<$t>(ptr);
+            }
+
+            ::std::thread_local::KeyInner {
+                inner: ::std::cell::UnsafeCell { value: $init },
+                os: ::std::thread_local::OsStaticKey {
+                    inner: ::std::thread_local::OS_INIT_INNER,
+                    dtor: ::std::option::Option::Some(__destroy as unsafe extern fn(*mut u8)),
+                },
+            }
+        };
+
+        INIT
+    });
+}
+
+impl<T: 'static> Key<T> {
+    /// Acquire a reference to the value in this TLS key.
+    ///
+    /// This will lazily initialize the value if this thread has not referenced
+    /// this key yet.
+    ///
+    /// # Panics
+    ///
+    /// This function will `panic!()` if the key currently has its
+    /// destructor running, and it **may** panic if the destructor has
+    /// previously been run for this thread.
+    pub fn with<F, R>(&'static self, f: F) -> R
+                      where F: FnOnce(&T) -> R {
+        let slot = (self.inner)();
+        unsafe {
+            let slot = slot.get().expect("cannot access a TLS value during or \
+                                          after it is destroyed");
+            if (*slot.get()).is_none() {
+                *slot.get() = Some((self.init)());
+            }
+            f((*slot.get()).as_ref().unwrap())
+        }
+    }
+
+    /// Test this TLS key to determine whether its value has been destroyed for
+    /// the current thread or not.
+    ///
+    /// This will not initialize the key if it is not already initialized.
+    pub fn destroyed(&'static self) -> bool {
+        unsafe { (self.inner)().get().is_none() }
+    }
+}
+
+#[cfg(any(target_os = "macos", target_os = "linux"))]
+mod imp {
+    use prelude::*;
+
+    use cell::UnsafeCell;
+    use intrinsics;
+    use ptr;
+
+    #[doc(hidden)]
+    pub struct Key<T> {
+        // Place the inner bits in an `UnsafeCell` to currently get around the
+        // "only Sync statics" restriction. This allows any type to be placed in
+        // the cell.
+        //
+        // Note that all access requires `T: 'static` so it can't be a type with
+        // any borrowed pointers still.
+        pub inner: UnsafeCell<T>,
+
+        // Metadata to keep track of the state of the destructor. Remember that
+        // these variables are thread-local, not global.
+        pub dtor_registered: UnsafeCell<bool>, // should be Cell
+        pub dtor_running: UnsafeCell<bool>, // should be Cell
+    }
+
+    #[doc(hidden)]
+    impl<T> Key<T> {
+        pub unsafe fn get(&'static self) -> Option<&'static T> {
+            if intrinsics::needs_drop::<T>() && *self.dtor_running.get() {
+                return None
+            }
+            self.register_dtor();
+            Some(&*self.inner.get())
+        }
+
+        unsafe fn register_dtor(&self) {
+            if !intrinsics::needs_drop::<T>() || *self.dtor_registered.get() {
+                return
+            }
+
+            register_dtor(self as *const _ as *mut u8,
+                          destroy_value::<T>);
+            *self.dtor_registered.get() = true;
+        }
+    }
+
+    // Since what appears to be glibc 2.18 this symbol has been shipped which
+    // GCC and clang both use to invoke destructors in thread_local globals, so
+    // let's do the same!
+    //
+    // Note, however, that we run on lots older linuxes, as well as cross
+    // compiling from a newer linux to an older linux, so we also have a
+    // fallback implementation to use as well.
+    //
+    // Due to rust-lang/rust#18804, make sure this is not generic!
+    #[cfg(target_os = "linux")]
+    unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
+        use mem;
+        use libc;
+        use sys_common::thread_local as os;
+
+        extern {
+            static __dso_handle: *mut u8;
+            #[linkage = "extern_weak"]
+            static __cxa_thread_atexit_impl: *const ();
+        }
+        if !__cxa_thread_atexit_impl.is_null() {
+            type F = unsafe extern fn(dtor: unsafe extern fn(*mut u8),
+                                      arg: *mut u8,
+                                      dso_handle: *mut u8) -> libc::c_int;
+            mem::transmute::<*const (), F>(__cxa_thread_atexit_impl)
+            (dtor, t, __dso_handle);
+            return
+        }
+
+        // The fallback implementation uses a vanilla OS-based TLS key to track
+        // the list of destructors that need to be run for this thread. The key
+        // then has its own destructor which runs all the other destructors.
+        //
+        // The destructor for DTORS is a little special in that it has a `while`
+        // loop to continuously drain the list of registered destructors. It
+        // *should* be the case that this loop always terminates because we
+        // provide the guarantee that a TLS key cannot be set after it is
+        // flagged for destruction.
+        #[cfg(not(stage0))]
+        static DTORS: os::StaticKey = os::StaticKey {
+            inner: os::INIT_INNER,
+            dtor: Some(run_dtors as unsafe extern "C" fn(*mut u8)),
+        };
+        #[cfg(stage0)]
+        static DTORS: os::StaticKey = os::StaticKey {
+            inner: os::INIT_INNER,
+            dtor: Some(run_dtors),
+        };
+        type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>;
+        if DTORS.get().is_null() {
+            let v: Box<List> = box Vec::new();
+            DTORS.set(mem::transmute(v));
+        }
+        let list: &mut List = &mut *(DTORS.get() as *mut List);
+        list.push((t, dtor));
+
+        unsafe extern fn run_dtors(mut ptr: *mut u8) {
+            while !ptr.is_null() {
+                let list: Box<List> = mem::transmute(ptr);
+                for &(ptr, dtor) in list.iter() {
+                    dtor(ptr);
+                }
+                ptr = DTORS.get();
+                DTORS.set(0 as *mut _);
+            }
+        }
+    }
+
+    // OSX's analog of the above linux function is this _tlv_atexit function.
+    // The disassembly of thread_local globals in C++ (at least produced by
+    // clang) will have this show up in the output.
+    #[cfg(target_os = "macos")]
+    unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
+        extern {
+            fn _tlv_atexit(dtor: unsafe extern fn(*mut u8),
+                           arg: *mut u8);
+        }
+        _tlv_atexit(dtor, t);
+    }
+
+    #[doc(hidden)]
+    pub unsafe extern fn destroy_value<T>(ptr: *mut u8) {
+        let ptr = ptr as *mut Key<T>;
+        // Right before we run the user destructor be sure to flag the
+        // destructor as running for this thread so calls to `get` will return
+        // `None`.
+        *(*ptr).dtor_running.get() = true;
+        ptr::read((*ptr).inner.get() as *const T);
+    }
+}
+
+#[cfg(not(any(target_os = "macos", target_os = "linux")))]
+mod imp {
+    use prelude::*;
+
+    use cell::UnsafeCell;
+    use mem;
+    use sys_common::thread_local::StaticKey as OsStaticKey;
+
+    #[doc(hidden)]
+    pub struct Key<T> {
+        // Statically allocated initialization expression, using an `UnsafeCell`
+        // for the same reasons as above.
+        pub inner: UnsafeCell<T>,
+
+        // OS-TLS key that we'll use to key off.
+        pub os: OsStaticKey,
+    }
+
+    struct Value<T: 'static> {
+        key: &'static Key<T>,
+        value: T,
+    }
+
+    #[doc(hidden)]
+    impl<T> Key<T> {
+        pub unsafe fn get(&'static self) -> Option<&'static T> {
+            self.ptr().map(|p| &*p)
+        }
+
+        unsafe fn ptr(&'static self) -> Option<*mut T> {
+            let ptr = self.os.get() as *mut Value<T>;
+            if !ptr.is_null() {
+                if ptr as uint == 1 {
+                    return None
+                }
+                return Some(&mut (*ptr).value as *mut T);
+            }
+
+            // If the lookup returned null, we haven't initialized our own local
+            // copy, so do that now.
+            //
+            // Also note that this transmute_copy should be ok because the value
+            // `inner` is already validated to be a valid `static` value, so we
+            // should be able to freely copy the bits.
+            let ptr: Box<Value<T>> = box Value {
+                key: self,
+                value: mem::transmute_copy(&self.inner),
+            };
+            let ptr: *mut Value<T> = mem::transmute(ptr);
+            self.os.set(ptr as *mut u8);
+            Some(&mut (*ptr).value as *mut T)
+        }
+    }
+
+    #[doc(hidden)]
+    pub unsafe extern fn destroy_value<T: 'static>(ptr: *mut u8) {
+        // The OS TLS ensures that this key contains a NULL value when this
+        // destructor starts to run. We set it back to a sentinel value of 1 to
+        // ensure that any future calls to `get` for this thread will return
+        // `None`.
+        //
+        // Note that to prevent an infinite loop we reset it back to null right
+        // before we return from the destructor ourselves.
+        let ptr: Box<Value<T>> = mem::transmute(ptr);
+        let key = ptr.key;
+        key.os.set(1 as *mut u8);
+        drop(ptr);
+        key.os.set(0 as *mut u8);
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use prelude::*;
+
+    use cell::UnsafeCell;
+    use thread::Thread;
+
+    struct Foo(Sender<()>);
+
+    impl Drop for Foo {
+        fn drop(&mut self) {
+            let Foo(ref s) = *self;
+            s.send(());
+        }
+    }
+
+    #[test]
+    fn smoke_no_dtor() {
+        thread_local!(static FOO: UnsafeCell<int> = UnsafeCell { value: 1 });
+
+        FOO.with(|f| unsafe {
+            assert_eq!(*f.get(), 1);
+            *f.get() = 2;
+        });
+        let (tx, rx) = channel();
+        spawn(move|| {
+            FOO.with(|f| unsafe {
+                assert_eq!(*f.get(), 1);
+            });
+            tx.send(());
+        });
+        rx.recv();
+
+        FOO.with(|f| unsafe {
+            assert_eq!(*f.get(), 2);
+        });
+    }
+
+    #[test]
+    fn smoke_dtor() {
+        thread_local!(static FOO: UnsafeCell<Option<Foo>> = UnsafeCell {
+            value: None
+        });
+
+        let (tx, rx) = channel();
+        spawn(move|| unsafe {
+            let mut tx = Some(tx);
+            FOO.with(|f| {
+                *f.get() = Some(Foo(tx.take().unwrap()));
+            });
+        });
+        rx.recv();
+    }
+
+    #[test]
+    fn circular() {
+        struct S1;
+        struct S2;
+        thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell {
+            value: None
+        });
+        thread_local!(static K2: UnsafeCell<Option<S2>> = UnsafeCell {
+            value: None
+        });
+        static mut HITS: uint = 0;
+
+        impl Drop for S1 {
+            fn drop(&mut self) {
+                unsafe {
+                    HITS += 1;
+                    if K2.destroyed() {
+                        assert_eq!(HITS, 3);
+                    } else {
+                        if HITS == 1 {
+                            K2.with(|s| *s.get() = Some(S2));
+                        } else {
+                            assert_eq!(HITS, 3);
+                        }
+                    }
+                }
+            }
+        }
+        impl Drop for S2 {
+            fn drop(&mut self) {
+                unsafe {
+                    HITS += 1;
+                    assert!(!K1.destroyed());
+                    assert_eq!(HITS, 2);
+                    K1.with(|s| *s.get() = Some(S1));
+                }
+            }
+        }
+
+        Thread::spawn(move|| {
+            drop(S1);
+        }).join();
+    }
+
+    #[test]
+    fn self_referential() {
+        struct S1;
+        thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell {
+            value: None
+        });
+
+        impl Drop for S1 {
+            fn drop(&mut self) {
+                assert!(K1.destroyed());
+            }
+        }
+
+        Thread::spawn(move|| unsafe {
+            K1.with(|s| *s.get() = Some(S1));
+        }).join();
+    }
+
+    #[test]
+    fn dtors_in_dtors_in_dtors() {
+        struct S1(Sender<()>);
+        thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell {
+            value: None
+        });
+        thread_local!(static K2: UnsafeCell<Option<Foo>> = UnsafeCell {
+            value: None
+        });
+
+        impl Drop for S1 {
+            fn drop(&mut self) {
+                let S1(ref tx) = *self;
+                unsafe {
+                    if !K2.destroyed() {
+                        K2.with(|s| *s.get() = Some(Foo(tx.clone())));
+                    }
+                }
+            }
+        }
+
+        let (tx, rx) = channel();
+        spawn(move|| unsafe {
+            let mut tx = Some(tx);
+            K1.with(|s| *s.get() = Some(S1(tx.take().unwrap())));
+        });
+        rx.recv();
+    }
+}
+
+#[cfg(test)]
+mod dynamic_tests {
+    use prelude::*;
+
+    use cell::RefCell;
+    use collections::HashMap;
+
+    #[test]
+    fn smoke() {
+        fn square(i: int) -> int { i * i }
+        thread_local!(static FOO: int = square(3));
+
+        FOO.with(|f| {
+            assert_eq!(*f, 9);
+        });
+    }
+
+    #[test]
+    fn hashmap() {
+        fn map() -> RefCell<HashMap<int, int>> {
+            let mut m = HashMap::new();
+            m.insert(1, 2);
+            RefCell::new(m)
+        }
+        thread_local!(static FOO: RefCell<HashMap<int, int>> = map());
+
+        FOO.with(|map| {
+            assert_eq!(map.borrow()[1], 2);
+        });
+    }
+
+    #[test]
+    fn refcell_vec() {
+        thread_local!(static FOO: RefCell<Vec<uint>> = RefCell::new(vec![1, 2, 3]));
+
+        FOO.with(|vec| {
+            assert_eq!(vec.borrow().len(), 3);
+            vec.borrow_mut().push(4);
+            assert_eq!(vec.borrow()[3], 4);
+        });
+    }
+}
diff --git a/src/libstd/thread_local/scoped.rs b/src/libstd/thread_local/scoped.rs
new file mode 100644
index 00000000000..643a0f55e74
--- /dev/null
+++ b/src/libstd/thread_local/scoped.rs
@@ -0,0 +1,264 @@
+// 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.
+
+//! Scoped thread-local storage
+//!
+//! This module provides the ability to generate *scoped* thread-local
+//! variables. In this sense, scoped indicates that thread local storage
+//! actually stores a reference to a value, and this reference is only placed
+//! in storage for a scoped amount of time.
+//!
+//! There are no restrictions on what types can be placed into a scoped
+//! variable, but all scoped variables are initialized to the equivalent of
+//! null. Scoped thread local storage is useful when a value is present for a known
+//! period of time and it is not required to relinquish ownership of the
+//! contents.
+//!
+//! # Example
+//!
+//! ```
+//! scoped_thread_local!(static FOO: uint);
+//!
+//! // Initially each scoped slot is empty.
+//! assert!(!FOO.is_set());
+//!
+//! // When inserting a value, the value is only in place for the duration
+//! // of the closure specified.
+//! FOO.set(&1, || {
+//!     FOO.with(|slot| {
+//!         assert_eq!(*slot, 1);
+//!     });
+//! });
+//! ```
+
+#![macro_escape]
+
+use prelude::*;
+
+// macro hygiene sure would be nice, wouldn't it?
+#[doc(hidden)] pub use self::imp::KeyInner;
+#[doc(hidden)] pub use sys_common::thread_local::INIT as OS_INIT;
+
+/// Type representing a thread local storage key corresponding to a reference
+/// to the type parameter `T`.
+///
+/// Keys are statically allocated and can contain a reference to an instance of
+/// type `T` scoped to a particular lifetime. Keys provides two methods, `set`
+/// and `with`, both of which currently use closures to control the scope of
+/// their contents.
+pub struct Key<T> { #[doc(hidden)] pub inner: KeyInner<T> }
+
+/// Declare a new scoped thread local storage key.
+///
+/// This macro declares a `static` item on which methods are used to get and
+/// set the value stored within.
+#[macro_export]
+macro_rules! scoped_thread_local {
+    (static $name:ident: $t:ty) => (
+        __scoped_thread_local_inner!(static $name: $t)
+    );
+    (pub static $name:ident: $t:ty) => (
+        __scoped_thread_local_inner!(pub static $name: $t)
+    );
+}
+
+#[macro_export]
+#[doc(hidden)]
+macro_rules! __scoped_thread_local_inner {
+    (static $name:ident: $t:ty) => (
+        #[cfg_attr(not(any(windows, target_os = "android", target_os = "ios")),
+                   thread_local)]
+        static $name: ::std::thread_local::scoped::Key<$t> =
+            __scoped_thread_local_inner!($t);
+    );
+    (pub static $name:ident: $t:ty) => (
+        #[cfg_attr(not(any(windows, target_os = "android", target_os = "ios")),
+                   thread_local)]
+        pub static $name: ::std::thread_local::scoped::Key<$t> =
+            __scoped_thread_local_inner!($t);
+    );
+    ($t:ty) => ({
+        use std::thread_local::scoped::Key as __Key;
+
+        #[cfg(not(any(windows, target_os = "android", target_os = "ios")))]
+        const INIT: __Key<$t> = __Key {
+            inner: ::std::thread_local::scoped::KeyInner {
+                inner: ::std::cell::UnsafeCell { value: 0 as *mut _ },
+            }
+        };
+
+        #[cfg(any(windows, target_os = "android", target_os = "ios"))]
+        const INIT: __Key<$t> = __Key {
+            inner: ::std::thread_local::scoped::KeyInner {
+                inner: ::std::thread_local::scoped::OS_INIT,
+                marker: ::std::kinds::marker::InvariantType,
+            }
+        };
+
+        INIT
+    })
+}
+
+impl<T> Key<T> {
+    /// Insert a value into this scoped thread local storage slot for a
+    /// duration of a closure.
+    ///
+    /// While `cb` is running, the value `t` will be returned by `get` unless
+    /// this function is called recursively inside of `cb`.
+    ///
+    /// Upon return, this function will restore the previous value, if any
+    /// was available.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// scoped_thread_local!(static FOO: uint);
+    ///
+    /// FOO.set(&100, || {
+    ///     let val = FOO.with(|v| *v);
+    ///     assert_eq!(val, 100);
+    ///
+    ///     // set can be called recursively
+    ///     FOO.set(&101, || {
+    ///         // ...
+    ///     });
+    ///
+    ///     // Recursive calls restore the previous value.
+    ///     let val = FOO.with(|v| *v);
+    ///     assert_eq!(val, 100);
+    /// });
+    /// ```
+    pub fn set<R, F>(&'static self, t: &T, cb: F) -> R where
+        F: FnOnce() -> R,
+    {
+        struct Reset<'a, T: 'a> {
+            key: &'a KeyInner<T>,
+            val: *mut T,
+        }
+        #[unsafe_destructor]
+        impl<'a, T> Drop for Reset<'a, T> {
+            fn drop(&mut self) {
+                unsafe { self.key.set(self.val) }
+            }
+        }
+
+        let prev = unsafe {
+            let prev = self.inner.get();
+            self.inner.set(t as *const T as *mut T);
+            prev
+        };
+
+        let _reset = Reset { key: &self.inner, val: prev };
+        cb()
+    }
+
+    /// Get a value out of this scoped variable.
+    ///
+    /// This function takes a closure which receives the value of this
+    /// variable.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if `set` has not previously been called.
+    ///
+    /// # Example
+    ///
+    /// ```no_run
+    /// scoped_thread_local!(static FOO: uint);
+    ///
+    /// FOO.with(|slot| {
+    ///     // work with `slot`
+    /// });
+    /// ```
+    pub fn with<R, F>(&'static self, cb: F) -> R where
+        F: FnOnce(&T) -> R
+    {
+        unsafe {
+            let ptr = self.inner.get();
+            assert!(!ptr.is_null(), "cannot access a scoped thread local \
+                                     variable without calling `set` first");
+            cb(&*ptr)
+        }
+    }
+
+    /// Test whether this TLS key has been `set` for the current thread.
+    pub fn is_set(&'static self) -> bool {
+        unsafe { !self.inner.get().is_null() }
+    }
+}
+
+#[cfg(not(any(windows, target_os = "android", target_os = "ios")))]
+mod imp {
+    use std::cell::UnsafeCell;
+
+    // FIXME: Should be a `Cell`, but that's not `Sync`
+    #[doc(hidden)]
+    pub struct KeyInner<T> { pub inner: UnsafeCell<*mut T> }
+
+    #[doc(hidden)]
+    impl<T> KeyInner<T> {
+        #[doc(hidden)]
+        pub unsafe fn set(&self, ptr: *mut T) { *self.inner.get() = ptr; }
+        #[doc(hidden)]
+        pub unsafe fn get(&self) -> *mut T { *self.inner.get() }
+    }
+}
+
+#[cfg(any(windows, target_os = "android", target_os = "ios"))]
+mod imp {
+    use kinds::marker;
+    use sys_common::thread_local::StaticKey as OsStaticKey;
+
+    #[doc(hidden)]
+    pub struct KeyInner<T> {
+        pub inner: OsStaticKey,
+        pub marker: marker::InvariantType<T>,
+    }
+
+    #[doc(hidden)]
+    impl<T> KeyInner<T> {
+        #[doc(hidden)]
+        pub unsafe fn set(&self, ptr: *mut T) { self.inner.set(ptr as *mut _) }
+        #[doc(hidden)]
+        pub unsafe fn get(&self) -> *mut T { self.inner.get() as *mut _ }
+    }
+}
+
+
+#[cfg(test)]
+mod tests {
+    use cell::Cell;
+    use prelude::*;
+
+    #[test]
+    fn smoke() {
+        scoped_thread_local!(static BAR: uint);
+
+        assert!(!BAR.is_set());
+        BAR.set(&1, || {
+            assert!(BAR.is_set());
+            BAR.with(|slot| {
+                assert_eq!(*slot, 1);
+            });
+        });
+        assert!(!BAR.is_set());
+    }
+
+    #[test]
+    fn cell_allowed() {
+        scoped_thread_local!(static BAR: Cell<uint>);
+
+        BAR.set(&Cell::new(1), || {
+            BAR.with(|slot| {
+                assert_eq!(slot.get(), 1);
+            });
+        });
+    }
+}
diff --git a/src/libstd/thunk.rs b/src/libstd/thunk.rs
new file mode 100644
index 00000000000..067926042f1
--- /dev/null
+++ b/src/libstd/thunk.rs
@@ -0,0 +1,55 @@
+// 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.
+
+// Because this module is temporary...
+#![allow(missing_docs)]
+
+use alloc::boxed::Box;
+use core::kinds::Send;
+use core::ops::FnOnce;
+
+pub struct Thunk<A=(),R=()> {
+    invoke: Box<Invoke<A,R>+Send>
+}
+
+impl<R> Thunk<(),R> {
+    pub fn new<F>(func: F) -> Thunk<(),R>
+        where F : FnOnce() -> R, F : Send
+    {
+        Thunk::with_arg(move|: ()| func())
+    }
+}
+
+impl<A,R> Thunk<A,R> {
+    pub fn with_arg<F>(func: F) -> Thunk<A,R>
+        where F : FnOnce(A) -> R, F : Send
+    {
+        Thunk {
+            invoke: box func
+        }
+    }
+
+    pub fn invoke(self, arg: A) -> R {
+        self.invoke.invoke(arg)
+    }
+}
+
+pub trait Invoke<A=(),R=()> {
+    fn invoke(self: Box<Self>, arg: A) -> R;
+}
+
+impl<A,R,F> Invoke<A,R> for F
+    where F : FnOnce(A) -> R
+{
+    fn invoke(self: Box<F>, arg: A) -> R {
+        let f = *self;
+        f(arg)
+    }
+}
diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs
index ec2d62ff85c..f7351c9580f 100644
--- a/src/libstd/time/duration.rs
+++ b/src/libstd/time/duration.rs
@@ -13,10 +13,12 @@
 #![experimental]
 
 use {fmt, i64};
-use ops::{Add, Sub, Mul, Div, Neg};
-use option::{Option, Some, None};
+use ops::{Add, Sub, Mul, Div, Neg, FnOnce};
+use option::Option;
+use option::Option::{Some, None};
 use num::Int;
-use result::{Result, Ok, Err};
+use result::Result;
+use result::Result::{Ok, Err};
 
 /// The number of nanoseconds in a microsecond.
 const NANOS_PER_MICRO: i32 = 1000;
@@ -37,14 +39,14 @@ const SECS_PER_DAY: i64 = 86400;
 /// The number of (non-leap) seconds in a week.
 const SECS_PER_WEEK: i64 = 604800;
 
-macro_rules! try_opt(
+macro_rules! try_opt {
     ($e:expr) => (match $e { Some(v) => v, None => return None })
-)
+}
 
 
 /// ISO 8601 time duration with nanosecond precision.
 /// This also allows for the negative duration; see individual methods for details.
-#[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
+#[deriving(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
 pub struct Duration {
     secs: i64,
     nanos: i32, // Always 0 <= nanos < NANOS_PER_SEC
@@ -136,7 +138,7 @@ impl Duration {
 
     /// Runs a closure, returning the duration of time it took to run the
     /// closure.
-    pub fn span(f: ||) -> Duration {
+    pub fn span<F>(f: F) -> Duration where F: FnOnce() {
         let before = super::precise_time_ns();
         f();
         Duration::nanoseconds((super::precise_time_ns() - before) as i64)
@@ -260,6 +262,8 @@ impl Duration {
     }
 }
 
+// NOTE(stage0): Remove impl after a snapshot
+#[cfg(stage0)]
 impl Neg<Duration> for Duration {
     #[inline]
     fn neg(&self) -> Duration {
@@ -271,8 +275,20 @@ impl Neg<Duration> for Duration {
     }
 }
 
-impl Add<Duration,Duration> for Duration {
-    fn add(&self, rhs: &Duration) -> Duration {
+#[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
+impl Neg<Duration> for Duration {
+    #[inline]
+    fn neg(self) -> Duration {
+        if self.nanos == 0 {
+            Duration { secs: -self.secs, nanos: 0 }
+        } else {
+            Duration { secs: -self.secs - 1, nanos: NANOS_PER_SEC - self.nanos }
+        }
+    }
+}
+
+impl Add<Duration, Duration> for Duration {
+    fn add(self, rhs: Duration) -> Duration {
         let mut secs = self.secs + rhs.secs;
         let mut nanos = self.nanos + rhs.nanos;
         if nanos >= NANOS_PER_SEC {
@@ -283,8 +299,8 @@ impl Add<Duration,Duration> for Duration {
     }
 }
 
-impl Sub<Duration,Duration> for Duration {
-    fn sub(&self, rhs: &Duration) -> Duration {
+impl Sub<Duration, Duration> for Duration {
+    fn sub(self, rhs: Duration) -> Duration {
         let mut secs = self.secs - rhs.secs;
         let mut nanos = self.nanos - rhs.nanos;
         if nanos < 0 {
@@ -295,22 +311,22 @@ impl Sub<Duration,Duration> for Duration {
     }
 }
 
-impl Mul<i32,Duration> for Duration {
-    fn mul(&self, rhs: &i32) -> Duration {
+impl Mul<i32, Duration> for Duration {
+    fn mul(self, rhs: i32) -> Duration {
         // Multiply nanoseconds as i64, because it cannot overflow that way.
-        let total_nanos = self.nanos as i64 * *rhs as i64;
+        let total_nanos = self.nanos as i64 * rhs as i64;
         let (extra_secs, nanos) = div_mod_floor_64(total_nanos, NANOS_PER_SEC as i64);
-        let secs = self.secs * *rhs as i64 + extra_secs;
+        let secs = self.secs * rhs as i64 + extra_secs;
         Duration { secs: secs, nanos: nanos as i32 }
     }
 }
 
-impl Div<i32,Duration> for Duration {
-    fn div(&self, rhs: &i32) -> Duration {
-        let mut secs = self.secs / *rhs as i64;
-        let carry = self.secs - secs * *rhs as i64;
-        let extra_nanos = carry * NANOS_PER_SEC as i64 / *rhs as i64;
-        let mut nanos = self.nanos / *rhs + extra_nanos as i32;
+impl Div<i32, Duration> for Duration {
+    fn div(self, rhs: i32) -> Duration {
+        let mut secs = self.secs / rhs as i64;
+        let carry = self.secs - secs * rhs as i64;
+        let extra_nanos = carry * NANOS_PER_SEC as i64 / rhs as i64;
+        let mut nanos = self.nanos / rhs + extra_nanos as i32;
         if nanos >= NANOS_PER_SEC {
             nanos -= NANOS_PER_SEC;
             secs += 1;
@@ -387,7 +403,7 @@ fn div_rem_64(this: i64, other: i64) -> (i64, i64) {
 mod tests {
     use super::{Duration, MIN, MAX};
     use {i32, i64};
-    use option::{Some, None};
+    use option::Option::{Some, None};
     use string::ToString;
 
     #[test]
@@ -538,20 +554,20 @@ mod tests {
 
     #[test]
     fn test_duration_fmt() {
-        assert_eq!(Duration::zero().to_string(), "PT0S".to_string());
-        assert_eq!(Duration::days(42).to_string(), "P42D".to_string());
-        assert_eq!(Duration::days(-42).to_string(), "-P42D".to_string());
-        assert_eq!(Duration::seconds(42).to_string(), "PT42S".to_string());
-        assert_eq!(Duration::milliseconds(42).to_string(), "PT0.042S".to_string());
-        assert_eq!(Duration::microseconds(42).to_string(), "PT0.000042S".to_string());
-        assert_eq!(Duration::nanoseconds(42).to_string(), "PT0.000000042S".to_string());
+        assert_eq!(Duration::zero().to_string(), "PT0S");
+        assert_eq!(Duration::days(42).to_string(), "P42D");
+        assert_eq!(Duration::days(-42).to_string(), "-P42D");
+        assert_eq!(Duration::seconds(42).to_string(), "PT42S");
+        assert_eq!(Duration::milliseconds(42).to_string(), "PT0.042S");
+        assert_eq!(Duration::microseconds(42).to_string(), "PT0.000042S");
+        assert_eq!(Duration::nanoseconds(42).to_string(), "PT0.000000042S");
         assert_eq!((Duration::days(7) + Duration::milliseconds(6543)).to_string(),
-                   "P7DT6.543S".to_string());
-        assert_eq!(Duration::seconds(-86401).to_string(), "-P1DT1S".to_string());
-        assert_eq!(Duration::nanoseconds(-1).to_string(), "-PT0.000000001S".to_string());
+                   "P7DT6.543S");
+        assert_eq!(Duration::seconds(-86401).to_string(), "-P1DT1S");
+        assert_eq!(Duration::nanoseconds(-1).to_string(), "-PT0.000000001S");
 
         // the format specifier should have no effect on `Duration`
         assert_eq!(format!("{:30}", Duration::days(1) + Duration::milliseconds(2345)),
-                   "P1DT2.345S".to_string());
+                   "P1DT2.345S");
     }
 }
diff --git a/src/libstd/tuple.rs b/src/libstd/tuple.rs
new file mode 100644
index 00000000000..5cd60d6e153
--- /dev/null
+++ b/src/libstd/tuple.rs
@@ -0,0 +1,66 @@
+// Copyright 2012 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.
+
+//! Operations on tuples
+//!
+//! To access a single element of a tuple one can use the following
+//! methods:
+//!
+//! * `valN` - returns a value of _N_-th element
+//! * `refN` - returns a reference to _N_-th element
+//! * `mutN` - returns a mutable reference to _N_-th element
+//!
+//! Indexing starts from zero, so `val0` returns first value, `val1`
+//! returns second value, and so on. In general, a tuple with _S_
+//! elements provides aforementioned methods suffixed with numbers
+//! from `0` to `S-1`. Traits which contain these methods are
+//! implemented for tuples with up to 12 elements.
+//!
+//! If every type inside a tuple implements one of the following
+//! traits, then a tuple itself also implements it.
+//!
+//! * `Clone`
+//! * `PartialEq`
+//! * `Eq`
+//! * `PartialOrd`
+//! * `Ord`
+//! * `Default`
+//!
+//! # Examples
+//!
+//! Using methods:
+//!
+//! ```
+//! #[allow(deprecated)]
+//! # fn main() {
+//! let pair = ("pi", 3.14f64);
+//! assert_eq!(pair.val0(), "pi");
+//! assert_eq!(pair.val1(), 3.14f64);
+//! # }
+//! ```
+//!
+//! Using traits implemented for tuples:
+//!
+//! ```
+//! use std::default::Default;
+//!
+//! let a = (1i, 2i);
+//! let b = (3i, 4i);
+//! assert!(a != b);
+//!
+//! let c = b.clone();
+//! assert!(b == c);
+//!
+//! let d : (u32, f32) = Default::default();
+//! assert_eq!(d, (0u32, 0.0f32));
+//! ```
+
+#![doc(primitive = "tuple")]
+#![stable]
diff --git a/src/libstd/unit.rs b/src/libstd/unit.rs
new file mode 100644
index 00000000000..012b175b031
--- /dev/null
+++ b/src/libstd/unit.rs
@@ -0,0 +1,45 @@
+// 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.
+
+#![doc(primitive = "unit")]
+#![stable]
+
+//! The `()` type, sometimes called "unit" or "nil".
+//!
+//! The `()` type has exactly one value `()`, and is used when there
+//! is no other meaningful value that could be returned. `()` is most
+//! commonly seen implicitly: functions without a `-> ...` implicitly
+//! have return type `()`, that is, these are equivalent:
+//!
+//! ```rust
+//! fn long() -> () {}
+//!
+//! fn short() {}
+//! ```
+//!
+//! The semicolon `;` can be used to discard the result of an
+//! expression at the end of a block, making the expression (and thus
+//! the block) evaluate to `()`. For example,
+//!
+//! ```rust
+//! fn returns_i64() -> i64 {
+//!     1i64
+//! }
+//! fn returns_unit() {
+//!     1i64;
+//! }
+//!
+//! let is_i64 = {
+//!     returns_i64()
+//! };
+//! let is_unit = {
+//!     returns_i64();
+//! };
+//! ```