about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorMarcin Fatyga <marcinf@google.com>2016-11-01 15:26:22 +0100
committerMarcin Fatyga <marcinf@google.com>2016-11-01 15:26:22 +0100
commit655effedf25e2039d283b839429bf2f42b7012a4 (patch)
tree34fd087d891556c70a14b26a90d1bdccd0a7ccb2 /src/libstd
parent4e2822c5c28bb342e5862ba7cc0b90b865c68be1 (diff)
parentac968c466451cb9aafd9e8598ddb396ed0e6fe31 (diff)
downloadrust-655effedf25e2039d283b839429bf2f42b7012a4.tar.gz
rust-655effedf25e2039d283b839429bf2f42b7012a4.zip
Merge branch 'master' of https://github.com/rust-lang/rust
Conflicts:
	src/libcoretest/lib.rs
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/build.rs10
-rw-r--r--src/libstd/collections/hash/bench.rs6
-rw-r--r--src/libstd/collections/hash/map.rs724
-rw-r--r--src/libstd/collections/hash/set.rs307
-rw-r--r--src/libstd/collections/hash/table.rs238
-rw-r--r--src/libstd/collections/mod.rs123
-rw-r--r--src/libstd/env.rs187
-rw-r--r--src/libstd/error.rs31
-rw-r--r--src/libstd/ffi/c_str.rs26
-rw-r--r--src/libstd/ffi/os_str.rs11
-rw-r--r--src/libstd/fs.rs149
-rw-r--r--src/libstd/io/buffered.rs28
-rw-r--r--src/libstd/io/cursor.rs55
-rw-r--r--src/libstd/io/impls.rs11
-rw-r--r--src/libstd/io/mod.rs189
-rw-r--r--src/libstd/io/stdio.rs16
-rw-r--r--src/libstd/lib.rs12
-rw-r--r--src/libstd/macros.rs42
-rw-r--r--src/libstd/memchr.rs275
-rw-r--r--src/libstd/net/addr.rs37
-rw-r--r--src/libstd/net/ip.rs37
-rw-r--r--src/libstd/net/mod.rs5
-rw-r--r--src/libstd/net/parser.rs4
-rw-r--r--src/libstd/net/tcp.rs2
-rw-r--r--src/libstd/net/test.rs2
-rw-r--r--src/libstd/net/udp.rs2
-rw-r--r--src/libstd/os/fuchsia/fs.rs103
-rw-r--r--src/libstd/os/fuchsia/mod.rs16
-rw-r--r--src/libstd/os/fuchsia/raw.rs270
-rw-r--r--src/libstd/os/haiku/fs.rs138
-rw-r--r--src/libstd/os/haiku/mod.rs16
-rw-r--r--src/libstd/os/haiku/raw.rs74
-rw-r--r--src/libstd/os/linux/raw.rs3
-rw-r--r--src/libstd/os/mod.rs2
-rw-r--r--src/libstd/os/raw.rs6
-rw-r--r--src/libstd/panic.rs46
-rw-r--r--src/libstd/panicking.rs30
-rw-r--r--src/libstd/path.rs143
-rw-r--r--src/libstd/primitive_docs.rs2
-rw-r--r--src/libstd/process.rs22
-rw-r--r--src/libstd/rand/mod.rs3
-rw-r--r--src/libstd/rt.rs2
-rw-r--r--src/libstd/rtdeps.rs4
-rw-r--r--src/libstd/sync/barrier.rs1
-rw-r--r--src/libstd/sync/condvar.rs4
-rw-r--r--src/libstd/sync/mpsc/mod.rs16
-rw-r--r--src/libstd/sync/mpsc/mpsc_queue.rs2
-rw-r--r--src/libstd/sync/mpsc/oneshot.rs2
-rw-r--r--src/libstd/sync/mpsc/select.rs6
-rw-r--r--src/libstd/sync/mpsc/spsc_queue.rs2
-rw-r--r--src/libstd/sync/mutex.rs2
-rw-r--r--src/libstd/sync/once.rs16
-rw-r--r--src/libstd/sync/rwlock.rs10
-rw-r--r--src/libstd/sys/common/args.rs99
-rw-r--r--src/libstd/sys/common/io.rs2
-rw-r--r--src/libstd/sys/common/memchr.rs230
-rw-r--r--src/libstd/sys/common/mod.rs4
-rw-r--r--src/libstd/sys/common/net.rs25
-rw-r--r--src/libstd/sys/common/poison.rs5
-rw-r--r--src/libstd/sys/common/remutex.rs2
-rw-r--r--src/libstd/sys/common/wtf8.rs21
-rw-r--r--src/libstd/sys/unix/android.rs63
-rw-r--r--src/libstd/sys/unix/args.rs212
-rw-r--r--src/libstd/sys/unix/env.rs184
-rw-r--r--src/libstd/sys/unix/ext/fs.rs45
-rw-r--r--src/libstd/sys/unix/ext/mod.rs2
-rw-r--r--src/libstd/sys/unix/ext/net.rs15
-rw-r--r--src/libstd/sys/unix/ext/process.rs6
-rw-r--r--src/libstd/sys/unix/fd.rs68
-rw-r--r--src/libstd/sys/unix/fs.rs33
-rw-r--r--src/libstd/sys/unix/memchr.rs57
-rw-r--r--src/libstd/sys/unix/mod.rs12
-rw-r--r--src/libstd/sys/unix/net.rs23
-rw-r--r--src/libstd/sys/unix/os.rs172
-rw-r--r--src/libstd/sys/unix/path.rs29
-rw-r--r--src/libstd/sys/unix/process.rs4
-rw-r--r--src/libstd/sys/unix/rand.rs60
-rw-r--r--src/libstd/sys/unix/stdio.rs2
-rw-r--r--src/libstd/sys/unix/thread.rs56
-rw-r--r--src/libstd/sys/windows/args.rs76
-rw-r--r--src/libstd/sys/windows/env.rs19
-rw-r--r--src/libstd/sys/windows/ext/fs.rs51
-rw-r--r--src/libstd/sys/windows/ext/mod.rs2
-rw-r--r--src/libstd/sys/windows/ext/process.rs10
-rw-r--r--src/libstd/sys/windows/fs.rs16
-rw-r--r--src/libstd/sys/windows/handle.rs30
-rw-r--r--src/libstd/sys/windows/memchr.rs15
-rw-r--r--src/libstd/sys/windows/mod.rs4
-rw-r--r--src/libstd/sys/windows/os.rs56
-rw-r--r--src/libstd/sys/windows/path.rs108
-rw-r--r--src/libstd/sys/windows/stdio.rs2
-rw-r--r--src/libstd/thread/local.rs74
-rw-r--r--src/libstd/thread/mod.rs63
-rw-r--r--src/libstd/time/duration.rs4
-rw-r--r--src/libstd/time/mod.rs2
95 files changed, 3703 insertions, 1730 deletions
diff --git a/src/libstd/build.rs b/src/libstd/build.rs
index 2d540c6b59a..72cd6e4830b 100644
--- a/src/libstd/build.rs
+++ b/src/libstd/build.rs
@@ -23,10 +23,10 @@ fn main() {
     println!("cargo:rustc-cfg=cargobuild");
     println!("cargo:rerun-if-changed=build.rs");
 
-    let target = env::var("TARGET").unwrap();
-    let host = env::var("HOST").unwrap();
+    let target = env::var("TARGET").expect("TARGET was not set");
+    let host = env::var("HOST").expect("HOST was not set");
     if cfg!(feature = "backtrace") && !target.contains("apple") && !target.contains("msvc") &&
-        !target.contains("emscripten") {
+        !target.contains("emscripten") && !target.contains("fuchsia") {
         build_libbacktrace(&host, &target);
     }
 
@@ -58,6 +58,8 @@ fn main() {
         println!("cargo:rustc-link-lib=ws2_32");
         println!("cargo:rustc-link-lib=userenv");
         println!("cargo:rustc-link-lib=shell32");
+    } else if target.contains("fuchsia") {
+        println!("cargo:rustc-link-lib=magenta");
     }
 }
 
@@ -103,5 +105,5 @@ fn build_libbacktrace(host: &str, target: &str) {
     run(Command::new("make")
                 .current_dir(&build_dir)
                 .arg(format!("INCDIR={}", src_dir.display()))
-                .arg("-j").arg(env::var("NUM_JOBS").unwrap()));
+                .arg("-j").arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set")));
 }
diff --git a/src/libstd/collections/hash/bench.rs b/src/libstd/collections/hash/bench.rs
index a1275d23d57..ff6cb7985a4 100644
--- a/src/libstd/collections/hash/bench.rs
+++ b/src/libstd/collections/hash/bench.rs
@@ -15,17 +15,17 @@ extern crate test;
 use self::test::Bencher;
 
 #[bench]
-fn new_drop(b : &mut Bencher) {
+fn new_drop(b: &mut Bencher) {
     use super::map::HashMap;
 
     b.iter(|| {
-        let m : HashMap<i32, i32> = HashMap::new();
+        let m: HashMap<i32, i32> = HashMap::new();
         assert_eq!(m.len(), 0);
     })
 }
 
 #[bench]
-fn new_insert_drop(b : &mut Bencher) {
+fn new_insert_drop(b: &mut Bencher) {
     use super::map::HashMap;
 
     b.iter(|| {
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index eb1653f18cb..fb8a0c3c265 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -14,33 +14,19 @@ use self::VacantEntryState::*;
 use borrow::Borrow;
 use cmp::max;
 use fmt::{self, Debug};
+#[allow(deprecated)]
 use hash::{Hash, Hasher, BuildHasher, SipHasher13};
 use iter::{FromIterator, FusedIterator};
 use mem::{self, replace};
 use ops::{Deref, Index};
 use rand::{self, Rng};
 
-use super::table::{
-    self,
-    Bucket,
-    EmptyBucket,
-    FullBucket,
-    FullBucketMut,
-    RawTable,
-    SafeHash
-};
-use super::table::BucketState::{
-    Empty,
-    Full,
-};
-
-const INITIAL_LOG2_CAP: usize = 5;
-const INITIAL_CAPACITY: usize = 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 condition:
-///
-/// - if size > 0.909 * capacity: grow the map
+use super::table::{self, Bucket, EmptyBucket, FullBucket, FullBucketMut, RawTable, SafeHash};
+use super::table::BucketState::{Empty, Full};
+
+const MIN_NONZERO_RAW_CAPACITY: usize = 32;     // must be a power of two
+
+/// The default behavior of HashMap implements a maximum load factor of 90.9%.
 #[derive(Clone)]
 struct DefaultResizePolicy;
 
@@ -49,40 +35,35 @@ impl DefaultResizePolicy {
         DefaultResizePolicy
     }
 
+    /// A hash map's "capacity" is the number of elements it can hold without
+    /// being resized. Its "raw capacity" is the number of slots required to
+    /// provide that capacity, accounting for maximum loading. The raw capacity
+    /// is always zero or a power of two.
     #[inline]
-    fn min_capacity(&self, usable_size: usize) -> usize {
-        // Here, we are rephrasing the logic by specifying the lower limit
-        // on capacity:
-        //
-        // - if `cap < size * 1.1`: grow the map
-        usable_size * 11 / 10
+    fn raw_capacity(&self, len: usize) -> usize {
+        if len == 0 {
+            0
+        } else {
+            // 1. Account for loading: `raw_capacity >= len * 1.1`.
+            // 2. Ensure it is a power of two.
+            // 3. Ensure it is at least the minimum size.
+            let mut raw_cap = len * 11 / 10;
+            assert!(raw_cap >= len, "raw_cap overflow");
+            raw_cap = raw_cap.checked_next_power_of_two().expect("raw_capacity overflow");
+            raw_cap = max(MIN_NONZERO_RAW_CAPACITY, raw_cap);
+            raw_cap
+        }
     }
 
-    /// An inverse of `min_capacity`, approximately.
+    /// The capacity of the given raw capacity.
     #[inline]
-    fn usable_capacity(&self, cap: usize) -> usize {
-        // 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 left-hand side can only be smaller due to flooring by integer
-        // division.
-        //
+    fn capacity(&self, raw_cap: usize) -> usize {
         // This doesn't have to be checked for overflow since allocation size
         // in bytes will overflow earlier than multiplication by 10.
         //
         // As per https://github.com/rust-lang/rust/pull/30991 this is updated
-        // to be: (cap * den + den - 1) / num
-        (cap * 10 + 10 - 1) / 11
-    }
-}
-
-#[test]
-fn test_resize_policy() {
-    let rp = DefaultResizePolicy;
-    for n in 0..1000 {
-        assert!(rp.min_capacity(rp.usable_capacity(n)) <= n);
-        assert!(rp.usable_capacity(rp.min_capacity(n)) <= n);
+        // to be: (raw_cap * den + den - 1) / num
+        (raw_cap * 10 + 10 - 1) / 11
     }
 }
 
@@ -196,15 +177,29 @@ fn test_resize_policy() {
 //
 // FIXME(Gankro, pczarn): review the proof and put it all in a separate README.md
 
-/// A hash map implementation which uses linear probing with Robin
-/// Hood bucket stealing.
+/// A hash map implementation which uses linear probing with Robin Hood bucket
+/// stealing.
 ///
-/// By default, HashMap uses a somewhat slow hashing algorithm which can provide resistance
-/// to DoS attacks. Rust makes a best attempt at acquiring random numbers without IO
-/// blocking from your system. Because of this HashMap is not guaranteed to provide
-/// DoS resistance since the numbers generated might not be truly random. If you do
-/// require this behavior you can create your own hashing function using
-/// [BuildHasherDefault](../hash/struct.BuildHasherDefault.html).
+/// By default, `HashMap` uses a hashing algorithm selected to provide
+/// resistance against HashDoS attacks. The algorithm is randomly seeded, and a
+/// reasonable best-effort is made to generate this seed from a high quality,
+/// secure source of randomness provided by the host without blocking the
+/// program. Because of this, the randomness of the seed is dependant on the
+/// quality of the system's random number generator at the time it is created.
+/// In particular, seeds generated when the system's entropy pool is abnormally
+/// low such as during system boot may be of a lower quality.
+///
+/// The default hashing algorithm is currently SipHash 1-3, though this is
+/// subject to change at any point in the future. While its performance is very
+/// competitive for medium sized keys, other hashing algorithms will outperform
+/// it for small keys such as integers as well as large keys such as long
+/// strings, though those algorithms will typically *not* protect against
+/// attacks such as HashDoS.
+///
+/// The hashing algorithm can be replaced on a per-`HashMap` basis using the
+/// `HashMap::default`, `HashMap::with_hasher`, and
+/// `HashMap::with_capacity_and_hasher` methods. Many alternative algorithms
+/// are available on crates.io, such as the `fnv` crate.
 ///
 /// It is required that the keys implement the [`Eq`] and [`Hash`] traits, although
 /// this can frequently be achieved by using `#[derive(PartialEq, Eq, Hash)]`.
@@ -335,6 +330,22 @@ fn test_resize_policy() {
 ///     println!("{:?} has {} hp", viking, health);
 /// }
 /// ```
+///
+/// A HashMap with fixed list of elements can be initialized from an array:
+///
+/// ```
+/// use std::collections::HashMap;
+///
+/// fn main() {
+///     let timber_resources: HashMap<&str, i32> =
+///     [("Norway", 100),
+///      ("Denmark", 50),
+///      ("Iceland", 10)]
+///      .iter().cloned().collect();
+///     // use the values stored in map
+/// }
+/// ```
+
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct HashMap<K, V, S = RandomState> {
@@ -348,12 +359,9 @@ pub struct HashMap<K, V, S = RandomState> {
 
 /// Search for a pre-hashed key.
 #[inline]
-fn search_hashed<K, V, M, F>(table: M,
-                             hash: SafeHash,
-                             mut is_match: F)
-                             -> InternalEntry<K, V, M> where
-    M: Deref<Target=RawTable<K, V>>,
-    F: FnMut(&K) -> bool,
+fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> InternalEntry<K, V, M>
+    where M: Deref<Target = RawTable<K, V>>,
+          F: FnMut(&K) -> bool
 {
     // This is the only function where capacity can be zero. To avoid
     // undefined behavior when Bucket::new gets the raw bucket in this
@@ -375,7 +383,7 @@ fn search_hashed<K, V, M, F>(table: M,
                     elem: NoElem(bucket),
                 };
             }
-            Full(bucket) => bucket
+            Full(bucket) => bucket,
         };
 
         let robin_ib = full.index() as isize - full.displacement() as isize;
@@ -394,9 +402,7 @@ fn search_hashed<K, V, M, F>(table: M,
         if hash == full.hash() {
             // If the key doesn't match, it can't be this one..
             if is_match(full.read().0) {
-                return InternalEntry::Occupied {
-                    elem: full
-                };
+                return InternalEntry::Occupied { elem: full };
             }
         }
 
@@ -409,13 +415,13 @@ fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>) -> (K, V) {
     let (empty, retkey, retval) = starting_bucket.take();
     let mut gap = match empty.gap_peek() {
         Some(b) => b,
-        None => return (retkey, retval)
+        None => return (retkey, retval),
     };
 
     while gap.full().displacement() != 0 {
         gap = match gap.shift() {
             Some(b) => b,
-            None => break
+            None => break,
         };
     }
 
@@ -429,11 +435,11 @@ fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>) -> (K, V) {
 ///
 /// `hash`, `k`, and `v` are the elements to "robin hood" into the hashtable.
 fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
-                        mut ib: usize,
-                        mut hash: SafeHash,
-                        mut key: K,
-                        mut val: V)
-                        -> &'a mut V {
+                                mut ib: usize,
+                                mut hash: SafeHash,
+                                mut key: K,
+                                mut val: V)
+                                -> &'a mut V {
     let starting_index = bucket.index();
     let size = bucket.table().size();
     // Save the *starting point*.
@@ -465,8 +471,8 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
                     // FullBucketMut, into just one FullBucketMut. The "table"
                     // refers to the inner FullBucketMut in this context.
                     return bucket.into_table().into_mut_refs().1;
-                },
-                Full(bucket) => bucket
+                }
+                Full(bucket) => bucket,
             };
 
             let probe_ib = full_bucket.index() - full_bucket.displacement();
@@ -483,9 +489,12 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
 }
 
 impl<K, V, S> HashMap<K, V, S>
-    where K: Eq + Hash, S: BuildHasher
+    where K: Eq + Hash,
+          S: BuildHasher
 {
-    fn make_hash<X: ?Sized>(&self, x: &X) -> SafeHash where X: Hash {
+    fn make_hash<X: ?Sized>(&self, x: &X) -> SafeHash
+        where X: Hash
+    {
         table::make_hash(&self.hash_builder, x)
     }
 
@@ -494,7 +503,8 @@ impl<K, V, S> HashMap<K, V, S>
     /// search_hashed.
     #[inline]
     fn search<'a, Q: ?Sized>(&'a self, q: &Q) -> InternalEntry<K, V, &'a RawTable<K, V>>
-        where K: Borrow<Q>, Q: Eq + Hash
+        where K: Borrow<Q>,
+              Q: Eq + Hash
     {
         let hash = self.make_hash(q);
         search_hashed(&self.table, hash, |k| q.eq(k.borrow()))
@@ -502,7 +512,8 @@ impl<K, V, S> HashMap<K, V, S>
 
     #[inline]
     fn search_mut<'a, Q: ?Sized>(&'a mut self, q: &Q) -> InternalEntry<K, V, &'a mut RawTable<K, V>>
-        where K: Borrow<Q>, Q: Eq + Hash
+        where K: Borrow<Q>,
+              Q: Eq + Hash
     {
         let hash = self.make_hash(q);
         search_hashed(&mut self.table, hash, |k| q.eq(k.borrow()))
@@ -510,11 +521,11 @@ impl<K, V, S> HashMap<K, V, S>
 
     // 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 raw_cap = self.raw_capacity();
         let mut buckets = Bucket::new(&mut self.table, hash);
         let ib = buckets.index();
 
-        while buckets.index() != ib + cap {
+        while buckets.index() != ib + raw_cap {
             // We don't need to compare hashes for value swap.
             // Not even DIBs for Robin Hood.
             buckets = match buckets.peek() {
@@ -522,7 +533,7 @@ impl<K, V, S> HashMap<K, V, S>
                     empty.put(hash, k, v);
                     return;
                 }
-                Full(b) => b.into_bucket()
+                Full(b) => b.into_bucket(),
             };
             buckets.next();
         }
@@ -545,7 +556,10 @@ impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
         Default::default()
     }
 
-    /// Creates an empty `HashMap` with the given initial capacity.
+    /// Creates an empty `HashMap` with the specified capacity.
+    ///
+    /// The hash map will be able to hold at least `capacity` elements without
+    /// reallocating. If `capacity` is 0, the hash map will not allocate.
     ///
     /// # Examples
     ///
@@ -561,7 +575,8 @@ impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
 }
 
 impl<K, V, S> HashMap<K, V, S>
-    where K: Eq + Hash, S: BuildHasher
+    where K: Eq + Hash,
+          S: BuildHasher
 {
     /// Creates an empty `HashMap` which will use the given hash builder to hash
     /// keys.
@@ -593,9 +608,11 @@ impl<K, V, S> HashMap<K, V, S>
         }
     }
 
-    /// Creates an empty `HashMap` with space for at least `capacity`
-    /// elements, using `hasher` to hash the keys.
+    /// Creates an empty `HashMap` with the specified capacity, using `hasher`
+    /// to hash the keys.
     ///
+    /// The hash map will be able to hold at least `capacity` elements without
+    /// reallocating. If `capacity` is 0, the hash map will not allocate.
     /// Warning: `hasher` is normally randomly generated, and
     /// is designed to allow HashMaps to be resistant to attacks that
     /// cause many collisions and very poor performance. Setting it
@@ -613,16 +630,13 @@ impl<K, V, S> HashMap<K, V, S>
     /// ```
     #[inline]
     #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
-    pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S)
-                                    -> HashMap<K, V, S> {
+    pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> HashMap<K, V, S> {
         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");
+        let raw_cap = resize_policy.raw_capacity(capacity);
         HashMap {
             hash_builder: hash_builder,
             resize_policy: resize_policy,
-            table: RawTable::new(internal_cap),
+            table: RawTable::new(raw_cap),
         }
     }
 
@@ -647,7 +661,13 @@ impl<K, V, S> HashMap<K, V, S>
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn capacity(&self) -> usize {
-        self.resize_policy.usable_capacity(self.table.capacity())
+        self.resize_policy.capacity(self.raw_capacity())
+    }
+
+    /// Returns the hash map's raw capacity.
+    #[inline]
+    fn raw_capacity(&self) -> usize {
+        self.table.capacity()
     }
 
     /// Reserves capacity for at least `additional` more elements to be inserted
@@ -667,28 +687,24 @@ impl<K, V, S> HashMap<K, V, S>
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve(&mut self, additional: usize) {
-        let new_size = self.len().checked_add(additional).expect("capacity overflow");
-        let min_cap = self.resize_policy.min_capacity(new_size);
-
-        // 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() < min_cap {
-            let new_capacity = max(min_cap.next_power_of_two(), INITIAL_CAPACITY);
-            self.resize(new_capacity);
+        let remaining = self.capacity() - self.len(); // this can't overflow
+        if remaining < additional {
+            let min_cap = self.len().checked_add(additional).expect("reserve overflow");
+            let raw_cap = self.resize_policy.raw_capacity(min_cap);
+            self.resize(raw_cap);
         }
     }
 
-    /// 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
+    /// Resizes the internal vectors to a new capacity. It's your
+    /// responsibility to:
+    ///   1) Ensure `new_raw_cap` is enough for all the elements, accounting
     ///      for the load factor.
-    ///   2) Ensure `new_capacity` is a power of two or zero.
-    fn resize(&mut self, new_capacity: usize) {
-        assert!(self.table.size() <= new_capacity);
-        assert!(new_capacity.is_power_of_two() || new_capacity == 0);
+    ///   2) Ensure `new_raw_cap` is a power of two or zero.
+    fn resize(&mut self, new_raw_cap: usize) {
+        assert!(self.table.size() <= new_raw_cap);
+        assert!(new_raw_cap.is_power_of_two() || new_raw_cap == 0);
 
-        let mut old_table = replace(&mut self.table, RawTable::new(new_capacity));
+        let mut old_table = replace(&mut self.table, RawTable::new(new_raw_cap));
         let old_size = old_table.size();
 
         if old_table.capacity() == 0 || old_table.size() == 0 {
@@ -752,7 +768,7 @@ impl<K, V, S> HashMap<K, V, S>
                     }
                     b.into_bucket()
                 }
-                Empty(b) => b.into_bucket()
+                Empty(b) => b.into_bucket(),
             };
             bucket.next();
         }
@@ -778,14 +794,9 @@ impl<K, V, S> HashMap<K, V, S>
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     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!(self.len() <= min_capacity);
-
-        if self.table.capacity() != min_capacity {
-            let old_table = replace(&mut self.table, RawTable::new(min_capacity));
+        let new_raw_cap = self.resize_policy.raw_capacity(self.len());
+        if self.raw_capacity() != new_raw_cap {
+            let old_table = replace(&mut self.table, RawTable::new(new_raw_cap));
             let old_size = old_table.size();
 
             // Shrink the table. Naive algorithm for resizing:
@@ -806,16 +817,12 @@ impl<K, V, S> HashMap<K, V, S>
     fn insert_hashed_nocheck(&mut self, hash: SafeHash, k: K, v: V) -> Option<V> {
         let entry = search_hashed(&mut self.table, hash, |key| *key == k).into_entry(k);
         match entry {
-            Some(Occupied(mut elem)) => {
-                Some(elem.insert(v))
-            }
+            Some(Occupied(mut elem)) => Some(elem.insert(v)),
             Some(Vacant(elem)) => {
                 elem.insert(v);
                 None
             }
-            None => {
-                unreachable!()
-            }
+            None => unreachable!(),
         }
     }
 
@@ -979,7 +986,9 @@ impl<K, V, S> HashMap<K, V, S>
     /// assert_eq!(a.len(), 1);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn len(&self) -> usize { self.table.size() }
+    pub fn len(&self) -> usize {
+        self.table.size()
+    }
 
     /// Returns true if the map contains no elements.
     ///
@@ -995,7 +1004,9 @@ impl<K, V, S> HashMap<K, V, S>
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn is_empty(&self) -> bool { self.len() == 0 }
+    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.
@@ -1019,9 +1030,7 @@ impl<K, V, S> HashMap<K, V, S>
     #[inline]
     #[stable(feature = "drain", since = "1.6.0")]
     pub fn drain(&mut self) -> Drain<K, V> {
-        Drain {
-            inner: self.table.drain(),
-        }
+        Drain { inner: self.table.drain() }
     }
 
     /// Clears the map, removing all key-value pairs. Keeps the allocated memory
@@ -1064,7 +1073,8 @@ impl<K, V, S> HashMap<K, V, S>
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
-        where K: Borrow<Q>, Q: Hash + Eq
+        where K: Borrow<Q>,
+              Q: Hash + Eq
     {
         self.search(k).into_occupied_bucket().map(|bucket| bucket.into_refs().1)
     }
@@ -1090,7 +1100,8 @@ impl<K, V, S> HashMap<K, V, S>
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
-        where K: Borrow<Q>, Q: Hash + Eq
+        where K: Borrow<Q>,
+              Q: Hash + Eq
     {
         self.search(k).into_occupied_bucket().is_some()
     }
@@ -1118,7 +1129,8 @@ impl<K, V, S> HashMap<K, V, S>
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
-        where K: Borrow<Q>, Q: Hash + Eq
+        where K: Borrow<Q>,
+              Q: Hash + Eq
     {
         self.search_mut(k).into_occupied_bucket().map(|bucket| bucket.into_mut_refs().1)
     }
@@ -1176,10 +1188,11 @@ impl<K, V, S> HashMap<K, V, S>
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
-        where K: Borrow<Q>, Q: Hash + Eq
+        where K: Borrow<Q>,
+              Q: Hash + Eq
     {
         if self.table.size() == 0 {
-            return None
+            return None;
         }
 
         self.search_mut(k).into_occupied_bucket().map(|bucket| pop_internal(bucket).1)
@@ -1188,25 +1201,32 @@ impl<K, V, S> HashMap<K, V, S>
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> PartialEq for HashMap<K, V, S>
-    where K: Eq + Hash, V: PartialEq, S: BuildHasher
+    where K: Eq + Hash,
+          V: PartialEq,
+          S: BuildHasher
 {
     fn eq(&self, other: &HashMap<K, V, S>) -> bool {
-        if self.len() != other.len() { return false; }
+        if self.len() != other.len() {
+            return false;
+        }
 
-        self.iter().all(|(key, value)|
-            other.get(key).map_or(false, |v| *value == *v)
-        )
+        self.iter().all(|(key, value)| other.get(key).map_or(false, |v| *value == *v))
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> Eq for HashMap<K, V, S>
-    where K: Eq + Hash, V: Eq, S: BuildHasher
-{}
+    where K: Eq + Hash,
+          V: Eq,
+          S: BuildHasher
+{
+}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> Debug for HashMap<K, V, S>
-    where K: Eq + Hash + Debug, V: Debug, S: BuildHasher
+    where K: Eq + Hash + Debug,
+          V: Debug,
+          S: BuildHasher
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_map().entries(self.iter()).finish()
@@ -1216,7 +1236,7 @@ impl<K, V, S> Debug for HashMap<K, V, S>
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> Default for HashMap<K, V, S>
     where K: Eq + Hash,
-          S: BuildHasher + Default,
+          S: BuildHasher + Default
 {
     /// Creates an empty `HashMap<K, V, S>`, with the `Default` value for the hasher.
     fn default() -> HashMap<K, V, S> {
@@ -1228,7 +1248,7 @@ impl<K, V, S> Default for HashMap<K, V, S>
 impl<'a, K, Q: ?Sized, V, S> Index<&'a Q> for HashMap<K, V, S>
     where K: Eq + Hash + Borrow<Q>,
           Q: Eq + Hash,
-          S: BuildHasher,
+          S: BuildHasher
 {
     type Output = V;
 
@@ -1241,79 +1261,71 @@ impl<'a, K, Q: ?Sized, V, S> Index<&'a Q> for HashMap<K, V, S>
 /// HashMap iterator.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, K: 'a, V: 'a> {
-    inner: table::Iter<'a, K, V>
+    inner: table::Iter<'a, K, V>,
 }
 
 // FIXME(#19839) Remove in favor of `#[derive(Clone)]`
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> Clone for Iter<'a, K, V> {
     fn clone(&self) -> Iter<'a, K, V> {
-        Iter {
-            inner: self.inner.clone()
-        }
+        Iter { inner: self.inner.clone() }
     }
 }
 
 /// HashMap mutable values iterator.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, K: 'a, V: 'a> {
-    inner: table::IterMut<'a, K, V>
+    inner: table::IterMut<'a, K, V>,
 }
 
 /// HashMap move iterator.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<K, V> {
-    inner: table::IntoIter<K, V>
+    inner: table::IntoIter<K, V>,
 }
 
 /// HashMap keys iterator.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Keys<'a, K: 'a, V: 'a> {
-    inner: Iter<'a, K, V>
+    inner: Iter<'a, K, V>,
 }
 
 // FIXME(#19839) Remove in favor of `#[derive(Clone)]`
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> Clone for Keys<'a, K, V> {
     fn clone(&self) -> Keys<'a, K, V> {
-        Keys {
-            inner: self.inner.clone()
-        }
+        Keys { inner: self.inner.clone() }
     }
 }
 
 /// HashMap values iterator.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Values<'a, K: 'a, V: 'a> {
-    inner: Iter<'a, K, V>
+    inner: Iter<'a, K, V>,
 }
 
 // FIXME(#19839) Remove in favor of `#[derive(Clone)]`
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> Clone for Values<'a, K, V> {
     fn clone(&self) -> Values<'a, K, V> {
-        Values {
-            inner: self.inner.clone()
-        }
+        Values { inner: self.inner.clone() }
     }
 }
 
 /// HashMap drain iterator.
 #[stable(feature = "drain", since = "1.6.0")]
 pub struct Drain<'a, K: 'a, V: 'a> {
-    inner: table::Drain<'a, K, V>
+    inner: table::Drain<'a, K, V>,
 }
 
 /// Mutable HashMap values iterator.
 #[stable(feature = "map_values_mut", since = "1.10.0")]
 pub struct ValuesMut<'a, K: 'a, V: 'a> {
-    inner: IterMut<'a, K, V>
+    inner: IterMut<'a, K, V>,
 }
 
 enum InternalEntry<K, V, M> {
-    Occupied {
-        elem: FullBucket<K, V, M>,
-    },
+    Occupied { elem: FullBucket<K, V, M> },
     Vacant {
         hash: SafeHash,
         elem: VacantEntryState<K, V, M>,
@@ -1338,7 +1350,7 @@ impl<'a, K, V> InternalEntry<K, V, &'a mut RawTable<K, V>> {
             InternalEntry::Occupied { elem } => {
                 Some(Occupied(OccupiedEntry {
                     key: Some(key),
-                    elem: elem
+                    elem: elem,
                 }))
             }
             InternalEntry::Vacant { hash, elem } => {
@@ -1348,7 +1360,7 @@ impl<'a, K, V> InternalEntry<K, V, &'a mut RawTable<K, V>> {
                     elem: elem,
                 }))
             }
-            InternalEntry::TableIsEmpty => None
+            InternalEntry::TableIsEmpty => None,
         }
     }
 }
@@ -1362,27 +1374,29 @@ impl<'a, K, V> InternalEntry<K, V, &'a mut RawTable<K, V>> {
 pub enum Entry<'a, K: 'a, V: 'a> {
     /// An occupied Entry.
     #[stable(feature = "rust1", since = "1.0.0")]
-    Occupied(
-        #[stable(feature = "rust1", since = "1.0.0")] OccupiedEntry<'a, K, V>
-    ),
+    Occupied(#[stable(feature = "rust1", since = "1.0.0")]
+             OccupiedEntry<'a, K, V>),
 
     /// A vacant Entry.
     #[stable(feature = "rust1", since = "1.0.0")]
-    Vacant(
-        #[stable(feature = "rust1", since = "1.0.0")] VacantEntry<'a, K, V>
-    ),
+    Vacant(#[stable(feature = "rust1", since = "1.0.0")]
+           VacantEntry<'a, K, V>),
 }
 
 #[stable(feature= "debug_hash_map", since = "1.12.0")]
 impl<'a, K: 'a + Debug, V: 'a + Debug> Debug for Entry<'a, K, V> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            Vacant(ref v) => f.debug_tuple("Entry")
-                              .field(v)
-                              .finish(),
-            Occupied(ref o) => f.debug_tuple("Entry")
-                                .field(o)
-                                .finish(),
+            Vacant(ref v) => {
+                f.debug_tuple("Entry")
+                    .field(v)
+                    .finish()
+            }
+            Occupied(ref o) => {
+                f.debug_tuple("Entry")
+                    .field(o)
+                    .finish()
+            }
         }
     }
 }
@@ -1401,9 +1415,9 @@ pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
 impl<'a, K: 'a + Debug, V: 'a + Debug> Debug for OccupiedEntry<'a, K, V> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_struct("OccupiedEntry")
-         .field("key", self.key())
-         .field("value", self.get())
-         .finish()
+            .field("key", self.key())
+            .field("value", self.get())
+            .finish()
     }
 }
 
@@ -1422,8 +1436,8 @@ pub struct VacantEntry<'a, K: 'a, V: 'a> {
 impl<'a, K: 'a + Debug, V: 'a> Debug for VacantEntry<'a, K, V> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_tuple("VacantEntry")
-         .field(self.key())
-         .finish()
+            .field(self.key())
+            .finish()
     }
 }
 
@@ -1438,7 +1452,8 @@ enum VacantEntryState<K, V, M> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S>
-    where K: Eq + Hash, S: BuildHasher
+    where K: Eq + Hash,
+          S: BuildHasher
 {
     type Item = (&'a K, &'a V);
     type IntoIter = Iter<'a, K, V>;
@@ -1450,7 +1465,8 @@ impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S>
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V, S> IntoIterator for &'a mut HashMap<K, V, S>
-    where K: Eq + Hash, S: BuildHasher
+    where K: Eq + Hash,
+          S: BuildHasher
 {
     type Item = (&'a K, &'a mut V);
     type IntoIter = IterMut<'a, K, V>;
@@ -1462,7 +1478,8 @@ impl<'a, K, V, S> IntoIterator for &'a mut HashMap<K, V, S>
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> IntoIterator for HashMap<K, V, S>
-    where K: Eq + Hash, S: BuildHasher
+    where K: Eq + Hash,
+          S: BuildHasher
 {
     type Item = (K, V);
     type IntoIter = IntoIter<K, V>;
@@ -1485,9 +1502,7 @@ impl<K, V, S> IntoIterator for HashMap<K, V, S>
     /// let vec: Vec<(&str, isize)> = map.into_iter().collect();
     /// ```
     fn into_iter(self) -> IntoIter<K, V> {
-        IntoIter {
-            inner: self.table.into_iter()
-        }
+        IntoIter { inner: self.table.into_iter() }
     }
 }
 
@@ -1495,12 +1510,21 @@ impl<K, V, S> IntoIterator for HashMap<K, V, S>
 impl<'a, K, V> Iterator for Iter<'a, K, V> {
     type Item = (&'a K, &'a V);
 
-    #[inline] fn next(&mut self) -> Option<(&'a K, &'a V)> { self.inner.next() }
-    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+    #[inline]
+    fn next(&mut self) -> Option<(&'a K, &'a V)> {
+        self.inner.next()
+    }
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.inner.size_hint()
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
-    #[inline] fn len(&self) -> usize { self.inner.len() }
+    #[inline]
+    fn len(&self) -> usize {
+        self.inner.len()
+    }
 }
 
 #[unstable(feature = "fused", issue = "35602")]
@@ -1510,12 +1534,21 @@ impl<'a, K, V> FusedIterator for Iter<'a, K, V> {}
 impl<'a, K, V> Iterator for IterMut<'a, K, V> {
     type Item = (&'a K, &'a mut V);
 
-    #[inline] fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.inner.next() }
-    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+    #[inline]
+    fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
+        self.inner.next()
+    }
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.inner.size_hint()
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
-    #[inline] fn len(&self) -> usize { self.inner.len() }
+    #[inline]
+    fn len(&self) -> usize {
+        self.inner.len()
+    }
 }
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {}
@@ -1524,12 +1557,21 @@ impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {}
 impl<K, V> Iterator for IntoIter<K, V> {
     type Item = (K, V);
 
-    #[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next().map(|(_, k, v)| (k, v)) }
-    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+    #[inline]
+    fn next(&mut self) -> Option<(K, V)> {
+        self.inner.next().map(|(_, k, v)| (k, v))
+    }
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.inner.size_hint()
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V> ExactSizeIterator for IntoIter<K, V> {
-    #[inline] fn len(&self) -> usize { self.inner.len() }
+    #[inline]
+    fn len(&self) -> usize {
+        self.inner.len()
+    }
 }
 #[unstable(feature = "fused", issue = "35602")]
 impl<K, V> FusedIterator for IntoIter<K, V> {}
@@ -1538,12 +1580,21 @@ impl<K, V> FusedIterator for IntoIter<K, V> {}
 impl<'a, K, V> Iterator for Keys<'a, K, V> {
     type Item = &'a K;
 
-    #[inline] fn next(&mut self) -> Option<(&'a K)> { self.inner.next().map(|(k, _)| k) }
-    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+    #[inline]
+    fn next(&mut self) -> Option<(&'a K)> {
+        self.inner.next().map(|(k, _)| k)
+    }
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.inner.size_hint()
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> {
-    #[inline] fn len(&self) -> usize { self.inner.len() }
+    #[inline]
+    fn len(&self) -> usize {
+        self.inner.len()
+    }
 }
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, K, V> FusedIterator for Keys<'a, K, V> {}
@@ -1552,12 +1603,21 @@ impl<'a, K, V> FusedIterator for Keys<'a, K, V> {}
 impl<'a, K, V> Iterator for Values<'a, K, V> {
     type Item = &'a V;
 
-    #[inline] fn next(&mut self) -> Option<(&'a V)> { self.inner.next().map(|(_, v)| v) }
-    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+    #[inline]
+    fn next(&mut self) -> Option<(&'a V)> {
+        self.inner.next().map(|(_, v)| v)
+    }
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.inner.size_hint()
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {
-    #[inline] fn len(&self) -> usize { self.inner.len() }
+    #[inline]
+    fn len(&self) -> usize {
+        self.inner.len()
+    }
 }
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, K, V> FusedIterator for Values<'a, K, V> {}
@@ -1566,26 +1626,44 @@ impl<'a, K, V> FusedIterator for Values<'a, K, V> {}
 impl<'a, K, V> Iterator for ValuesMut<'a, K, V> {
     type Item = &'a mut V;
 
-    #[inline] fn next(&mut self) -> Option<(&'a mut V)> { self.inner.next().map(|(_, v)| v) }
-    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+    #[inline]
+    fn next(&mut self) -> Option<(&'a mut V)> {
+        self.inner.next().map(|(_, v)| v)
+    }
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.inner.size_hint()
+    }
 }
 #[stable(feature = "map_values_mut", since = "1.10.0")]
 impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> {
-    #[inline] fn len(&self) -> usize { self.inner.len() }
+    #[inline]
+    fn len(&self) -> usize {
+        self.inner.len()
+    }
 }
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, K, V> FusedIterator for ValuesMut<'a, K, V> {}
 
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "drain", since = "1.6.0")]
 impl<'a, K, V> Iterator for Drain<'a, K, V> {
     type Item = (K, V);
 
-    #[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next().map(|(_, k, v)| (k, v)) }
-    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+    #[inline]
+    fn next(&mut self) -> Option<(K, V)> {
+        self.inner.next().map(|(_, k, v)| (k, v))
+    }
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.inner.size_hint()
+    }
 }
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "drain", since = "1.6.0")]
 impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
-    #[inline] fn len(&self) -> usize { self.inner.len() }
+    #[inline]
+    fn len(&self) -> usize {
+        self.inner.len()
+    }
 }
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, K, V> FusedIterator for Drain<'a, K, V> {}
@@ -1880,21 +1958,18 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(self, value: V) -> &'a mut V {
         match self.elem {
-            NeqElem(bucket, ib) => {
-                robin_hood(bucket, ib, self.hash, self.key, value)
-            }
-            NoElem(bucket) => {
-                bucket.put(self.hash, self.key, value).into_mut_refs().1
-            }
+            NeqElem(bucket, ib) => robin_hood(bucket, ib, self.hash, self.key, value),
+            NoElem(bucket) => bucket.put(self.hash, self.key, value).into_mut_refs().1,
         }
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> FromIterator<(K, V)> for HashMap<K, V, S>
-    where K: Eq + Hash, S: BuildHasher + Default
+    where K: Eq + Hash,
+          S: BuildHasher + Default
 {
-    fn from_iter<T: IntoIterator<Item=(K, V)>>(iter: T) -> HashMap<K, V, S> {
+    fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> HashMap<K, V, S> {
         let iterator = iter.into_iter();
         let lower = iterator.size_hint().0;
         let mut map = HashMap::with_capacity_and_hasher(lower, Default::default());
@@ -1905,9 +1980,10 @@ impl<K, V, S> FromIterator<(K, V)> for HashMap<K, V, S>
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> Extend<(K, V)> for HashMap<K, V, S>
-    where K: Eq + Hash, S: BuildHasher
+    where K: Eq + Hash,
+          S: BuildHasher
 {
-    fn extend<T: IntoIterator<Item=(K, V)>>(&mut self, iter: T) {
+    fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
         for (k, v) in iter {
             self.insert(k, v);
         }
@@ -1916,9 +1992,11 @@ impl<K, V, S> Extend<(K, V)> for HashMap<K, V, S>
 
 #[stable(feature = "hash_extend_copy", since = "1.4.0")]
 impl<'a, K, V, S> Extend<(&'a K, &'a V)> for HashMap<K, V, S>
-    where K: Eq + Hash + Copy, V: Copy, S: BuildHasher
+    where K: Eq + Hash + Copy,
+          V: Copy,
+          S: BuildHasher
 {
-    fn extend<T: IntoIterator<Item=(&'a K, &'a V)>>(&mut self, iter: T) {
+    fn extend<T: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: T) {
         self.extend(iter.into_iter().map(|(&key, &value)| (key, value)));
     }
 }
@@ -1960,7 +2038,8 @@ impl RandomState {
     /// let s = RandomState::new();
     /// ```
     #[inline]
-    #[allow(deprecated)] // rand
+    #[allow(deprecated)]
+    // rand
     #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
     pub fn new() -> RandomState {
         // Historically this function did not cache keys from the OS and instead
@@ -1987,9 +2066,7 @@ impl RandomState {
             (r.gen(), r.gen())
         });
 
-        KEYS.with(|&(k0, k1)| {
-            RandomState { k0: k0, k1: k1 }
-        })
+        KEYS.with(|&(k0, k1)| RandomState { k0: k0, k1: k1 })
     }
 }
 
@@ -1997,6 +2074,7 @@ impl RandomState {
 impl BuildHasher for RandomState {
     type Hasher = DefaultHasher;
     #[inline]
+    #[allow(deprecated)]
     fn build_hasher(&self) -> DefaultHasher {
         DefaultHasher(SipHasher13::new_with_keys(self.k0, self.k1))
     }
@@ -2009,10 +2087,32 @@ impl BuildHasher for RandomState {
 ///
 /// [`RandomState`]: struct.RandomState.html
 /// [`Hasher`]: ../../hash/trait.Hasher.html
-#[unstable(feature = "hashmap_default_hasher", issue = "0")]
+#[stable(feature = "hashmap_default_hasher", since = "1.13.0")]
+#[allow(deprecated)]
+#[derive(Debug)]
 pub struct DefaultHasher(SipHasher13);
 
-#[unstable(feature = "hashmap_default_hasher", issue = "0")]
+impl DefaultHasher {
+    /// Creates a new `DefaultHasher`.
+    ///
+    /// This hasher is not guaranteed to be the same as all other
+    /// `DefaultHasher` instances, but is the same as all other `DefaultHasher`
+    /// instances created through `new` or `default`.
+    #[stable(feature = "hashmap_default_hasher", since = "1.13.0")]
+    #[allow(deprecated)]
+    pub fn new() -> DefaultHasher {
+        DefaultHasher(SipHasher13::new_with_keys(0, 0))
+    }
+}
+
+#[stable(feature = "hashmap_default_hasher", since = "1.13.0")]
+impl Default for DefaultHasher {
+    fn default() -> DefaultHasher {
+        DefaultHasher::new()
+    }
+}
+
+#[stable(feature = "hashmap_default_hasher", since = "1.13.0")]
 impl Hasher for DefaultHasher {
     #[inline]
     fn write(&mut self, msg: &[u8]) {
@@ -2025,7 +2125,7 @@ impl Hasher for DefaultHasher {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
 impl Default for RandomState {
     /// Constructs a new `RandomState`.
     #[inline]
@@ -2035,7 +2135,9 @@ impl Default for RandomState {
 }
 
 impl<K, S, Q: ?Sized> super::Recover<Q> for HashMap<K, (), S>
-    where K: Eq + Hash + Borrow<Q>, S: BuildHasher, Q: Eq + Hash
+    where K: Eq + Hash + Borrow<Q>,
+          S: BuildHasher,
+          Q: Eq + Hash
 {
     type Key = K;
 
@@ -2045,7 +2147,7 @@ impl<K, S, Q: ?Sized> super::Recover<Q> for HashMap<K, (), S>
 
     fn take(&mut self, key: &Q) -> Option<K> {
         if self.table.size() == 0 {
-            return None
+            return None;
         }
 
         self.search_mut(key).into_occupied_bucket().map(|bucket| pop_internal(bucket).0)
@@ -2069,28 +2171,83 @@ impl<K, S, Q: ?Sized> super::Recover<Q> for HashMap<K, (), S>
 
 #[allow(dead_code)]
 fn assert_covariance() {
-    fn map_key<'new>(v: HashMap<&'static str, u8>) -> HashMap<&'new str, u8> { v }
-    fn map_val<'new>(v: HashMap<u8, &'static str>) -> HashMap<u8, &'new str> { v }
-    fn iter_key<'a, 'new>(v: Iter<'a, &'static str, u8>) -> Iter<'a, &'new str, u8> { v }
-    fn iter_val<'a, 'new>(v: Iter<'a, u8, &'static str>) -> Iter<'a, u8, &'new str> { v }
-    fn into_iter_key<'new>(v: IntoIter<&'static str, u8>) -> IntoIter<&'new str, u8> { v }
-    fn into_iter_val<'new>(v: IntoIter<u8, &'static str>) -> IntoIter<u8, &'new str> { v }
-    fn keys_key<'a, 'new>(v: Keys<'a, &'static str, u8>) -> Keys<'a, &'new str, u8> { v }
-    fn keys_val<'a, 'new>(v: Keys<'a, u8, &'static str>) -> Keys<'a, u8, &'new str> { v }
-    fn values_key<'a, 'new>(v: Values<'a, &'static str, u8>) -> Values<'a, &'new str, u8> { v }
-    fn values_val<'a, 'new>(v: Values<'a, u8, &'static str>) -> Values<'a, u8, &'new str> { v }
+    fn map_key<'new>(v: HashMap<&'static str, u8>) -> HashMap<&'new str, u8> {
+        v
+    }
+    fn map_val<'new>(v: HashMap<u8, &'static str>) -> HashMap<u8, &'new str> {
+        v
+    }
+    fn iter_key<'a, 'new>(v: Iter<'a, &'static str, u8>) -> Iter<'a, &'new str, u8> {
+        v
+    }
+    fn iter_val<'a, 'new>(v: Iter<'a, u8, &'static str>) -> Iter<'a, u8, &'new str> {
+        v
+    }
+    fn into_iter_key<'new>(v: IntoIter<&'static str, u8>) -> IntoIter<&'new str, u8> {
+        v
+    }
+    fn into_iter_val<'new>(v: IntoIter<u8, &'static str>) -> IntoIter<u8, &'new str> {
+        v
+    }
+    fn keys_key<'a, 'new>(v: Keys<'a, &'static str, u8>) -> Keys<'a, &'new str, u8> {
+        v
+    }
+    fn keys_val<'a, 'new>(v: Keys<'a, u8, &'static str>) -> Keys<'a, u8, &'new str> {
+        v
+    }
+    fn values_key<'a, 'new>(v: Values<'a, &'static str, u8>) -> Values<'a, &'new str, u8> {
+        v
+    }
+    fn values_val<'a, 'new>(v: Values<'a, u8, &'static str>) -> Values<'a, u8, &'new str> {
+        v
+    }
     fn drain<'new>(d: Drain<'static, &'static str, &'static str>)
-        -> Drain<'new, &'new str, &'new str> { d }
+                   -> Drain<'new, &'new str, &'new str> {
+        d
+    }
 }
 
 #[cfg(test)]
 mod test_map {
     use super::HashMap;
     use super::Entry::{Occupied, Vacant};
+    use super::RandomState;
     use cell::RefCell;
     use rand::{thread_rng, Rng};
 
     #[test]
+    fn test_zero_capacities() {
+        type HM = HashMap<i32, i32>;
+
+        let m = HM::new();
+        assert_eq!(m.capacity(), 0);
+
+        let m = HM::default();
+        assert_eq!(m.capacity(), 0);
+
+        let m = HM::with_hasher(RandomState::new());
+        assert_eq!(m.capacity(), 0);
+
+        let m = HM::with_capacity(0);
+        assert_eq!(m.capacity(), 0);
+
+        let m = HM::with_capacity_and_hasher(0, RandomState::new());
+        assert_eq!(m.capacity(), 0);
+
+        let mut m = HM::new();
+        m.insert(1, 1);
+        m.insert(2, 2);
+        m.remove(&1);
+        m.remove(&2);
+        m.shrink_to_fit();
+        assert_eq!(m.capacity(), 0);
+
+        let mut m = HM::new();
+        m.reserve(0);
+        assert_eq!(m.capacity(), 0);
+    }
+
+    #[test]
     fn test_create_capacity_zero() {
         let mut m = HashMap::with_capacity(0);
 
@@ -2130,7 +2287,7 @@ mod test_map {
 
     #[derive(Hash, PartialEq, Eq)]
     struct Dropable {
-        k: usize
+        k: usize,
     }
 
     impl Dropable {
@@ -2174,7 +2331,7 @@ mod test_map {
 
             for i in 0..100 {
                 let d1 = Dropable::new(i);
-                let d2 = Dropable::new(i+100);
+                let d2 = Dropable::new(i + 100);
                 m.insert(d1, d2);
             }
 
@@ -2233,7 +2390,7 @@ mod test_map {
 
             for i in 0..100 {
                 let d1 = Dropable::new(i);
-                let d2 = Dropable::new(i+100);
+                let d2 = Dropable::new(i + 100);
                 hm.insert(d1, d2);
             }
 
@@ -2261,13 +2418,13 @@ mod test_map {
             for _ in half.by_ref() {}
 
             DROP_VECTOR.with(|v| {
-                let nk = (0..100).filter(|&i| {
-                    v.borrow()[i] == 1
-                }).count();
+                let nk = (0..100)
+                    .filter(|&i| v.borrow()[i] == 1)
+                    .count();
 
-                let nv = (0..100).filter(|&i| {
-                    v.borrow()[i+100] == 1
-                }).count();
+                let nv = (0..100)
+                    .filter(|&i| v.borrow()[i + 100] == 1)
+                    .count();
 
                 assert_eq!(nk, 50);
                 assert_eq!(nv, 50);
@@ -2324,12 +2481,12 @@ mod test_map {
             for i in 1..1001 {
                 assert!(m.insert(i, i).is_none());
 
-                for j in 1..i+1 {
+                for j in 1..i + 1 {
                     let r = m.get(&j);
                     assert_eq!(r, Some(&j));
                 }
 
-                for j in i+1..1001 {
+                for j in i + 1..1001 {
                     let r = m.get(&j);
                     assert_eq!(r, None);
                 }
@@ -2343,11 +2500,11 @@ mod test_map {
             for i in 1..1001 {
                 assert!(m.remove(&i).is_some());
 
-                for j in 1..i+1 {
+                for j in 1..i + 1 {
                     assert!(!m.contains_key(&j));
                 }
 
-                for j in i+1..1001 {
+                for j in i + 1..1001 {
                     assert!(m.contains_key(&j));
                 }
             }
@@ -2383,7 +2540,8 @@ mod test_map {
         assert!(m.insert(5, 14).is_none());
         let new = 100;
         match m.get_mut(&5) {
-            None => panic!(), Some(x) => *x = new
+            None => panic!(),
+            Some(x) => *x = new,
         }
         assert_eq!(m.get(&5), Some(&new));
     }
@@ -2502,7 +2660,7 @@ mod test_map {
         m.insert(1, 2);
         match m.get(&1) {
             None => panic!(),
-            Some(v) => assert_eq!(*v, 2)
+            Some(v) => assert_eq!(*v, 2),
         }
     }
 
@@ -2547,8 +2705,8 @@ mod test_map {
         assert!(m.is_empty());
 
         let mut i = 0;
-        let old_cap = m.table.capacity();
-        while old_cap == m.table.capacity() {
+        let old_raw_cap = m.raw_capacity();
+        while old_raw_cap == m.raw_capacity() {
             m.insert(i, i);
             i += 1;
         }
@@ -2562,47 +2720,47 @@ mod test_map {
         let mut m = HashMap::new();
 
         assert_eq!(m.len(), 0);
-        assert_eq!(m.table.capacity(), 0);
+        assert_eq!(m.raw_capacity(), 0);
         assert!(m.is_empty());
 
         m.insert(0, 0);
         m.remove(&0);
         assert!(m.is_empty());
-        let initial_cap = m.table.capacity();
-        m.reserve(initial_cap);
-        let cap = m.table.capacity();
+        let initial_raw_cap = m.raw_capacity();
+        m.reserve(initial_raw_cap);
+        let raw_cap = m.raw_capacity();
 
-        assert_eq!(cap, initial_cap * 2);
+        assert_eq!(raw_cap, initial_raw_cap * 2);
 
         let mut i = 0;
-        for _ in 0..cap * 3 / 4 {
+        for _ in 0..raw_cap * 3 / 4 {
             m.insert(i, i);
             i += 1;
         }
         // three quarters full
 
         assert_eq!(m.len(), i);
-        assert_eq!(m.table.capacity(), cap);
+        assert_eq!(m.raw_capacity(), raw_cap);
 
-        for _ in 0..cap / 4 {
+        for _ in 0..raw_cap / 4 {
             m.insert(i, i);
             i += 1;
         }
         // half full
 
-        let new_cap = m.table.capacity();
-        assert_eq!(new_cap, cap * 2);
+        let new_raw_cap = m.raw_capacity();
+        assert_eq!(new_raw_cap, raw_cap * 2);
 
-        for _ in 0..cap / 2 - 1 {
+        for _ in 0..raw_cap / 2 - 1 {
             i -= 1;
             m.remove(&i);
-            assert_eq!(m.table.capacity(), new_cap);
+            assert_eq!(m.raw_capacity(), new_raw_cap);
         }
         // A little more than one quarter full.
         m.shrink_to_fit();
-        assert_eq!(m.table.capacity(), cap);
+        assert_eq!(m.raw_capacity(), raw_cap);
         // again, a little more than half full
-        for _ in 0..cap / 2 - 1 {
+        for _ in 0..raw_cap / 2 - 1 {
             i -= 1;
             m.remove(&i);
         }
@@ -2610,7 +2768,7 @@ mod test_map {
 
         assert_eq!(m.len(), i);
         assert!(!m.is_empty());
-        assert_eq!(m.table.capacity(), initial_cap);
+        assert_eq!(m.raw_capacity(), initial_raw_cap);
     }
 
     #[test]
@@ -2665,7 +2823,7 @@ mod test_map {
     fn test_size_hint() {
         let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
 
-        let map: HashMap<_, _>  = xs.iter().cloned().collect();
+        let map: HashMap<_, _> = xs.iter().cloned().collect();
 
         let mut iter = map.iter();
 
@@ -2678,7 +2836,7 @@ mod test_map {
     fn test_iter_len() {
         let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
 
-        let map: HashMap<_, _>  = xs.iter().cloned().collect();
+        let map: HashMap<_, _> = xs.iter().cloned().collect();
 
         let mut iter = map.iter();
 
@@ -2691,7 +2849,7 @@ mod test_map {
     fn test_mut_size_hint() {
         let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
 
-        let mut map: HashMap<_, _>  = xs.iter().cloned().collect();
+        let mut map: HashMap<_, _> = xs.iter().cloned().collect();
 
         let mut iter = map.iter_mut();
 
@@ -2704,7 +2862,7 @@ mod test_map {
     fn test_iter_mut_len() {
         let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
 
-        let mut map: HashMap<_, _>  = xs.iter().cloned().collect();
+        let mut map: HashMap<_, _> = xs.iter().cloned().collect();
 
         let mut iter = map.iter_mut();
 
@@ -2737,7 +2895,7 @@ mod test_map {
     }
 
     #[test]
-    fn test_entry(){
+    fn test_entry() {
         let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)];
 
         let mut map: HashMap<_, _> = xs.iter().cloned().collect();
@@ -2811,11 +2969,11 @@ mod test_map {
         for i in 0..1000 {
             let x = rng.gen_range(-10, 10);
             match m.entry(x) {
-                Vacant(_) => {},
+                Vacant(_) => {}
                 Occupied(e) => {
                     println!("{}: remove {}", i, x);
                     e.remove();
-                },
+                }
             }
 
             check(&m);
@@ -2893,7 +3051,7 @@ mod test_map {
             Vacant(e) => {
                 assert_eq!(key, *e.key());
                 e.insert(value.clone());
-            },
+            }
         }
         assert_eq!(a.len(), 1);
         assert_eq!(a[key], value);
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index ff56747fee6..1ec7a4a7b63 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -17,8 +17,6 @@ use ops::{BitOr, BitAnd, BitXor, Sub};
 use super::Recover;
 use super::map::{self, HashMap, Keys, RandomState};
 
-const INITIAL_CAPACITY: usize = 32;
-
 // Future Optimization (FIXME!)
 // =============================
 //
@@ -100,10 +98,24 @@ const INITIAL_CAPACITY: usize = 32;
 ///     println!("{:?}", x);
 /// }
 /// ```
+///
+/// HashSet with fixed list of elements can be initialized from an array:
+///
+/// ```
+/// use std::collections::HashSet;
+///
+/// fn main() {
+///     let viking_names: HashSet<&str> =
+///         [ "Einar", "Olaf", "Harald" ].iter().cloned().collect();
+///     // use the values stored in the set
+/// }
+/// ```
+
+
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct HashSet<T, S = RandomState> {
-    map: HashMap<T, (), S>
+    map: HashMap<T, (), S>,
 }
 
 impl<T: Hash + Eq> HashSet<T, RandomState> {
@@ -118,11 +130,13 @@ impl<T: Hash + Eq> HashSet<T, RandomState> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> HashSet<T, RandomState> {
-        HashSet::with_capacity(INITIAL_CAPACITY)
+        HashSet { map: HashMap::new() }
     }
 
-    /// Creates an empty HashSet with space for at least `n` elements in
-    /// the hash table.
+    /// Creates an empty `HashSet` with the specified capacity.
+    ///
+    /// The hash set will be able to hold at least `capacity` elements without
+    /// reallocating. If `capacity` is 0, the hash set will not allocate.
     ///
     /// # Examples
     ///
@@ -138,7 +152,8 @@ impl<T: Hash + Eq> HashSet<T, RandomState> {
 }
 
 impl<T, S> HashSet<T, S>
-    where T: Eq + Hash, S: BuildHasher
+    where T: Eq + Hash,
+          S: BuildHasher
 {
     /// Creates a new empty hash set which will use the given hasher to hash
     /// keys.
@@ -163,11 +178,14 @@ impl<T, S> HashSet<T, S>
     #[inline]
     #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
     pub fn with_hasher(hasher: S) -> HashSet<T, S> {
-        HashSet::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
+        HashSet { map: HashMap::with_hasher(hasher) }
     }
 
-    /// Creates an empty HashSet with space for at least `capacity`
-    /// elements in the hash table, using `hasher` to hash the keys.
+    /// Creates an empty HashSet with with the specified capacity, using
+    /// `hasher` to hash the keys.
+    ///
+    /// The hash set will be able to hold at least `capacity` elements without
+    /// reallocating. If `capacity` is 0, the hash set will not allocate.
     ///
     /// Warning: `hasher` is normally randomly generated, and
     /// is designed to allow `HashSet`s to be resistant to attacks that
@@ -186,11 +204,8 @@ impl<T, S> HashSet<T, S>
     /// ```
     #[inline]
     #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
-    pub fn with_capacity_and_hasher(capacity: usize, hasher: S)
-                                    -> HashSet<T, S> {
-        HashSet {
-            map: HashMap::with_capacity_and_hasher(capacity, hasher),
-        }
+    pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> HashSet<T, S> {
+        HashSet { map: HashMap::with_capacity_and_hasher(capacity, hasher) }
     }
 
     /// Returns a reference to the set's hasher.
@@ -327,8 +342,9 @@ impl<T, S> HashSet<T, S>
     /// assert_eq!(diff1, [1, 4].iter().cloned().collect());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, S>)
-        -> SymmetricDifference<'a, T, S> {
+    pub fn symmetric_difference<'a>(&'a self,
+                                    other: &'a HashSet<T, S>)
+                                    -> SymmetricDifference<'a, T, S> {
         SymmetricDifference { iter: self.difference(other).chain(other.difference(self)) }
     }
 
@@ -392,7 +408,9 @@ impl<T, S> HashSet<T, S>
     /// assert_eq!(v.len(), 1);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn len(&self) -> usize { self.map.len() }
+    pub fn len(&self) -> usize {
+        self.map.len()
+    }
 
     /// Returns true if the set contains no elements.
     ///
@@ -407,7 +425,9 @@ impl<T, S> HashSet<T, S>
     /// assert!(!v.is_empty());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn is_empty(&self) -> bool { self.map.is_empty() }
+    pub fn is_empty(&self) -> bool {
+        self.map.is_empty()
+    }
 
     /// Clears the set, returning all elements in an iterator.
     #[inline]
@@ -429,7 +449,9 @@ impl<T, S> HashSet<T, S>
     /// assert!(v.is_empty());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn clear(&mut self) { self.map.clear() }
+    pub fn clear(&mut self) {
+        self.map.clear()
+    }
 
     /// Returns `true` if the set contains a value.
     ///
@@ -448,7 +470,8 @@ impl<T, S> HashSet<T, S>
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
-        where T: Borrow<Q>, Q: Hash + Eq
+        where T: Borrow<Q>,
+              Q: Hash + Eq
     {
         self.map.contains_key(value)
     }
@@ -460,7 +483,8 @@ impl<T, S> HashSet<T, S>
     /// the value type.
     #[stable(feature = "set_recovery", since = "1.9.0")]
     pub fn get<Q: ?Sized>(&self, value: &Q) -> Option<&T>
-        where T: Borrow<Q>, Q: Hash + Eq
+        where T: Borrow<Q>,
+              Q: Hash + Eq
     {
         Recover::get(&self.map, value)
     }
@@ -551,7 +575,9 @@ impl<T, S> HashSet<T, S>
     /// assert_eq!(set.len(), 1);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()).is_none() }
+    pub fn insert(&mut self, value: T) -> bool {
+        self.map.insert(value, ()).is_none()
+    }
 
     /// Adds a value to the set, replacing the existing value, if any, that is equal to the given
     /// one. Returns the replaced value.
@@ -580,7 +606,8 @@ impl<T, S> HashSet<T, S>
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
-        where T: Borrow<Q>, Q: Hash + Eq
+        where T: Borrow<Q>,
+              Q: Hash + Eq
     {
         self.map.remove(value).is_some()
     }
@@ -592,7 +619,8 @@ impl<T, S> HashSet<T, S>
     /// the value type.
     #[stable(feature = "set_recovery", since = "1.9.0")]
     pub fn take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
-        where T: Borrow<Q>, Q: Hash + Eq
+        where T: Borrow<Q>,
+              Q: Hash + Eq
     {
         Recover::take(&mut self.map, value)
     }
@@ -600,10 +628,13 @@ impl<T, S> HashSet<T, S>
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> PartialEq for HashSet<T, S>
-    where T: Eq + Hash, S: BuildHasher
+    where T: Eq + Hash,
+          S: BuildHasher
 {
     fn eq(&self, other: &HashSet<T, S>) -> bool {
-        if self.len() != other.len() { return false; }
+        if self.len() != other.len() {
+            return false;
+        }
 
         self.iter().all(|key| other.contains(key))
     }
@@ -611,8 +642,10 @@ impl<T, S> PartialEq for HashSet<T, S>
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> Eq for HashSet<T, S>
-    where T: Eq + Hash, S: BuildHasher
-{}
+    where T: Eq + Hash,
+          S: BuildHasher
+{
+}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> fmt::Debug for HashSet<T, S>
@@ -627,9 +660,9 @@ impl<T, S> fmt::Debug for HashSet<T, S>
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> FromIterator<T> for HashSet<T, S>
     where T: Eq + Hash,
-          S: BuildHasher + Default,
+          S: BuildHasher + Default
 {
-    fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> HashSet<T, S> {
+    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> HashSet<T, S> {
         let iterator = iter.into_iter();
         let lower = iterator.size_hint().0;
         let mut set = HashSet::with_capacity_and_hasher(lower, Default::default());
@@ -641,9 +674,9 @@ impl<T, S> FromIterator<T> for HashSet<T, S>
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> Extend<T> for HashSet<T, S>
     where T: Eq + Hash,
-          S: BuildHasher,
+          S: BuildHasher
 {
-    fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) {
+    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
         for k in iter {
             self.insert(k);
         }
@@ -653,9 +686,9 @@ impl<T, S> Extend<T> for HashSet<T, S>
 #[stable(feature = "hash_extend_copy", since = "1.4.0")]
 impl<'a, T, S> Extend<&'a T> for HashSet<T, S>
     where T: 'a + Eq + Hash + Copy,
-          S: BuildHasher,
+          S: BuildHasher
 {
-    fn extend<I: IntoIterator<Item=&'a T>>(&mut self, iter: I) {
+    fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
         self.extend(iter.into_iter().cloned());
     }
 }
@@ -663,18 +696,18 @@ impl<'a, T, S> Extend<&'a T> for HashSet<T, S>
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> Default for HashSet<T, S>
     where T: Eq + Hash,
-          S: BuildHasher + Default,
+          S: BuildHasher + Default
 {
     /// Creates an empty `HashSet<T, S>` with the `Default` value for the hasher.
     fn default() -> HashSet<T, S> {
-        HashSet::with_hasher(Default::default())
+        HashSet { map: HashMap::default() }
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b, T, S> BitOr<&'b HashSet<T, S>> for &'a HashSet<T, S>
     where T: Eq + Hash + Clone,
-          S: BuildHasher + Default,
+          S: BuildHasher + Default
 {
     type Output = HashSet<T, S>;
 
@@ -706,7 +739,7 @@ impl<'a, 'b, T, S> BitOr<&'b HashSet<T, S>> for &'a HashSet<T, S>
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b, T, S> BitAnd<&'b HashSet<T, S>> for &'a HashSet<T, S>
     where T: Eq + Hash + Clone,
-          S: BuildHasher + Default,
+          S: BuildHasher + Default
 {
     type Output = HashSet<T, S>;
 
@@ -738,7 +771,7 @@ impl<'a, 'b, T, S> BitAnd<&'b HashSet<T, S>> for &'a HashSet<T, S>
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b, T, S> BitXor<&'b HashSet<T, S>> for &'a HashSet<T, S>
     where T: Eq + Hash + Clone,
-          S: BuildHasher + Default,
+          S: BuildHasher + Default
 {
     type Output = HashSet<T, S>;
 
@@ -770,7 +803,7 @@ impl<'a, 'b, T, S> BitXor<&'b HashSet<T, S>> for &'a HashSet<T, S>
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b, T, S> Sub<&'b HashSet<T, S>> for &'a HashSet<T, S>
     where T: Eq + Hash + Clone,
-          S: BuildHasher + Default,
+          S: BuildHasher + Default
 {
     type Output = HashSet<T, S>;
 
@@ -802,13 +835,13 @@ impl<'a, 'b, T, S> Sub<&'b HashSet<T, S>> for &'a HashSet<T, S>
 /// HashSet iterator
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, K: 'a> {
-    iter: Keys<'a, K, ()>
+    iter: Keys<'a, K, ()>,
 }
 
 /// HashSet move iterator
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<K> {
-    iter: map::IntoIter<K, ()>
+    iter: map::IntoIter<K, ()>,
 }
 
 /// HashSet drain iterator
@@ -838,18 +871,19 @@ pub struct Difference<'a, T: 'a, S: 'a> {
 /// Symmetric difference iterator.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct SymmetricDifference<'a, T: 'a, S: 'a> {
-    iter: Chain<Difference<'a, T, S>, Difference<'a, T, S>>
+    iter: Chain<Difference<'a, T, S>, Difference<'a, T, S>>,
 }
 
 /// Set union iterator.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Union<'a, T: 'a, S: 'a> {
-    iter: Chain<Iter<'a, T>, Difference<'a, T, S>>
+    iter: Chain<Iter<'a, T>, Difference<'a, T, S>>,
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> IntoIterator for &'a HashSet<T, S>
-    where T: Eq + Hash, S: BuildHasher
+    where T: Eq + Hash,
+          S: BuildHasher
 {
     type Item = &'a T;
     type IntoIter = Iter<'a, T>;
@@ -894,18 +928,26 @@ impl<T, S> IntoIterator for HashSet<T, S>
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K> Clone for Iter<'a, K> {
-    fn clone(&self) -> Iter<'a, K> { Iter { iter: self.iter.clone() } }
+    fn clone(&self) -> Iter<'a, K> {
+        Iter { iter: self.iter.clone() }
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K> Iterator for Iter<'a, K> {
     type Item = &'a K;
 
-    fn next(&mut self) -> Option<&'a K> { self.iter.next() }
-    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+    fn next(&mut self) -> Option<&'a K> {
+        self.iter.next()
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K> ExactSizeIterator for Iter<'a, K> {
-    fn len(&self) -> usize { self.iter.len() }
+    fn len(&self) -> usize {
+        self.iter.len()
+    }
 }
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, K> FusedIterator for Iter<'a, K> {}
@@ -914,12 +956,18 @@ impl<'a, K> FusedIterator for Iter<'a, K> {}
 impl<K> Iterator for IntoIter<K> {
     type Item = K;
 
-    fn next(&mut self) -> Option<K> { self.iter.next().map(|(k, _)| k) }
-    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+    fn next(&mut self) -> Option<K> {
+        self.iter.next().map(|(k, _)| k)
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K> ExactSizeIterator for IntoIter<K> {
-    fn len(&self) -> usize { self.iter.len() }
+    fn len(&self) -> usize {
+        self.iter.len()
+    }
 }
 #[unstable(feature = "fused", issue = "35602")]
 impl<K> FusedIterator for IntoIter<K> {}
@@ -928,12 +976,18 @@ impl<K> FusedIterator for IntoIter<K> {}
 impl<'a, K> Iterator for Drain<'a, K> {
     type Item = K;
 
-    fn next(&mut self) -> Option<K> { self.iter.next().map(|(k, _)| k) }
-    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+    fn next(&mut self) -> Option<K> {
+        self.iter.next().map(|(k, _)| k)
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K> ExactSizeIterator for Drain<'a, K> {
-    fn len(&self) -> usize { self.iter.len() }
+    fn len(&self) -> usize {
+        self.iter.len()
+    }
 }
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, K> FusedIterator for Drain<'a, K> {}
@@ -947,7 +1001,8 @@ impl<'a, T, S> Clone for Intersection<'a, T, S> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> Iterator for Intersection<'a, T, S>
-    where T: Eq + Hash, S: BuildHasher
+    where T: Eq + Hash,
+          S: BuildHasher
 {
     type Item = &'a T;
 
@@ -955,9 +1010,11 @@ impl<'a, T, S> Iterator for Intersection<'a, T, S>
         loop {
             match self.iter.next() {
                 None => return None,
-                Some(elt) => if self.other.contains(elt) {
-                    return Some(elt)
-                },
+                Some(elt) => {
+                    if self.other.contains(elt) {
+                        return Some(elt);
+                    }
+                }
             }
         }
     }
@@ -970,8 +1027,10 @@ impl<'a, T, S> Iterator for Intersection<'a, T, S>
 
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, T, S> FusedIterator for Intersection<'a, T, S>
-    where T: Eq + Hash, S: BuildHasher
-{}
+    where T: Eq + Hash,
+          S: BuildHasher
+{
+}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> Clone for Difference<'a, T, S> {
@@ -982,7 +1041,8 @@ impl<'a, T, S> Clone for Difference<'a, T, S> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> Iterator for Difference<'a, T, S>
-    where T: Eq + Hash, S: BuildHasher
+    where T: Eq + Hash,
+          S: BuildHasher
 {
     type Item = &'a T;
 
@@ -990,9 +1050,11 @@ impl<'a, T, S> Iterator for Difference<'a, T, S>
         loop {
             match self.iter.next() {
                 None => return None,
-                Some(elt) => if !self.other.contains(elt) {
-                    return Some(elt)
-                },
+                Some(elt) => {
+                    if !self.other.contains(elt) {
+                        return Some(elt);
+                    }
+                }
             }
         }
     }
@@ -1005,8 +1067,10 @@ impl<'a, T, S> Iterator for Difference<'a, T, S>
 
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, T, S> FusedIterator for Difference<'a, T, S>
-    where T: Eq + Hash, S: BuildHasher
-{}
+    where T: Eq + Hash,
+          S: BuildHasher
+{
+}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> Clone for SymmetricDifference<'a, T, S> {
@@ -1017,58 +1081,123 @@ impl<'a, T, S> Clone for SymmetricDifference<'a, T, S> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> Iterator for SymmetricDifference<'a, T, S>
-    where T: Eq + Hash, S: BuildHasher
+    where T: Eq + Hash,
+          S: BuildHasher
 {
     type Item = &'a T;
 
-    fn next(&mut self) -> Option<&'a T> { self.iter.next() }
-    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+    fn next(&mut self) -> Option<&'a T> {
+        self.iter.next()
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
 }
 
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, T, S> FusedIterator for SymmetricDifference<'a, T, S>
-    where T: Eq + Hash, S: BuildHasher
-{}
+    where T: Eq + Hash,
+          S: BuildHasher
+{
+}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> Clone for Union<'a, T, S> {
-    fn clone(&self) -> Union<'a, T, S> { Union { iter: self.iter.clone() } }
+    fn clone(&self) -> Union<'a, T, S> {
+        Union { iter: self.iter.clone() }
+    }
 }
 
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, T, S> FusedIterator for Union<'a, T, S>
-    where T: Eq + Hash, S: BuildHasher
-{}
+    where T: Eq + Hash,
+          S: BuildHasher
+{
+}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> Iterator for Union<'a, T, S>
-    where T: Eq + Hash, S: BuildHasher
+    where T: Eq + Hash,
+          S: BuildHasher
 {
     type Item = &'a T;
 
-    fn next(&mut self) -> Option<&'a T> { self.iter.next() }
-    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+    fn next(&mut self) -> Option<&'a T> {
+        self.iter.next()
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
 }
 
 #[allow(dead_code)]
 fn assert_covariance() {
-    fn set<'new>(v: HashSet<&'static str>) -> HashSet<&'new str> { v }
-    fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> { v }
-    fn into_iter<'new>(v: IntoIter<&'static str>) -> IntoIter<&'new str> { v }
+    fn set<'new>(v: HashSet<&'static str>) -> HashSet<&'new str> {
+        v
+    }
+    fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> {
+        v
+    }
+    fn into_iter<'new>(v: IntoIter<&'static str>) -> IntoIter<&'new str> {
+        v
+    }
     fn difference<'a, 'new>(v: Difference<'a, &'static str, RandomState>)
-        -> Difference<'a, &'new str, RandomState> { v }
+                            -> Difference<'a, &'new str, RandomState> {
+        v
+    }
     fn symmetric_difference<'a, 'new>(v: SymmetricDifference<'a, &'static str, RandomState>)
-        -> SymmetricDifference<'a, &'new str, RandomState> { v }
+                                      -> SymmetricDifference<'a, &'new str, RandomState> {
+        v
+    }
     fn intersection<'a, 'new>(v: Intersection<'a, &'static str, RandomState>)
-        -> Intersection<'a, &'new str, RandomState> { v }
+                              -> Intersection<'a, &'new str, RandomState> {
+        v
+    }
     fn union<'a, 'new>(v: Union<'a, &'static str, RandomState>)
-        -> Union<'a, &'new str, RandomState> { v }
-    fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { d }
+                       -> Union<'a, &'new str, RandomState> {
+        v
+    }
+    fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {
+        d
+    }
 }
 
 #[cfg(test)]
 mod test_set {
     use super::HashSet;
+    use super::super::map::RandomState;
+
+    #[test]
+    fn test_zero_capacities() {
+        type HS = HashSet<i32>;
+
+        let s = HS::new();
+        assert_eq!(s.capacity(), 0);
+
+        let s = HS::default();
+        assert_eq!(s.capacity(), 0);
+
+        let s = HS::with_hasher(RandomState::new());
+        assert_eq!(s.capacity(), 0);
+
+        let s = HS::with_capacity(0);
+        assert_eq!(s.capacity(), 0);
+
+        let s = HS::with_capacity_and_hasher(0, RandomState::new());
+        assert_eq!(s.capacity(), 0);
+
+        let mut s = HS::new();
+        s.insert(1);
+        s.insert(2);
+        s.remove(&1);
+        s.remove(&2);
+        s.shrink_to_fit();
+        assert_eq!(s.capacity(), 0);
+
+        let mut s = HS::new();
+        s.reserve(0);
+        assert_eq!(s.capacity(), 0);
+    }
 
     #[test]
     fn test_disjoint() {
@@ -1335,7 +1464,9 @@ mod test_set {
                 assert_eq!(last_i, 49);
             }
 
-            for _ in &s { panic!("s should be empty!"); }
+            for _ in &s {
+                panic!("s should be empty!");
+            }
 
             // reset to try again.
             s.extend(1..100);
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index 8f02c9c7d3d..ec0e457dc6a 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -21,13 +21,24 @@ use ptr::{self, Unique, Shared};
 
 use self::BucketState::*;
 
-const EMPTY_BUCKET: u64 = 0;
+/// Integer type used for stored hash values.
+///
+/// No more than bit_width(usize) bits are needed to select a bucket.
+///
+/// The most significant bit is ours to use for tagging `SafeHash`.
+///
+/// (Even if we could have usize::MAX bytes allocated for buckets,
+/// each bucket stores at least a `HashUint`, so there can be no more than
+/// usize::MAX / size_of(usize) buckets.)
+type HashUint = usize;
+
+const EMPTY_BUCKET: HashUint = 0;
 
 /// The raw hashtable, providing safe-ish access to the unzipped and highly
-/// optimized arrays of hashes, keys, and values.
+/// optimized arrays of hashes, and key-value pairs.
 ///
-/// This design uses less memory and is a lot faster than the naive
-/// `Vec<Option<u64, K, V>>`, because we don't pay for the overhead of an
+/// This design is a lot faster than the naive
+/// `Vec<Option<(u64, K, V)>>`, because we don't pay for the overhead of an
 /// option on every element, and we get a generally more cache-aware design.
 ///
 /// Essential invariants of this structure:
@@ -48,22 +59,23 @@ const EMPTY_BUCKET: u64 = 0;
 ///     which will likely map to the same bucket, while not being confused
 ///     with "empty".
 ///
-///   - All three "arrays represented by pointers" are the same length:
+///   - Both "arrays represented by pointers" are the same length:
 ///     `capacity`. This is set at creation and never changes. The arrays
-///     are unzipped to save space (we don't have to pay for the padding
-///     between odd sized elements, such as in a map from u64 to u8), and
-///     be more cache aware (scanning through 8 hashes brings in at most
-///     2 cache lines, since they're all right beside each other).
+///     are unzipped and are more cache aware (scanning through 8 hashes
+///     brings in at most 2 cache lines, since they're all right beside each
+///     other). This layout may waste space in padding such as in a map from
+///     u64 to u8, but is a more cache conscious layout as the key-value pairs
+///     are only very shortly probed and the desired value will be in the same
+///     or next cache line.
 ///
 /// You can kind of think of this module/data structure as a safe wrapper
 /// around just the "table" part of the hashtable. It enforces some
 /// invariants at the type level and employs some performance trickery,
-/// but in general is just a tricked out `Vec<Option<u64, K, V>>`.
-#[cfg_attr(stage0, unsafe_no_drop_flag)]
+/// but in general is just a tricked out `Vec<Option<(u64, K, V)>>`.
 pub struct RawTable<K, V> {
     capacity: usize,
     size: usize,
-    hashes: Unique<u64>,
+    hashes: Unique<HashUint>,
 
     // Because K/V do not appear directly in any of the types in the struct,
     // inform rustc that in fact instances of K and V are reachable from here.
@@ -74,11 +86,9 @@ unsafe impl<K: Send, V: Send> Send for RawTable<K, V> {}
 unsafe impl<K: Sync, V: Sync> Sync for RawTable<K, V> {}
 
 struct RawBucket<K, V> {
-    hash: *mut u64,
-
+    hash: *mut HashUint,
     // We use *const to ensure covariance with respect to K and V
-    key: *const K,
-    val: *const V,
+    pair: *const (K, V),
     _marker: marker::PhantomData<(K, V)>,
 }
 
@@ -137,15 +147,27 @@ pub struct GapThenFull<K, V, M> {
 /// buckets.
 #[derive(PartialEq, Copy, Clone)]
 pub struct SafeHash {
-    hash: u64,
+    hash: HashUint,
 }
 
 impl SafeHash {
     /// Peek at the hash value, which is guaranteed to be non-zero.
     #[inline(always)]
-    pub fn inspect(&self) -> u64 {
+    pub fn inspect(&self) -> HashUint {
         self.hash
     }
+
+    #[inline(always)]
+    pub fn new(hash: u64) -> Self {
+        // We need to avoid 0 in order to prevent collisions with
+        // EMPTY_HASH. We can maintain our precious uniform distribution
+        // of initial indexes by unconditionally setting the MSB,
+        // effectively reducing the hashes by one bit.
+        //
+        // Truncate hash to fit in `HashUint`.
+        let hash_bits = size_of::<HashUint>() * 8;
+        SafeHash { hash: (1 << (hash_bits - 1)) | (hash as HashUint) }
+    }
 }
 
 /// We need to remove hashes of 0. That's reserved for empty buckets.
@@ -157,33 +179,28 @@ pub fn make_hash<T: ?Sized, S>(hash_state: &S, t: &T) -> SafeHash
 {
     let mut state = hash_state.build_hasher();
     t.hash(&mut state);
-    // We need to avoid 0 in order to prevent collisions with
-    // EMPTY_HASH. We can maintain our precious uniform distribution
-    // of initial indexes by unconditionally setting the MSB,
-    // effectively reducing 64-bits hashes to 63 bits.
-    SafeHash { hash: 0x8000_0000_0000_0000 | state.finish() }
+    SafeHash::new(state.finish())
 }
 
-// `replace` casts a `*u64` to a `*SafeHash`. Since we statically
+// `replace` casts a `*HashUint` to a `*SafeHash`. Since we statically
 // ensure that a `FullBucket` points to an index with a non-zero hash,
-// and a `SafeHash` is just a `u64` with a different name, this is
+// and a `SafeHash` is just a `HashUint` with a different name, this is
 // safe.
 //
 // This test ensures that a `SafeHash` really IS the same size as a
-// `u64`. If you need to change the size of `SafeHash` (and
+// `HashUint`. If you need to change the size of `SafeHash` (and
 // consequently made this test fail), `replace` needs to be
 // modified to no longer assume this.
 #[test]
-fn can_alias_safehash_as_u64() {
-    assert_eq!(size_of::<SafeHash>(), size_of::<u64>())
+fn can_alias_safehash_as_hash() {
+    assert_eq!(size_of::<SafeHash>(), size_of::<HashUint>())
 }
 
 impl<K, V> RawBucket<K, V> {
     unsafe fn offset(self, count: isize) -> RawBucket<K, V> {
         RawBucket {
             hash: self.hash.offset(count),
-            key: self.key.offset(count),
-            val: self.val.offset(count),
+            pair: self.pair.offset(count),
             _marker: marker::PhantomData,
         }
     }
@@ -371,8 +388,7 @@ impl<K, V, M> EmptyBucket<K, V, M>
     pub fn put(mut self, hash: SafeHash, key: K, value: V) -> FullBucket<K, V, M> {
         unsafe {
             *self.raw.hash = hash.inspect();
-            ptr::write(self.raw.key as *mut K, key);
-            ptr::write(self.raw.val as *mut V, value);
+            ptr::write(self.raw.pair as *mut (K, V), (key, value));
 
             self.table.borrow_table_mut().size += 1;
         }
@@ -431,7 +447,7 @@ impl<K, V, M: Deref<Target = RawTable<K, V>>> FullBucket<K, V, M> {
 
     /// Gets references to the key and value at a given index.
     pub fn read(&self) -> (&K, &V) {
-        unsafe { (&*self.raw.key, &*self.raw.val) }
+        unsafe { (&(*self.raw.pair).0, &(*self.raw.pair).1) }
     }
 }
 
@@ -448,13 +464,14 @@ impl<'t, K, V> FullBucket<K, V, &'t mut RawTable<K, V>> {
 
         unsafe {
             *self.raw.hash = EMPTY_BUCKET;
+            let (k, v) = ptr::read(self.raw.pair);
             (EmptyBucket {
-                raw: self.raw,
-                idx: self.idx,
-                table: self.table,
-            },
-             ptr::read(self.raw.key),
-             ptr::read(self.raw.val))
+                 raw: self.raw,
+                 idx: self.idx,
+                 table: self.table,
+             },
+            k,
+            v)
         }
     }
 }
@@ -467,8 +484,7 @@ impl<K, V, M> FullBucket<K, V, M>
     pub fn replace(&mut self, h: SafeHash, k: K, v: V) -> (SafeHash, K, V) {
         unsafe {
             let old_hash = ptr::replace(self.raw.hash as *mut SafeHash, h);
-            let old_key = ptr::replace(self.raw.key as *mut K, k);
-            let old_val = ptr::replace(self.raw.val as *mut V, v);
+            let (old_key, old_val) = ptr::replace(self.raw.pair as *mut (K, V), (k, v));
 
             (old_hash, old_key, old_val)
         }
@@ -480,7 +496,8 @@ impl<K, V, M> FullBucket<K, V, M>
 {
     /// Gets mutable references to the key and value at a given index.
     pub fn read_mut(&mut self) -> (&mut K, &mut V) {
-        unsafe { (&mut *(self.raw.key as *mut K), &mut *(self.raw.val as *mut V)) }
+        let pair_mut = self.raw.pair as *mut (K, V);
+        unsafe { (&mut (*pair_mut).0, &mut (*pair_mut).1) }
     }
 }
 
@@ -493,7 +510,7 @@ impl<'t, K, V, M> FullBucket<K, V, M>
     /// in exchange for this, the returned references have a longer lifetime
     /// than the references returned by `read()`.
     pub fn into_refs(self) -> (&'t K, &'t V) {
-        unsafe { (&*self.raw.key, &*self.raw.val) }
+        unsafe { (&(*self.raw.pair).0, &(*self.raw.pair).1) }
     }
 }
 
@@ -503,7 +520,8 @@ impl<'t, K, V, M> FullBucket<K, V, M>
     /// This works similarly to `into_refs`, exchanging a bucket state
     /// for mutable references into the table.
     pub fn into_mut_refs(self) -> (&'t mut K, &'t mut V) {
-        unsafe { (&mut *(self.raw.key as *mut K), &mut *(self.raw.val as *mut V)) }
+        let pair_mut = self.raw.pair as *mut (K, V);
+        unsafe { (&mut (*pair_mut).0, &mut (*pair_mut).1) }
     }
 }
 
@@ -518,8 +536,7 @@ impl<K, V, M> GapThenFull<K, V, M>
     pub fn shift(mut self) -> Option<GapThenFull<K, V, M>> {
         unsafe {
             *self.gap.raw.hash = mem::replace(&mut *self.full.raw.hash, EMPTY_BUCKET);
-            ptr::copy_nonoverlapping(self.full.raw.key, self.gap.raw.key as *mut K, 1);
-            ptr::copy_nonoverlapping(self.full.raw.val, self.gap.raw.val as *mut V, 1);
+            ptr::copy_nonoverlapping(self.full.raw.pair, self.gap.raw.pair as *mut (K, V), 1);
         }
 
         let FullBucket { raw: prev_raw, idx: prev_idx, .. } = self.full;
@@ -561,49 +578,42 @@ fn test_rounding() {
     assert_eq!(round_up_to_next(5, 4), 8);
 }
 
-// Returns a tuple of (key_offset, val_offset),
+// Returns a tuple of (pairs_offset, end_of_pairs_offset),
 // from the start of a mallocated array.
 #[inline]
 fn calculate_offsets(hashes_size: usize,
-                     keys_size: usize,
-                     keys_align: usize,
-                     vals_align: usize)
+                     pairs_size: usize,
+                     pairs_align: usize)
                      -> (usize, usize, bool) {
-    let keys_offset = round_up_to_next(hashes_size, keys_align);
-    let (end_of_keys, oflo) = keys_offset.overflowing_add(keys_size);
+    let pairs_offset = round_up_to_next(hashes_size, pairs_align);
+    let (end_of_pairs, oflo) = pairs_offset.overflowing_add(pairs_size);
 
-    let vals_offset = round_up_to_next(end_of_keys, vals_align);
-
-    (keys_offset, vals_offset, oflo)
+    (pairs_offset, end_of_pairs, oflo)
 }
 
 // Returns a tuple of (minimum required malloc alignment, hash_offset,
 // array_size), from the start of a mallocated array.
 fn calculate_allocation(hash_size: usize,
                         hash_align: usize,
-                        keys_size: usize,
-                        keys_align: usize,
-                        vals_size: usize,
-                        vals_align: usize)
+                        pairs_size: usize,
+                        pairs_align: usize)
                         -> (usize, usize, usize, bool) {
     let hash_offset = 0;
-    let (_, vals_offset, oflo) = calculate_offsets(hash_size, keys_size, keys_align, vals_align);
-    let (end_of_vals, oflo2) = vals_offset.overflowing_add(vals_size);
+    let (_, end_of_pairs, oflo) = calculate_offsets(hash_size, pairs_size, pairs_align);
 
-    let align = cmp::max(hash_align, cmp::max(keys_align, vals_align));
+    let align = cmp::max(hash_align, pairs_align);
 
-    (align, hash_offset, end_of_vals, oflo || oflo2)
+    (align, hash_offset, end_of_pairs, oflo)
 }
 
 #[test]
 fn test_offset_calculation() {
-    assert_eq!(calculate_allocation(128, 8, 15, 1, 4, 4),
-               (8, 0, 148, false));
-    assert_eq!(calculate_allocation(3, 1, 2, 1, 1, 1), (1, 0, 6, false));
-    assert_eq!(calculate_allocation(6, 2, 12, 4, 24, 8), (8, 0, 48, false));
-    assert_eq!(calculate_offsets(128, 15, 1, 4), (128, 144, false));
-    assert_eq!(calculate_offsets(3, 2, 1, 1), (3, 5, false));
-    assert_eq!(calculate_offsets(6, 12, 4, 8), (8, 24, false));
+    assert_eq!(calculate_allocation(128, 8, 16, 8), (8, 0, 144, false));
+    assert_eq!(calculate_allocation(3, 1, 2, 1), (1, 0, 5, false));
+    assert_eq!(calculate_allocation(6, 2, 12, 4), (4, 0, 20, false));
+    assert_eq!(calculate_offsets(128, 15, 4), (128, 143, false));
+    assert_eq!(calculate_offsets(3, 2, 4), (4, 6, false));
+    assert_eq!(calculate_offsets(6, 12, 4), (8, 20, false));
 }
 
 impl<K, V> RawTable<K, V> {
@@ -614,18 +624,17 @@ impl<K, V> RawTable<K, V> {
             return RawTable {
                 size: 0,
                 capacity: 0,
-                hashes: Unique::new(EMPTY as *mut u64),
+                hashes: Unique::new(EMPTY as *mut HashUint),
                 marker: marker::PhantomData,
             };
         }
 
         // No need for `checked_mul` before a more restrictive check performed
         // later in this method.
-        let hashes_size = capacity * size_of::<u64>();
-        let keys_size = capacity * size_of::<K>();
-        let vals_size = capacity * size_of::<V>();
+        let hashes_size = capacity.wrapping_mul(size_of::<HashUint>());
+        let pairs_size = capacity.wrapping_mul(size_of::<(K, V)>());
 
-        // Allocating hashmaps is a little tricky. We need to allocate three
+        // Allocating hashmaps is a little tricky. We need to allocate two
         // arrays, but since we know their sizes and alignments up front,
         // we just allocate a single array, and then have the subarrays
         // point into it.
@@ -633,32 +642,25 @@ impl<K, V> RawTable<K, V> {
         // This is great in theory, but in practice getting the alignment
         // right is a little subtle. Therefore, calculating offsets has been
         // factored out into a different function.
-        let (malloc_alignment, hash_offset, size, oflo) = calculate_allocation(hashes_size,
-                                                                               align_of::<u64>(),
-                                                                               keys_size,
-                                                                               align_of::<K>(),
-                                                                               vals_size,
-                                                                               align_of::<V>());
-
+        let (alignment, hash_offset, size, oflo) = calculate_allocation(hashes_size,
+                                                                        align_of::<HashUint>(),
+                                                                        pairs_size,
+                                                                        align_of::<(K, V)>());
         assert!(!oflo, "capacity overflow");
 
         // One check for overflow that covers calculation and rounding of size.
-        let size_of_bucket = size_of::<u64>()
-                                 .checked_add(size_of::<K>())
-                                 .unwrap()
-                                 .checked_add(size_of::<V>())
-                                 .unwrap();
+        let size_of_bucket = size_of::<HashUint>().checked_add(size_of::<(K, V)>()).unwrap();
         assert!(size >=
                 capacity.checked_mul(size_of_bucket)
-                        .expect("capacity overflow"),
+                    .expect("capacity overflow"),
                 "capacity overflow");
 
-        let buffer = allocate(size, malloc_alignment);
+        let buffer = allocate(size, alignment);
         if buffer.is_null() {
             ::alloc::oom()
         }
 
-        let hashes = buffer.offset(hash_offset as isize) as *mut u64;
+        let hashes = buffer.offset(hash_offset as isize) as *mut HashUint;
 
         RawTable {
             capacity: capacity,
@@ -669,20 +671,17 @@ impl<K, V> RawTable<K, V> {
     }
 
     fn first_bucket_raw(&self) -> RawBucket<K, V> {
-        let hashes_size = self.capacity * size_of::<u64>();
-        let keys_size = self.capacity * size_of::<K>();
-
-        let buffer = *self.hashes as *const u8;
-        let (keys_offset, vals_offset, oflo) = calculate_offsets(hashes_size,
-                                                                 keys_size,
-                                                                 align_of::<K>(),
-                                                                 align_of::<V>());
+        let hashes_size = self.capacity * size_of::<HashUint>();
+        let pairs_size = self.capacity * size_of::<(K, V)>();
+
+        let buffer = *self.hashes as *mut u8;
+        let (pairs_offset, _, oflo) =
+            calculate_offsets(hashes_size, pairs_size, align_of::<(K, V)>());
         debug_assert!(!oflo, "capacity overflow");
         unsafe {
             RawBucket {
                 hash: *self.hashes,
-                key: buffer.offset(keys_offset as isize) as *const K,
-                val: buffer.offset(vals_offset as isize) as *const V,
+                pair: buffer.offset(pairs_offset as isize) as *const _,
                 _marker: marker::PhantomData,
             }
         }
@@ -776,7 +775,7 @@ impl<K, V> RawTable<K, V> {
 /// this interface is safe, it's not used outside this module.
 struct RawBuckets<'a, K, V> {
     raw: RawBucket<K, V>,
-    hashes_end: *mut u64,
+    hashes_end: *mut HashUint,
 
     // Strictly speaking, this should be &'a (K,V), but that would
     // require that K:'a, and we often use RawBuckets<'static...> for
@@ -822,7 +821,7 @@ impl<'a, K, V> Iterator for RawBuckets<'a, K, V> {
 /// the table's remaining entries. It's used in the implementation of Drop.
 struct RevMoveBuckets<'a, K, V> {
     raw: RawBucket<K, V>,
-    hashes_end: *mut u64,
+    hashes_end: *mut HashUint,
     elems_left: usize,
 
     // As above, `&'a (K,V)` would seem better, but we often use
@@ -847,7 +846,7 @@ impl<'a, K, V> Iterator for RevMoveBuckets<'a, K, V> {
 
                 if *self.raw.hash != EMPTY_BUCKET {
                     self.elems_left -= 1;
-                    return Some((ptr::read(self.raw.key), ptr::read(self.raw.val)));
+                    return Some(ptr::read(self.raw.pair));
                 }
             }
         }
@@ -912,7 +911,7 @@ impl<'a, K, V> Iterator for Iter<'a, K, V> {
     fn next(&mut self) -> Option<(&'a K, &'a V)> {
         self.iter.next().map(|bucket| {
             self.elems_left -= 1;
-            unsafe { (&*bucket.key, &*bucket.val) }
+            unsafe { (&(*bucket.pair).0, &(*bucket.pair).1) }
         })
     }
 
@@ -932,7 +931,8 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> {
     fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
         self.iter.next().map(|bucket| {
             self.elems_left -= 1;
-            unsafe { (&*bucket.key, &mut *(bucket.val as *mut V)) }
+            let pair_mut = bucket.pair as *mut (K, V);
+            unsafe { (&(*pair_mut).0, &mut (*pair_mut).1) }
         })
     }
 
@@ -953,7 +953,8 @@ impl<K, V> Iterator for IntoIter<K, V> {
         self.iter.next().map(|bucket| {
             self.table.size -= 1;
             unsafe {
-                (SafeHash { hash: *bucket.hash }, ptr::read(bucket.key), ptr::read(bucket.val))
+                let (k, v) = ptr::read(bucket.pair);
+                (SafeHash { hash: *bucket.hash }, k, v)
             }
         })
     }
@@ -977,9 +978,8 @@ impl<'a, K, V> Iterator for Drain<'a, K, V> {
         self.iter.next().map(|bucket| {
             unsafe {
                 (**self.table).size -= 1;
-                (SafeHash { hash: ptr::replace(bucket.hash, EMPTY_BUCKET) },
-                 ptr::read(bucket.key),
-                 ptr::read(bucket.val))
+                let (k, v) = ptr::read(bucket.pair);
+                (SafeHash { hash: ptr::replace(bucket.hash, EMPTY_BUCKET) }, k, v)
             }
         })
     }
@@ -991,9 +991,7 @@ impl<'a, K, V> Iterator for Drain<'a, K, V> {
 }
 impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
     fn len(&self) -> usize {
-        unsafe {
-            (**self.table).size()
-        }
+        unsafe { (**self.table).size() }
     }
 }
 
@@ -1020,8 +1018,7 @@ impl<K: Clone, V: Clone> Clone for RawTable<K, V> {
                                 (full.hash(), k.clone(), v.clone())
                             };
                             *new_buckets.raw.hash = h.inspect();
-                            ptr::write(new_buckets.raw.key as *mut K, k);
-                            ptr::write(new_buckets.raw.val as *mut V, v);
+                            ptr::write(new_buckets.raw.pair as *mut (K, V), (k, v));
                         }
                         Empty(..) => {
                             *new_buckets.raw.hash = EMPTY_BUCKET;
@@ -1058,15 +1055,12 @@ impl<K, V> Drop for RawTable<K, V> {
             }
         }
 
-        let hashes_size = self.capacity * size_of::<u64>();
-        let keys_size = self.capacity * size_of::<K>();
-        let vals_size = self.capacity * size_of::<V>();
+        let hashes_size = self.capacity * size_of::<HashUint>();
+        let pairs_size = self.capacity * size_of::<(K, V)>();
         let (align, _, size, oflo) = calculate_allocation(hashes_size,
-                                                          align_of::<u64>(),
-                                                          keys_size,
-                                                          align_of::<K>(),
-                                                          vals_size,
-                                                          align_of::<V>());
+                                                          align_of::<HashUint>(),
+                                                          pairs_size,
+                                                          align_of::<(K, V)>());
 
         debug_assert!(!oflo, "should be impossible");
 
diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs
index 9b13d542300..b9e92a01b2f 100644
--- a/src/libstd/collections/mod.rs
+++ b/src/libstd/collections/mod.rs
@@ -15,7 +15,7 @@
 //! standard implementations, it should be possible for two libraries to
 //! communicate without significant data conversion.
 //!
-//! To get this out of the way: you should probably just use `Vec` or `HashMap`.
+//! To get this out of the way: you should probably just use [`Vec`] or [`HashMap`].
 //! These two collections cover most use cases for generic data storage and
 //! processing. They are exceptionally good at doing what they do. All the other
 //! collections in the standard library have specific use cases where they are
@@ -25,10 +25,10 @@
 //!
 //! Rust's collections can be grouped into four major categories:
 //!
-//! * Sequences: `Vec`, `VecDeque`, `LinkedList`
-//! * Maps: `HashMap`, `BTreeMap`
-//! * Sets: `HashSet`, `BTreeSet`
-//! * Misc: `BinaryHeap`
+//! * Sequences: [`Vec`], [`VecDeque`], [`LinkedList`]
+//! * Maps: [`HashMap`], [`BTreeMap`]
+//! * Sets: [`HashSet`], [`BTreeSet`]
+//! * Misc: [`BinaryHeap`]
 //!
 //! # When Should You Use Which Collection?
 //!
@@ -46,13 +46,13 @@
 //! * You want a heap-allocated array.
 //!
 //! ### Use a `VecDeque` when:
-//! * You want a `Vec` that supports efficient insertion at both ends of the
+//! * You want a [`Vec`] that supports efficient insertion at both ends of the
 //!   sequence.
 //! * You want a queue.
 //! * You want a double-ended queue (deque).
 //!
 //! ### Use a `LinkedList` when:
-//! * You want a `Vec` or `VecDeque` of unknown size, and can't tolerate
+//! * You want a [`Vec`] or [`VecDeque`] of unknown size, and can't tolerate
 //!   amortization.
 //! * You want to efficiently split and append lists.
 //! * You are *absolutely* certain you *really*, *truly*, want a doubly linked
@@ -92,38 +92,38 @@
 //! Throughout the documentation, we will follow a few conventions. For all
 //! operations, the collection's size is denoted by n. If another collection is
 //! involved in the operation, it contains m elements. Operations which have an
-//! *amortized* cost are suffixed with a `*`.  Operations with an *expected*
+//! *amortized* cost are suffixed with a `*`. Operations with an *expected*
 //! cost are suffixed with a `~`.
 //!
 //! All amortized costs are for the potential need to resize when capacity is
-//! exhausted.  If a resize occurs it will take O(n) time. Our collections never
+//! exhausted. If a resize occurs it will take O(n) time. Our collections never
 //! automatically shrink, so removal operations aren't amortized. Over a
 //! sufficiently large series of operations, the average cost per operation will
 //! deterministically equal the given cost.
 //!
-//! Only HashMap has expected costs, due to the probabilistic nature of hashing.
-//! It is theoretically possible, though very unlikely, for HashMap to
+//! Only [`HashMap`] has expected costs, due to the probabilistic nature of hashing.
+//! It is theoretically possible, though very unlikely, for [`HashMap`] to
 //! experience worse performance.
 //!
 //! ## Sequences
 //!
-//! |              | get(i)         | insert(i)       | remove(i)      | append | split_off(i)   |
-//! |--------------|----------------|-----------------|----------------|--------|----------------|
-//! | Vec          | O(1)           | O(n-i)*         | O(n-i)         | O(m)*  | O(n-i)         |
-//! | VecDeque     | O(1)           | O(min(i, n-i))* | O(min(i, n-i)) | O(m)*  | O(min(i, n-i)) |
-//! | LinkedList   | O(min(i, n-i)) | O(min(i, n-i))  | O(min(i, n-i)) | O(1)   | O(min(i, n-i)) |
+//! |                | get(i)         | insert(i)       | remove(i)      | append | split_off(i)   |
+//! |----------------|----------------|-----------------|----------------|--------|----------------|
+//! | [`Vec`]        | O(1)           | O(n-i)*         | O(n-i)         | O(m)*  | O(n-i)         |
+//! | [`VecDeque`]   | O(1)           | O(min(i, n-i))* | O(min(i, n-i)) | O(m)*  | O(min(i, n-i)) |
+//! | [`LinkedList`] | O(min(i, n-i)) | O(min(i, n-i))  | O(min(i, n-i)) | O(1)   | O(min(i, n-i)) |
 //!
-//! Note that where ties occur, Vec is generally going to be faster than VecDeque, and VecDeque
-//! is generally going to be faster than LinkedList.
+//! Note that where ties occur, [`Vec`] is generally going to be faster than [`VecDeque`], and
+//! [`VecDeque`] is generally going to be faster than [`LinkedList`].
 //!
 //! ## Maps
 //!
 //! For Sets, all operations have the cost of the equivalent Map operation.
 //!
-//! |          | get       | insert   | remove   | predecessor | append |
-//! |----------|-----------|----------|----------|-------------|--------|
-//! | HashMap  | O(1)~     | O(1)~*   | O(1)~    | N/A         | N/A    |
-//! | BTreeMap | O(log n)  | O(log n) | O(log n) | O(log n)    | O(n+m) |
+//! |              | get       | insert   | remove   | predecessor | append |
+//! |--------------|-----------|----------|----------|-------------|--------|
+//! | [`HashMap`]  | O(1)~     | O(1)~*   | O(1)~    | N/A         | N/A    |
+//! | [`BTreeMap`] | O(log n)  | O(log n) | O(log n) | O(log n)    | O(n+m) |
 //!
 //! # Correct and Efficient Usage of Collections
 //!
@@ -136,7 +136,7 @@
 //! ## Capacity Management
 //!
 //! Many collections provide several constructors and methods that refer to
-//! "capacity".  These collections are generally built on top of an array.
+//! "capacity". These collections are generally built on top of an array.
 //! Optimally, this array would be exactly the right size to fit only the
 //! elements stored in the collection, but for the collection to do this would
 //! be very inefficient. If the backing array was exactly the right size at all
@@ -157,29 +157,29 @@
 //! information to do this itself. Therefore, it is up to us programmers to give
 //! it hints.
 //!
-//! Any `with_capacity` constructor will instruct the collection to allocate
+//! Any `with_capacity()` constructor will instruct the collection to allocate
 //! enough space for the specified number of elements. Ideally this will be for
 //! exactly that many elements, but some implementation details may prevent
-//! this. `Vec` and `VecDeque` can be relied on to allocate exactly the
-//! requested amount, though. Use `with_capacity` when you know exactly how many
+//! this. [`Vec`] and [`VecDeque`] can be relied on to allocate exactly the
+//! requested amount, though. Use `with_capacity()` when you know exactly how many
 //! elements will be inserted, or at least have a reasonable upper-bound on that
 //! number.
 //!
-//! When anticipating a large influx of elements, the `reserve` family of
+//! When anticipating a large influx of elements, the `reserve()` family of
 //! methods can be used to hint to the collection how much room it should make
-//! for the coming items.  As with `with_capacity`, the precise behavior of
+//! for the coming items. As with `with_capacity()`, the precise behavior of
 //! these methods will be specific to the collection of interest.
 //!
 //! For optimal performance, collections will generally avoid shrinking
-//! themselves.  If you believe that a collection will not soon contain any more
-//! elements, or just really need the memory, the `shrink_to_fit` method prompts
+//! themselves. If you believe that a collection will not soon contain any more
+//! elements, or just really need the memory, the `shrink_to_fit()` method prompts
 //! the collection to shrink the backing array to the minimum size capable of
 //! holding its elements.
 //!
 //! Finally, if ever you're interested in what the actual capacity of the
-//! collection is, most collections provide a `capacity` method to query this
-//! information on demand.  This can be useful for debugging purposes, or for
-//! use with the `reserve` methods.
+//! collection is, most collections provide a `capacity()` method to query this
+//! information on demand. This can be useful for debugging purposes, or for
+//! use with the `reserve()` methods.
 //!
 //! ## Iterators
 //!
@@ -194,15 +194,15 @@
 //!
 //! All of the standard collections provide several iterators for performing
 //! bulk manipulation of their contents. The three primary iterators almost
-//! every collection should provide are `iter`, `iter_mut`, and `into_iter`.
+//! every collection should provide are `iter()`, `iter_mut()`, and `into_iter()`.
 //! Some of these are not provided on collections where it would be unsound or
 //! unreasonable to provide them.
 //!
-//! `iter` provides an iterator of immutable references to all the contents of a
-//! collection in the most "natural" order. For sequence collections like `Vec`,
+//! `iter()` provides an iterator of immutable references to all the contents of a
+//! collection in the most "natural" order. For sequence collections like [`Vec`],
 //! this means the items will be yielded in increasing order of index starting
-//! at 0. For ordered collections like `BTreeMap`, this means that the items
-//! will be yielded in sorted order.  For unordered collections like `HashMap`,
+//! at 0. For ordered collections like [`BTreeMap`], this means that the items
+//! will be yielded in sorted order. For unordered collections like [`HashMap`],
 //! the items will be yielded in whatever order the internal representation made
 //! most convenient. This is great for reading through all the contents of the
 //! collection.
@@ -214,8 +214,8 @@
 //! }
 //! ```
 //!
-//! `iter_mut` provides an iterator of *mutable* references in the same order as
-//! `iter`.  This is great for mutating all the contents of the collection.
+//! `iter_mut()` provides an iterator of *mutable* references in the same order as
+//! `iter()`. This is great for mutating all the contents of the collection.
 //!
 //! ```
 //! let mut vec = vec![1, 2, 3, 4];
@@ -224,12 +224,12 @@
 //! }
 //! ```
 //!
-//! `into_iter` transforms the actual collection into an iterator over its
+//! `into_iter()` transforms the actual collection into an iterator over its
 //! contents by-value. This is great when the collection itself is no longer
-//! needed, and the values are needed elsewhere. Using `extend` with `into_iter`
+//! needed, and the values are needed elsewhere. Using `extend()` with `into_iter()`
 //! is the main way that contents of one collection are moved into another.
-//! `extend` automatically calls `into_iter`, and takes any `T: IntoIterator`.
-//! Calling `collect` on an iterator itself is also a great way to convert one
+//! `extend()` automatically calls `into_iter()`, and takes any `T: `[`IntoIterator`].
+//! Calling `collect()` on an iterator itself is also a great way to convert one
 //! collection into another. Both of these methods should internally use the
 //! capacity management tools discussed in the previous section to do this as
 //! efficiently as possible.
@@ -248,9 +248,9 @@
 //! ```
 //!
 //! Iterators also provide a series of *adapter* methods for performing common
-//! threads to sequences. Among the adapters are functional favorites like `map`,
-//! `fold`, `skip`, and `take`. Of particular interest to collections is the
-//! `rev` adapter, that reverses any iterator that supports this operation. Most
+//! threads to sequences. Among the adapters are functional favorites like `map()`,
+//! `fold()`, `skip()` and `take()`. Of particular interest to collections is the
+//! `rev()` adapter, that reverses any iterator that supports this operation. Most
 //! collections provide reversible iterators as the way to iterate over them in
 //! reverse order.
 //!
@@ -263,27 +263,27 @@
 //!
 //! Several other collection methods also return iterators to yield a sequence
 //! of results but avoid allocating an entire collection to store the result in.
-//! This provides maximum flexibility as `collect` or `extend` can be called to
+//! This provides maximum flexibility as `collect()` or `extend()` can be called to
 //! "pipe" the sequence into any collection if desired. Otherwise, the sequence
 //! can be looped over with a `for` loop. The iterator can also be discarded
 //! after partial use, preventing the computation of the unused items.
 //!
 //! ## Entries
 //!
-//! The `entry` API is intended to provide an efficient mechanism for
+//! The `entry()` API is intended to provide an efficient mechanism for
 //! manipulating the contents of a map conditionally on the presence of a key or
 //! not. The primary motivating use case for this is to provide efficient
 //! accumulator maps. For instance, if one wishes to maintain a count of the
 //! number of times each key has been seen, they will have to perform some
 //! conditional logic on whether this is the first time the key has been seen or
-//! not. Normally, this would require a `find` followed by an `insert`,
+//! not. Normally, this would require a `find()` followed by an `insert()`,
 //! effectively duplicating the search effort on each insertion.
 //!
 //! When a user calls `map.entry(&key)`, the map will search for the key and
 //! then yield a variant of the `Entry` enum.
 //!
 //! If a `Vacant(entry)` is yielded, then the key *was not* found. In this case
-//! the only valid operation is to `insert` a value into the entry. When this is
+//! the only valid operation is to `insert()` a value into the entry. When this is
 //! done, the vacant entry is consumed and converted into a mutable reference to
 //! the value that was inserted. This allows for further manipulation of the
 //! value beyond the lifetime of the search itself. This is useful if complex
@@ -291,14 +291,14 @@
 //! just inserted.
 //!
 //! If an `Occupied(entry)` is yielded, then the key *was* found. In this case,
-//! the user has several options: they can `get`, `insert`, or `remove` the
+//! the user has several options: they can `get()`, `insert()` or `remove()` the
 //! value of the occupied entry. Additionally, they can convert the occupied
 //! entry into a mutable reference to its value, providing symmetry to the
-//! vacant `insert` case.
+//! vacant `insert()` case.
 //!
 //! ### Examples
 //!
-//! Here are the two primary ways in which `entry` is used. First, a simple
+//! Here are the two primary ways in which `entry()` is used. First, a simple
 //! example where the logic performed on the values is trivial.
 //!
 //! #### Counting the number of times each character in a string occurs
@@ -322,7 +322,7 @@
 //! ```
 //!
 //! When the logic to be performed on the value is more complex, we may simply
-//! use the `entry` API to ensure that the value is initialized, and perform the
+//! use the `entry()` API to ensure that the value is initialized and perform the
 //! logic afterwards.
 //!
 //! #### Tracking the inebriation of customers at a bar
@@ -406,6 +406,16 @@
 //! // ...but the key hasn't changed. b is still "baz", not "xyz".
 //! assert_eq!(map.keys().next().unwrap().b, "baz");
 //! ```
+//!
+//! [`Vec`]: ../../std/vec/struct.Vec.html
+//! [`HashMap`]: ../../std/collections/struct.HashMap.html
+//! [`VecDeque`]: ../../std/collections/struct.VecDeque.html
+//! [`LinkedList`]: ../../std/collections/struct.LinkedList.html
+//! [`BTreeMap`]: ../../std/collections/struct.BTreeMap.html
+//! [`HashSet`]: ../../std/collections/struct.HashSet.html
+//! [`BTreeSet`]: ../../std/collections/struct.BTreeSet.html
+//! [`BinaryHeap`]: ../../std/collections/struct.BinaryHeap.html
+//! [`IntoIterator`]: ../../std/iter/trait.IntoIterator.html
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -425,6 +435,9 @@ pub use self::hash_map::HashMap;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::hash_set::HashSet;
 
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use core_collections::range;
+
 mod hash;
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index 63bf051c9bc..e29dbe35c5a 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -21,6 +21,7 @@ use ffi::{OsStr, OsString};
 use fmt;
 use io;
 use path::{Path, PathBuf};
+use sys;
 use sys::os as os_imp;
 
 /// Returns the current working directory as a `PathBuf`.
@@ -83,7 +84,7 @@ pub struct VarsOs { inner: os_imp::Env }
 /// environment variables of the current process.
 ///
 /// The returned iterator contains a snapshot of the process's environment
-/// variables at the time of this invocation, modifications to environment
+/// variables at the time of this invocation. Modifications to environment
 /// variables afterwards will not be reflected in the returned iterator.
 ///
 /// # Panics
@@ -112,7 +113,7 @@ pub fn vars() -> Vars {
 /// environment variables of the current process.
 ///
 /// The returned iterator contains a snapshot of the process's environment
-/// variables at the time of this invocation, modifications to environment
+/// variables at the time of this invocation. Modifications to environment
 /// variables afterwards will not be reflected in the returned iterator.
 ///
 /// # Examples
@@ -557,7 +558,7 @@ pub struct Args { inner: ArgsOs }
 ///
 /// This structure is created through the `std::env::args_os` method.
 #[stable(feature = "env", since = "1.0.0")]
-pub struct ArgsOs { inner: os_imp::Args }
+pub struct ArgsOs { inner: sys::args::Args }
 
 /// Returns the arguments which this program was started with (normally passed
 /// via the command line).
@@ -606,7 +607,7 @@ pub fn args() -> Args {
 /// ```
 #[stable(feature = "env", since = "1.0.0")]
 pub fn args_os() -> ArgsOs {
-    ArgsOs { inner: os_imp::args() }
+    ArgsOs { inner: sys::args::args() }
 }
 
 #[stable(feature = "env", since = "1.0.0")]
@@ -649,6 +650,8 @@ impl DoubleEndedIterator for ArgsOs {
 /// Constants associated with the current target
 #[stable(feature = "env", since = "1.0.0")]
 pub mod consts {
+    use sys::env::os;
+
     /// A string describing the architecture of the CPU that is currently
     /// in use.
     ///
@@ -673,7 +676,7 @@ pub mod consts {
     /// - unix
     /// - windows
     #[stable(feature = "env", since = "1.0.0")]
-    pub const FAMILY: &'static str = super::os::FAMILY;
+    pub const FAMILY: &'static str = os::FAMILY;
 
     /// A string describing the specific operating system in use.
     /// Example value is `linux`.
@@ -692,7 +695,7 @@ pub mod consts {
     /// - android
     /// - windows
     #[stable(feature = "env", since = "1.0.0")]
-    pub const OS: &'static str = super::os::OS;
+    pub const OS: &'static str = os::OS;
 
     /// Specifies the filename prefix used for shared libraries on this
     /// platform. Example value is `lib`.
@@ -702,7 +705,7 @@ pub mod consts {
     /// - lib
     /// - `""` (an empty string)
     #[stable(feature = "env", since = "1.0.0")]
-    pub const DLL_PREFIX: &'static str = super::os::DLL_PREFIX;
+    pub const DLL_PREFIX: &'static str = os::DLL_PREFIX;
 
     /// Specifies the filename suffix used for shared libraries on this
     /// platform. Example value is `.so`.
@@ -713,7 +716,7 @@ pub mod consts {
     /// - .dylib
     /// - .dll
     #[stable(feature = "env", since = "1.0.0")]
-    pub const DLL_SUFFIX: &'static str = super::os::DLL_SUFFIX;
+    pub const DLL_SUFFIX: &'static str = os::DLL_SUFFIX;
 
     /// Specifies the file extension used for shared libraries on this
     /// platform that goes after the dot. Example value is `so`.
@@ -724,7 +727,7 @@ pub mod consts {
     /// - dylib
     /// - dll
     #[stable(feature = "env", since = "1.0.0")]
-    pub const DLL_EXTENSION: &'static str = super::os::DLL_EXTENSION;
+    pub const DLL_EXTENSION: &'static str = os::DLL_EXTENSION;
 
     /// Specifies the filename suffix used for executable binaries on this
     /// platform. Example value is `.exe`.
@@ -736,7 +739,7 @@ pub mod consts {
     /// - .pexe
     /// - `""` (an empty string)
     #[stable(feature = "env", since = "1.0.0")]
-    pub const EXE_SUFFIX: &'static str = super::os::EXE_SUFFIX;
+    pub const EXE_SUFFIX: &'static str = os::EXE_SUFFIX;
 
     /// Specifies the file extension, if any, used for executable binaries
     /// on this platform. Example value is `exe`.
@@ -746,161 +749,7 @@ pub mod consts {
     /// - exe
     /// - `""` (an empty string)
     #[stable(feature = "env", since = "1.0.0")]
-    pub const EXE_EXTENSION: &'static str = super::os::EXE_EXTENSION;
-
-}
-
-#[cfg(target_os = "linux")]
-mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "linux";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
-}
-
-#[cfg(target_os = "macos")]
-mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "macos";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".dylib";
-    pub const DLL_EXTENSION: &'static str = "dylib";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
-}
-
-#[cfg(target_os = "ios")]
-mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "ios";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".dylib";
-    pub const DLL_EXTENSION: &'static str = "dylib";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
-}
-
-#[cfg(target_os = "freebsd")]
-mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "freebsd";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
-}
-
-#[cfg(target_os = "dragonfly")]
-mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "dragonfly";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
-}
-
-#[cfg(target_os = "bitrig")]
-mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "bitrig";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
-}
-
-#[cfg(target_os = "netbsd")]
-mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "netbsd";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
-}
-
-#[cfg(target_os = "openbsd")]
-mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "openbsd";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
-}
-
-#[cfg(target_os = "android")]
-mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "android";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
-}
-
-#[cfg(target_os = "solaris")]
-mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "solaris";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = "";
-    pub const EXE_EXTENSION: &'static str = "";
-}
-
-#[cfg(target_os = "windows")]
-mod os {
-    pub const FAMILY: &'static str = "windows";
-    pub const OS: &'static str = "windows";
-    pub const DLL_PREFIX: &'static str = "";
-    pub const DLL_SUFFIX: &'static str = ".dll";
-    pub const DLL_EXTENSION: &'static str = "dll";
-    pub const EXE_SUFFIX: &'static str = ".exe";
-    pub const EXE_EXTENSION: &'static str = "exe";
-}
-
-#[cfg(all(target_os = "nacl", not(target_arch = "le32")))]
-mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "nacl";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = ".nexe";
-    pub const EXE_EXTENSION: &'static str = "nexe";
-}
-#[cfg(all(target_os = "nacl", target_arch = "le32"))]
-mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "pnacl";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".pso";
-    pub const DLL_EXTENSION: &'static str = "pso";
-    pub const EXE_SUFFIX: &'static str = ".pexe";
-    pub const EXE_EXTENSION: &'static str = "pexe";
-}
-
-#[cfg(target_os = "emscripten")]
-mod os {
-    pub const FAMILY: &'static str = "unix";
-    pub const OS: &'static str = "emscripten";
-    pub const DLL_PREFIX: &'static str = "lib";
-    pub const DLL_SUFFIX: &'static str = ".so";
-    pub const DLL_EXTENSION: &'static str = "so";
-    pub const EXE_SUFFIX: &'static str = ".js";
-    pub const EXE_EXTENSION: &'static str = "js";
+    pub const EXE_EXTENSION: &'static str = os::EXE_EXTENSION;
 }
 
 #[cfg(target_arch = "x86")]
@@ -958,6 +807,11 @@ mod arch {
     pub const ARCH: &'static str = "asmjs";
 }
 
+#[cfg(target_arch = "wasm32")]
+mod arch {
+    pub const ARCH: &'static str = "wasm32";
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -1006,6 +860,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn test_var_big() {
         let mut s = "".to_string();
         let mut i = 0;
@@ -1019,6 +874,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn test_self_exe_path() {
         let path = current_exe();
         assert!(path.is_ok());
@@ -1029,6 +885,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn test_env_set_get_huge() {
         let n = make_rand_name();
         let s = repeat("x").take(10000).collect::<String>();
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 16290620010..a1909b0f957 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -13,9 +13,9 @@
 //! # The `Error` trait
 //!
 //! `Error` is a trait representing the basic expectations for error values,
-//! i.e. values of type `E` in `Result<T, E>`. At a minimum, errors must provide
+//! i.e. values of type `E` in [`Result<T, E>`]. At a minimum, errors must provide
 //! a description, but they may optionally provide additional detail (via
-//! `Display`) and cause chain information:
+//! [`Display`]) and cause chain information:
 //!
 //! ```
 //! use std::fmt::Display;
@@ -27,12 +27,16 @@
 //! }
 //! ```
 //!
-//! The `cause` method is generally used when errors cross "abstraction
+//! The [`cause`] method is generally used when errors cross "abstraction
 //! boundaries", i.e.  when a one module must report an error that is "caused"
 //! by an error from a lower-level module. This setup makes it possible for the
 //! high-level module to provide its own errors that do not commit to any
 //! particular implementation, but also reveal some of its implementation for
-//! debugging via `cause` chains.
+//! debugging via [`cause`] chains.
+//!
+//! [`Result<T, E>`]: ../result/enum.Result.html
+//! [`Display`]: ../fmt/trait.Display.html
+//! [`cause`]: trait.Error.html#method.cause
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -51,7 +55,6 @@ use any::TypeId;
 use cell;
 use char;
 use fmt::{self, Debug, Display};
-use marker::Reflect;
 use mem::transmute;
 use num;
 use str;
@@ -59,12 +62,14 @@ use string;
 
 /// Base functionality for all errors in Rust.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub trait Error: Debug + Display + Reflect {
+pub trait Error: Debug + Display {
     /// A short description of the error.
     ///
-    /// The description should not contain newlines or sentence-ending
-    /// punctuation, to facilitate embedding in larger user-facing
-    /// strings.
+    /// The description should only be used for a simple message.
+    /// It should not contain newlines or sentence-ending punctuation,
+    /// to facilitate embedding in larger user-facing strings.
+    /// For showing formatted error messages with more information see
+    /// [Display](https://doc.rust-lang.org/std/fmt/trait.Display.html).
     ///
     /// # Examples
     ///
@@ -288,15 +293,15 @@ impl Error for fmt::Error {
     }
 }
 
-#[unstable(feature = "try_borrow", issue = "35070")]
-impl<'a, T: ?Sized + Reflect> Error for cell::BorrowError<'a, T> {
+#[stable(feature = "try_borrow", since = "1.13.0")]
+impl Error for cell::BorrowError {
     fn description(&self) -> &str {
         "already mutably borrowed"
     }
 }
 
-#[unstable(feature = "try_borrow", issue = "35070")]
-impl<'a, T: ?Sized + Reflect> Error for cell::BorrowMutError<'a, T> {
+#[stable(feature = "try_borrow", since = "1.13.0")]
+impl Error for cell::BorrowMutError {
     fn description(&self) -> &str {
         "already borrowed"
     }
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index 1c449712e1f..3ad5b5627d3 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -146,19 +146,19 @@ pub struct CStr {
 
 /// An error returned from `CString::new` to indicate that a nul byte was found
 /// in the vector provided.
-#[derive(Clone, PartialEq, Debug)]
+#[derive(Clone, PartialEq, Eq, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct NulError(usize, Vec<u8>);
 
 /// An error returned from `CStr::from_bytes_with_nul` to indicate that a nul
 /// byte was found too early in the slice provided or one wasn't found at all.
-#[derive(Clone, PartialEq, Debug)]
+#[derive(Clone, PartialEq, Eq, Debug)]
 #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
 pub struct FromBytesWithNulError { _a: () }
 
 /// An error returned from `CString::into_string` to indicate that a UTF-8 error
 /// was encountered during the conversion.
-#[derive(Clone, PartialEq, Debug)]
+#[derive(Clone, PartialEq, Eq, Debug)]
 #[stable(feature = "cstring_into", since = "1.7.0")]
 pub struct IntoStringError {
     inner: CString,
@@ -228,9 +228,14 @@ impl CString {
 
     /// Retakes ownership of a `CString` that was transferred to C.
     ///
+    /// Additionally, the length of the string will be recalculated from the pointer.
+    ///
+    /// # Safety
+    ///
     /// This should only ever be called with a pointer that was earlier
-    /// obtained by calling `into_raw` on a `CString`. Additionally, the length
-    /// of the string will be recalculated from the pointer.
+    /// obtained by calling `into_raw` on a `CString`. Other usage (e.g. trying to take
+    /// ownership of a string that was allocated by foreign code) is likely to lead
+    /// to undefined behavior or allocator corruption.
     #[stable(feature = "cstr_memory", since = "1.4.0")]
     pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
         let len = libc::strlen(ptr) + 1; // Including the NUL byte
@@ -309,9 +314,11 @@ impl CString {
 }
 
 // Turns this `CString` into an empty string to prevent
-// memory unsafe code from working by accident.
+// memory unsafe code from working by accident. Inline
+// to prevent LLVM from optimizing it away in debug builds.
 #[stable(feature = "cstring_drop", since = "1.13.0")]
 impl Drop for CString {
+    #[inline]
     fn drop(&mut self) {
         unsafe { *self.inner.get_unchecked_mut(0) = 0; }
     }
@@ -719,7 +726,8 @@ mod tests {
     use super::*;
     use os::raw::c_char;
     use borrow::Cow::{Borrowed, Owned};
-    use hash::{SipHasher, Hash, Hasher};
+    use hash::{Hash, Hasher};
+    use collections::hash_map::DefaultHasher;
 
     #[test]
     fn c_to_rust() {
@@ -801,10 +809,10 @@ mod tests {
         let ptr = data.as_ptr() as *const c_char;
         let cstr: &'static CStr = unsafe { CStr::from_ptr(ptr) };
 
-        let mut s = SipHasher::new_with_keys(0, 0);
+        let mut s = DefaultHasher::new();
         cstr.hash(&mut s);
         let cstr_hash = s.finish();
-        let mut s = SipHasher::new_with_keys(0, 0);
+        let mut s = DefaultHasher::new();
         CString::new(&data[..data.len() - 1]).unwrap().hash(&mut s);
         let cstring_hash = s.finish();
 
diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs
index d93d3c73622..84b50f04463 100644
--- a/src/libstd/ffi/os_str.rs
+++ b/src/libstd/ffi/os_str.rs
@@ -53,17 +53,6 @@ impl OsString {
         OsString { inner: Buf::from_string(String::new()) }
     }
 
-    #[cfg(unix)]
-    fn _from_bytes(vec: Vec<u8>) -> Option<OsString> {
-        use os::unix::ffi::OsStringExt;
-        Some(OsString::from_vec(vec))
-    }
-
-    #[cfg(windows)]
-    fn _from_bytes(vec: Vec<u8>) -> Option<OsString> {
-        String::from_utf8(vec).ok().map(OsString::from)
-    }
-
     /// Converts to an `OsStr` slice.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn as_os_str(&self) -> &OsStr {
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index 698ec4f1b73..df5741d00a2 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -83,6 +83,7 @@ pub struct Metadata(fs_imp::FileAttr);
 ///
 /// [`io::Result`]: ../io/type.Result.html
 #[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Debug)]
 pub struct ReadDir(fs_imp::ReadDir);
 
 /// Entries returned by the [`ReadDir`] iterator.
@@ -1055,6 +1056,15 @@ impl DirEntry {
     }
 }
 
+#[stable(feature = "dir_entry_debug", since = "1.13.0")]
+impl fmt::Debug for DirEntry {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_tuple("DirEntry")
+            .field(&self.path())
+            .finish()
+    }
+}
+
 impl AsInner<fs_imp::DirEntry> for DirEntry {
     fn as_inner(&self) -> &fs_imp::DirEntry { &self.0 }
 }
@@ -1677,7 +1687,7 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use io::prelude::*;
 
@@ -1895,6 +1905,130 @@ mod tests {
     }
 
     #[test]
+    fn file_test_io_eof() {
+        let tmpdir = tmpdir();
+        let filename = tmpdir.join("file_rt_io_file_test_eof.txt");
+        let mut buf = [0; 256];
+        {
+            let oo = OpenOptions::new().create_new(true).write(true).read(true).clone();
+            let mut rw = check!(oo.open(&filename));
+            assert_eq!(check!(rw.read(&mut buf)), 0);
+            assert_eq!(check!(rw.read(&mut buf)), 0);
+        }
+        check!(fs::remove_file(&filename));
+    }
+
+    #[test]
+    #[cfg(unix)]
+    fn file_test_io_read_write_at() {
+        use os::unix::fs::FileExt;
+
+        let tmpdir = tmpdir();
+        let filename = tmpdir.join("file_rt_io_file_test_read_write_at.txt");
+        let mut buf = [0; 256];
+        let write1 = "asdf";
+        let write2 = "qwer-";
+        let write3 = "-zxcv";
+        let content = "qwer-asdf-zxcv";
+        {
+            let oo = OpenOptions::new().create_new(true).write(true).read(true).clone();
+            let mut rw = check!(oo.open(&filename));
+            assert_eq!(check!(rw.write_at(write1.as_bytes(), 5)), write1.len());
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 0);
+            assert_eq!(check!(rw.read_at(&mut buf, 5)), write1.len());
+            assert_eq!(str::from_utf8(&buf[..write1.len()]), Ok(write1));
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 0);
+            assert_eq!(check!(rw.read_at(&mut buf[..write2.len()], 0)), write2.len());
+            assert_eq!(str::from_utf8(&buf[..write2.len()]), Ok("\0\0\0\0\0"));
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 0);
+            assert_eq!(check!(rw.write(write2.as_bytes())), write2.len());
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 5);
+            assert_eq!(check!(rw.read(&mut buf)), write1.len());
+            assert_eq!(str::from_utf8(&buf[..write1.len()]), Ok(write1));
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 9);
+            assert_eq!(check!(rw.read_at(&mut buf[..write2.len()], 0)), write2.len());
+            assert_eq!(str::from_utf8(&buf[..write2.len()]), Ok(write2));
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 9);
+            assert_eq!(check!(rw.write_at(write3.as_bytes(), 9)), write3.len());
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 9);
+        }
+        {
+            let mut read = check!(File::open(&filename));
+            assert_eq!(check!(read.read_at(&mut buf, 0)), content.len());
+            assert_eq!(str::from_utf8(&buf[..content.len()]), Ok(content));
+            assert_eq!(check!(read.seek(SeekFrom::Current(0))), 0);
+            assert_eq!(check!(read.seek(SeekFrom::End(-5))), 9);
+            assert_eq!(check!(read.read_at(&mut buf, 0)), content.len());
+            assert_eq!(str::from_utf8(&buf[..content.len()]), Ok(content));
+            assert_eq!(check!(read.seek(SeekFrom::Current(0))), 9);
+            assert_eq!(check!(read.read(&mut buf)), write3.len());
+            assert_eq!(str::from_utf8(&buf[..write3.len()]), Ok(write3));
+            assert_eq!(check!(read.seek(SeekFrom::Current(0))), 14);
+            assert_eq!(check!(read.read_at(&mut buf, 0)), content.len());
+            assert_eq!(str::from_utf8(&buf[..content.len()]), Ok(content));
+            assert_eq!(check!(read.seek(SeekFrom::Current(0))), 14);
+            assert_eq!(check!(read.read_at(&mut buf, 14)), 0);
+            assert_eq!(check!(read.read_at(&mut buf, 15)), 0);
+            assert_eq!(check!(read.seek(SeekFrom::Current(0))), 14);
+        }
+        check!(fs::remove_file(&filename));
+    }
+
+    #[test]
+    #[cfg(windows)]
+    fn file_test_io_seek_read_write() {
+        use os::windows::fs::FileExt;
+
+        let tmpdir = tmpdir();
+        let filename = tmpdir.join("file_rt_io_file_test_seek_read_write.txt");
+        let mut buf = [0; 256];
+        let write1 = "asdf";
+        let write2 = "qwer-";
+        let write3 = "-zxcv";
+        let content = "qwer-asdf-zxcv";
+        {
+            let oo = OpenOptions::new().create_new(true).write(true).read(true).clone();
+            let mut rw = check!(oo.open(&filename));
+            assert_eq!(check!(rw.seek_write(write1.as_bytes(), 5)), write1.len());
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 9);
+            assert_eq!(check!(rw.seek_read(&mut buf, 5)), write1.len());
+            assert_eq!(str::from_utf8(&buf[..write1.len()]), Ok(write1));
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 9);
+            assert_eq!(check!(rw.seek(SeekFrom::Start(0))), 0);
+            assert_eq!(check!(rw.write(write2.as_bytes())), write2.len());
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 5);
+            assert_eq!(check!(rw.read(&mut buf)), write1.len());
+            assert_eq!(str::from_utf8(&buf[..write1.len()]), Ok(write1));
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 9);
+            assert_eq!(check!(rw.seek_read(&mut buf[..write2.len()], 0)), write2.len());
+            assert_eq!(str::from_utf8(&buf[..write2.len()]), Ok(write2));
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 5);
+            assert_eq!(check!(rw.seek_write(write3.as_bytes(), 9)), write3.len());
+            assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 14);
+        }
+        {
+            let mut read = check!(File::open(&filename));
+            assert_eq!(check!(read.seek_read(&mut buf, 0)), content.len());
+            assert_eq!(str::from_utf8(&buf[..content.len()]), Ok(content));
+            assert_eq!(check!(read.seek(SeekFrom::Current(0))), 14);
+            assert_eq!(check!(read.seek(SeekFrom::End(-5))), 9);
+            assert_eq!(check!(read.seek_read(&mut buf, 0)), content.len());
+            assert_eq!(str::from_utf8(&buf[..content.len()]), Ok(content));
+            assert_eq!(check!(read.seek(SeekFrom::Current(0))), 14);
+            assert_eq!(check!(read.seek(SeekFrom::End(-5))), 9);
+            assert_eq!(check!(read.read(&mut buf)), write3.len());
+            assert_eq!(str::from_utf8(&buf[..write3.len()]), Ok(write3));
+            assert_eq!(check!(read.seek(SeekFrom::Current(0))), 14);
+            assert_eq!(check!(read.seek_read(&mut buf, 0)), content.len());
+            assert_eq!(str::from_utf8(&buf[..content.len()]), Ok(content));
+            assert_eq!(check!(read.seek(SeekFrom::Current(0))), 14);
+            assert_eq!(check!(read.seek_read(&mut buf, 14)), 0);
+            assert_eq!(check!(read.seek_read(&mut buf, 15)), 0);
+        }
+        check!(fs::remove_file(&filename));
+    }
+
+    #[test]
     fn file_test_stat_is_correct_on_is_file() {
         let tmpdir = tmpdir();
         let filename = &tmpdir.join("file_stat_correct_on_is_file.txt");
@@ -2212,8 +2346,8 @@ mod tests {
         check!(fs::set_permissions(&out, attr.permissions()));
     }
 
-    #[cfg(windows)]
     #[test]
+    #[cfg(windows)]
     fn copy_file_preserves_streams() {
         let tmp = tmpdir();
         check!(check!(File::create(tmp.join("in.txt:bunny"))).write("carrot".as_bytes()));
@@ -2642,6 +2776,17 @@ mod tests {
     }
 
     #[test]
+    fn dir_entry_debug() {
+        let tmpdir = tmpdir();
+        File::create(&tmpdir.join("b")).unwrap();
+        let mut read_dir = tmpdir.path().read_dir().unwrap();
+        let dir_entry = read_dir.next().unwrap().unwrap();
+        let actual = format!("{:?}", dir_entry);
+        let expected = format!("DirEntry({:?})", dir_entry.0.path());
+        assert_eq!(actual, expected);
+    }
+
+    #[test]
     fn read_dir_not_found() {
         let res = fs::read_dir("/path/that/does/not/exist");
         assert_eq!(res.err().unwrap().kind(), ErrorKind::NotFound);
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index dbb45d54f38..44dd4e9874a 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -12,7 +12,6 @@
 
 use io::prelude::*;
 
-use marker::Reflect;
 use cmp;
 use error;
 use fmt;
@@ -21,11 +20,15 @@ use memchr;
 
 /// The `BufReader` struct adds buffering to any reader.
 ///
-/// It can be excessively inefficient to work directly with a `Read` instance.
-/// For example, every call to `read` on `TcpStream` results in a system call.
-/// A `BufReader` performs large, infrequent reads on the underlying `Read`
+/// It can be excessively inefficient to work directly with a [`Read`] instance.
+/// For example, every call to [`read`] on [`TcpStream`] results in a system call.
+/// A `BufReader` performs large, infrequent reads on the underlying [`Read`]
 /// and maintains an in-memory buffer of the results.
 ///
+/// [`Read`]: ../../std/io/trait.Read.html
+/// [`read`]: ../../std/net/struct.TcpStream.html#method.read
+/// [`TcpStream`]: ../../std/net/struct.TcpStream.html
+///
 /// # Examples
 ///
 /// ```
@@ -216,8 +219,8 @@ impl<R: Seek> Seek for BufReader<R> {
     ///
     /// Seeking always discards the internal buffer, even if the seek position
     /// would otherwise fall within it. This guarantees that calling
-    /// `.unwrap()` immediately after a seek yields the underlying reader at
-    /// the same position.
+    /// `.into_inner()` immediately after a seek yields the underlying reader
+    /// at the same position.
     ///
     /// See `std::io::Seek` for more details.
     ///
@@ -231,7 +234,7 @@ impl<R: Seek> Seek for BufReader<R> {
         if let SeekFrom::Current(n) = pos {
             let remainder = (self.cap - self.pos) as i64;
             // it should be safe to assume that remainder fits within an i64 as the alternative
-            // means we managed to allocate 8 ebibytes and that's absurd.
+            // means we managed to allocate 8 exbibytes and that's absurd.
             // But it's not out of the realm of possibility for some weird underlying reader to
             // support seeking by i64::min_value() so we need to handle underflow when subtracting
             // remainder.
@@ -255,7 +258,7 @@ impl<R: Seek> Seek for BufReader<R> {
 /// Wraps a writer and buffers its output.
 ///
 /// It can be excessively inefficient to work directly with something that
-/// implements `Write`. For example, every call to `write` on `TcpStream`
+/// implements [`Write`]. For example, every call to [`write`] on [`TcpStream`]
 /// results in a system call. A `BufWriter` keeps an in-memory buffer of data
 /// and writes it to an underlying writer in large, infrequent batches.
 ///
@@ -263,7 +266,7 @@ impl<R: Seek> Seek for BufReader<R> {
 ///
 /// # Examples
 ///
-/// Let's write the numbers one through ten to a `TcpStream`:
+/// Let's write the numbers one through ten to a [`TcpStream`]:
 ///
 /// ```no_run
 /// use std::io::prelude::*;
@@ -295,6 +298,10 @@ impl<R: Seek> Seek for BufReader<R> {
 /// By wrapping the stream with a `BufWriter`, these ten writes are all grouped
 /// together by the buffer, and will all be written out in one system call when
 /// the `stream` is dropped.
+///
+/// [`Write`]: ../../std/io/trait.Write.html
+/// [`write`]: ../../std/net/struct.TcpStream.html#method.write
+/// [`TcpStream`]: ../../std/net/struct.TcpStream.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct BufWriter<W: Write> {
     inner: Option<W>,
@@ -578,7 +585,7 @@ impl<W> From<IntoInnerError<W>> for Error {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<W: Reflect + Send + fmt::Debug> error::Error for IntoInnerError<W> {
+impl<W: Send + fmt::Debug> error::Error for IntoInnerError<W> {
     fn description(&self) -> &str {
         error::Error::description(self.error())
     }
@@ -1107,6 +1114,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn panic_in_write_doesnt_flush_in_drop() {
         static WRITES: AtomicUsize = AtomicUsize::new(0);
 
diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs
index 1b836b74537..cb9e7bd3270 100644
--- a/src/libstd/io/cursor.rs
+++ b/src/libstd/io/cursor.rs
@@ -10,26 +10,33 @@
 
 use io::prelude::*;
 
+use core::convert::TryInto;
 use cmp;
 use io::{self, SeekFrom, Error, ErrorKind};
 
 /// A `Cursor` wraps another type and provides it with a
-/// [`Seek`](trait.Seek.html) implementation.
+/// [`Seek`] implementation.
 ///
-/// Cursors are typically used with in-memory buffers to allow them to
-/// implement `Read` and/or `Write`, allowing these buffers to be used
+/// `Cursor`s are typically used with in-memory buffers to allow them to
+/// implement [`Read`] and/or [`Write`], allowing these buffers to be used
 /// anywhere you might use a reader or writer that does actual I/O.
 ///
 /// The standard library implements some I/O traits on various types which
-/// are commonly used as a buffer, like `Cursor<Vec<u8>>` and `Cursor<&[u8]>`.
+/// are commonly used as a buffer, like `Cursor<`[`Vec`]`<u8>>` and
+/// `Cursor<`[`&[u8]`]`>`.
 ///
 /// # Examples
 ///
-/// We may want to write bytes to a [`File`][file] in our production
+/// We may want to write bytes to a [`File`] in our production
 /// code, but use an in-memory buffer in our tests. We can do this with
 /// `Cursor`:
 ///
-/// [file]: ../fs/struct.File.html
+/// [`Seek`]: trait.Seek.html
+/// [`Read`]: ../../std/io/trait.Read.html
+/// [`Write`]: ../../std/io/trait.Write.html
+/// [`Vec`]: ../../std/vec/struct.Vec.html
+/// [`&[u8]`]: ../../std/primitive.slice.html
+/// [`File`]: ../fs/struct.File.html
 ///
 /// ```no_run
 /// use std::io::prelude::*;
@@ -242,18 +249,20 @@ impl<'a> Write for Cursor<&'a mut [u8]> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Write for Cursor<Vec<u8>> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        let pos: usize = self.position().try_into().map_err(|_| {
+            Error::new(ErrorKind::InvalidInput,
+                       "cursor position exceeds maximum possible vector length")
+        })?;
         // Make sure the internal buffer is as least as big as where we
         // currently are
-        let pos = self.position();
-        let amt = pos.saturating_sub(self.inner.len() as u64);
-        // use `resize` so that the zero filling is as efficient as possible
         let len = self.inner.len();
-        self.inner.resize(len + amt as usize, 0);
-
+        if len < pos {
+            // use `resize` so that the zero filling is as efficient as possible
+            self.inner.resize(pos, 0);
+        }
         // Figure out what bytes will be used to overwrite what's currently
         // there (left), and what will be appended on the end (right)
         {
-            let pos = pos as usize;
             let space = self.inner.len() - pos;
             let (left, right) = buf.split_at(cmp::min(space, buf.len()));
             self.inner[pos..pos + left.len()].copy_from_slice(left);
@@ -261,7 +270,7 @@ impl Write for Cursor<Vec<u8>> {
         }
 
         // Bump us forward
-        self.set_position(pos + buf.len() as u64);
+        self.set_position((pos + buf.len()) as u64);
         Ok(buf.len())
     }
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
@@ -383,7 +392,7 @@ mod tests {
 
     #[test]
     fn test_mem_reader() {
-        let mut reader = Cursor::new(vec!(0, 1, 2, 3, 4, 5, 6, 7));
+        let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7]);
         let mut buf = [];
         assert_eq!(reader.read(&mut buf).unwrap(), 0);
         assert_eq!(reader.position(), 0);
@@ -405,7 +414,7 @@ mod tests {
 
     #[test]
     fn test_boxed_slice_reader() {
-        let mut reader = Cursor::new(vec!(0, 1, 2, 3, 4, 5, 6, 7).into_boxed_slice());
+        let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7].into_boxed_slice());
         let mut buf = [];
         assert_eq!(reader.read(&mut buf).unwrap(), 0);
         assert_eq!(reader.position(), 0);
@@ -427,7 +436,7 @@ mod tests {
 
     #[test]
     fn read_to_end() {
-        let mut reader = Cursor::new(vec!(0, 1, 2, 3, 4, 5, 6, 7));
+        let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7]);
         let mut v = Vec::new();
         reader.read_to_end(&mut v).unwrap();
         assert_eq!(v, [0, 1, 2, 3, 4, 5, 6, 7]);
@@ -503,7 +512,7 @@ mod tests {
         assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
         assert_eq!(r.read(&mut [0]).unwrap(), 0);
 
-        let mut r = Cursor::new(vec!(10));
+        let mut r = Cursor::new(vec![10]);
         assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
         assert_eq!(r.read(&mut [0]).unwrap(), 0);
 
@@ -523,14 +532,14 @@ mod tests {
         let mut r = Cursor::new(&buf[..]);
         assert!(r.seek(SeekFrom::End(-2)).is_err());
 
-        let mut r = Cursor::new(vec!(10));
+        let mut r = Cursor::new(vec![10]);
         assert!(r.seek(SeekFrom::End(-2)).is_err());
 
         let mut buf = [0];
         let mut r = Cursor::new(&mut buf[..]);
         assert!(r.seek(SeekFrom::End(-2)).is_err());
 
-        let mut r = Cursor::new(vec!(10).into_boxed_slice());
+        let mut r = Cursor::new(vec![10].into_boxed_slice());
         assert!(r.seek(SeekFrom::End(-2)).is_err());
     }
 
@@ -580,4 +589,12 @@ mod tests {
         let mut r = Cursor::new(Vec::new());
         assert!(r.seek(SeekFrom::End(-2)).is_err());
     }
+
+    #[test]
+    #[cfg(target_pointer_width = "32")]
+    fn vec_seek_and_write_past_usize_max() {
+        let mut c = Cursor::new(Vec::new());
+        c.set_position(<usize>::max_value() as u64 + 1);
+        assert!(c.write_all(&[1, 2, 3]).is_err());
+    }
 }
diff --git a/src/libstd/io/impls.rs b/src/libstd/io/impls.rs
index cd05e6b5de9..6b26c016638 100644
--- a/src/libstd/io/impls.rs
+++ b/src/libstd/io/impls.rs
@@ -147,6 +147,10 @@ impl<B: BufRead + ?Sized> BufRead for Box<B> {
 // =============================================================================
 // In-memory buffer implementations
 
+/// Read is implemented for `&[u8]` by copying from the slice.
+///
+/// Note that reading updates the slice to point to the yet unread part.
+/// The slice will be empty when EOF is reached.
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Read for &'a [u8] {
     #[inline]
@@ -180,6 +184,11 @@ impl<'a> BufRead for &'a [u8] {
     fn consume(&mut self, amt: usize) { *self = &self[amt..]; }
 }
 
+/// Write is implemented for `&mut [u8]` by copying into the slice, overwriting
+/// its data.
+///
+/// Note that writing updates the slice to point to the yet unwritten part.
+/// The slice will be empty when it has been completely overwritten.
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Write for &'a mut [u8] {
     #[inline]
@@ -204,6 +213,8 @@ impl<'a> Write for &'a mut [u8] {
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
 }
 
+/// Write is implemented for `Vec<u8>` by appending to the vector.
+/// The vector will grow as needed.
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Write for Vec<u8> {
     #[inline]
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 06609cfad15..37c3f70d54d 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -12,18 +12,15 @@
 //!
 //! The `std::io` module contains a number of common things you'll need
 //! when doing input and output. The most core part of this module is
-//! the [`Read`][read] and [`Write`][write] traits, which provide the
+//! the [`Read`] and [`Write`] traits, which provide the
 //! most general interface for reading and writing input and output.
 //!
-//! [read]: trait.Read.html
-//! [write]: trait.Write.html
-//!
 //! # Read and Write
 //!
-//! Because they are traits, `Read` and `Write` are implemented by a number
+//! Because they are traits, [`Read`] and [`Write`] are implemented by a number
 //! of other types, and you can implement them for your types too. As such,
 //! you'll see a few different types of I/O throughout the documentation in
-//! this module: `File`s, `TcpStream`s, and sometimes even `Vec<T>`s. For
+//! this module: [`File`]s, [`TcpStream`]s, and sometimes even [`Vec<T>`]s. For
 //! example, `Read` adds a `read()` method, which we can use on `File`s:
 //!
 //! ```
@@ -43,15 +40,15 @@
 //! # }
 //! ```
 //!
-//! `Read` and `Write` are so important, implementors of the two traits have a
+//! [`Read`] and [`Write`] are so important, implementors of the two traits have a
 //! nickname: readers and writers. So you'll sometimes see 'a reader' instead
-//! of 'a type that implements the `Read` trait'. Much easier!
+//! of 'a type that implements the [`Read`] trait'. Much easier!
 //!
 //! ## Seek and BufRead
 //!
-//! Beyond that, there are two important traits that are provided: [`Seek`][seek]
-//! and [`BufRead`][bufread]. Both of these build on top of a reader to control
-//! how the reading happens. `Seek` lets you control where the next byte is
+//! Beyond that, there are two important traits that are provided: [`Seek`]
+//! and [`BufRead`]. Both of these build on top of a reader to control
+//! how the reading happens. [`Seek`] lets you control where the next byte is
 //! coming from:
 //!
 //! ```
@@ -75,21 +72,18 @@
 //! # }
 //! ```
 //!
-//! [seek]: trait.Seek.html
-//! [bufread]: trait.BufRead.html
-//!
-//! `BufRead` uses an internal buffer to provide a number of other ways to read, but
+//! [`BufRead`] uses an internal buffer to provide a number of other ways to read, but
 //! to show it off, we'll need to talk about buffers in general. Keep reading!
 //!
 //! ## BufReader and BufWriter
 //!
 //! Byte-based interfaces are unwieldy and can be inefficient, as we'd need to be
 //! making near-constant calls to the operating system. To help with this,
-//! `std::io` comes with two structs, `BufReader` and `BufWriter`, which wrap
+//! `std::io` comes with two structs, [`BufReader`] and [`BufWriter`], which wrap
 //! readers and writers. The wrapper uses a buffer, reducing the number of
 //! calls and providing nicer methods for accessing exactly what you want.
 //!
-//! For example, `BufReader` works with the `BufRead` trait to add extra
+//! For example, [`BufReader`] works with the [`BufRead`] trait to add extra
 //! methods to any reader:
 //!
 //! ```
@@ -111,8 +105,8 @@
 //! # }
 //! ```
 //!
-//! `BufWriter` doesn't add any new ways of writing; it just buffers every call
-//! to [`write()`][write()]:
+//! [`BufWriter`] doesn't add any new ways of writing; it just buffers every call
+//! to [`write()`]:
 //!
 //! ```
 //! use std::io;
@@ -134,8 +128,6 @@
 //! # }
 //! ```
 //!
-//! [write()]: trait.Write.html#tymethod.write
-//!
 //! ## Standard input and output
 //!
 //! A very common source of input is standard input:
@@ -165,13 +157,13 @@
 //! # }
 //! ```
 //!
-//! Of course, using `io::stdout()` directly is less common than something like
-//! `println!`.
+//! Of course, using [`io::stdout()`] directly is less common than something like
+//! [`println!`].
 //!
 //! ## Iterator types
 //!
 //! A large number of the structures provided by `std::io` are for various
-//! ways of iterating over I/O. For example, `Lines` is used to split over
+//! ways of iterating over I/O. For example, [`Lines`] is used to split over
 //! lines:
 //!
 //! ```
@@ -211,10 +203,10 @@
 //!
 //! ## io::Result
 //!
-//! Last, but certainly not least, is [`io::Result`][result]. This type is used
+//! Last, but certainly not least, is [`io::Result`]. This type is used
 //! as the return type of many `std::io` functions that can cause an error, and
 //! can be returned from your own functions as well. Many of the examples in this
-//! module use the [`try!`][try] macro:
+//! module use the [`try!`] macro:
 //!
 //! ```
 //! use std::io;
@@ -230,14 +222,11 @@
 //! }
 //! ```
 //!
-//! The return type of `read_input()`, `io::Result<()>`, is a very common type
-//! for functions which don't have a 'real' return value, but do want to return
-//! errors if they happen. In this case, the only purpose of this function is
+//! The return type of `read_input()`, [`io::Result<()>`][`io::Result`], is a very
+//! common type for functions which don't have a 'real' return value, but do want to
+//! return errors if they happen. In this case, the only purpose of this function is
 //! to read the line and print it, so we use `()`.
 //!
-//! [result]: type.Result.html
-//! [try]: ../macro.try.html
-//!
 //! ## Platform-specific behavior
 //!
 //! Many I/O functions throughout the standard library are documented to indicate
@@ -246,6 +235,22 @@
 //! any possibly unclear semantics. Note, however, that this is informative, not a binding
 //! contract. The implementation of many of these functions are subject to change over
 //! time and may call fewer or more syscalls/library functions.
+//!
+//! [`Read`]: trait.Read.html
+//! [`Write`]: trait.Write.html
+//! [`Seek`]: trait.Seek.html
+//! [`BufRead`]: trait.BufRead.html
+//! [`File`]: ../fs/struct.File.html
+//! [`TcpStream`]: ../net/struct.TcpStream.html
+//! [`Vec<T>`]: ../vec/struct.Vec.html
+//! [`BufReader`]: struct.BufReader.html
+//! [`BufWriter`]: struct.BufWriter.html
+//! [`write()`]: trait.Write.html#tymethod.write
+//! [`io::stdout()`]: fn.stdout.html
+//! [`println!`]: ../macro.println.html
+//! [`Lines`]: struct.Lines.html
+//! [`io::Result`]: type.Result.html
+//! [`try!`]: ../macro.try.html
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -1149,10 +1154,7 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>)
 ///
 /// For example, reading line-by-line is inefficient without using a buffer, so
 /// if you want to read by line, you'll need `BufRead`, which includes a
-/// [`read_line()`][readline] method as well as a [`lines()`][lines] iterator.
-///
-/// [readline]: #method.read_line
-/// [lines]: #method.lines
+/// [`read_line()`] method as well as a [`lines()`] iterator.
 ///
 /// # Examples
 ///
@@ -1168,14 +1170,17 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>)
 /// }
 /// ```
 ///
-/// If you have something that implements `Read`, you can use the [`BufReader`
-/// type][bufreader] to turn it into a `BufRead`.
+/// If you have something that implements [`Read`], you can use the [`BufReader`
+/// type][`BufReader`] to turn it into a `BufRead`.
 ///
-/// For example, [`File`][file] implements `Read`, but not `BufRead`.
-/// `BufReader` to the rescue!
+/// For example, [`File`] implements [`Read`], but not `BufRead`.
+/// [`BufReader`] to the rescue!
 ///
-/// [bufreader]: struct.BufReader.html
-/// [file]: ../fs/struct.File.html
+/// [`BufReader`]: struct.BufReader.html
+/// [`File`]: ../fs/struct.File.html
+/// [`read_line()`]: #method.read_line
+/// [`lines()`]: #method.lines
+/// [`Read`]: trait.Read.html
 ///
 /// ```
 /// use std::io::{self, BufReader};
@@ -1199,13 +1204,13 @@ pub trait BufRead: Read {
     /// Fills the internal buffer of this object, returning the buffer contents.
     ///
     /// This function is a lower-level call. It needs to be paired with the
-    /// [`consume`][consume] method to function properly. When calling this
+    /// [`consume()`] method to function properly. When calling this
     /// method, none of the contents will be "read" in the sense that later
-    /// calling `read` may return the same contents. As such, `consume` must be
-    /// called with the number of bytes that are consumed from this buffer to
+    /// calling `read` may return the same contents. As such, [`consume()`] must
+    /// be called with the number of bytes that are consumed from this buffer to
     /// ensure that the bytes are never returned twice.
     ///
-    /// [consume]: #tymethod.consume
+    /// [`consume()`]: #tymethod.consume
     ///
     /// An empty buffer returned indicates that the stream has reached EOF.
     ///
@@ -1246,38 +1251,36 @@ pub trait BufRead: Read {
     /// so they should no longer be returned in calls to `read`.
     ///
     /// This function is a lower-level call. It needs to be paired with the
-    /// [`fill_buf`][fillbuf] method to function properly. This function does
+    /// [`fill_buf()`] method to function properly. This function does
     /// not perform any I/O, it simply informs this object that some amount of
-    /// its buffer, returned from `fill_buf`, has been consumed and should no
-    /// longer be returned. As such, this function may do odd things if
-    /// `fill_buf` isn't called before calling it.
-    ///
-    /// [fillbuf]: #tymethod.fill_buf
+    /// its buffer, returned from [`fill_buf()`], has been consumed and should
+    /// no longer be returned. As such, this function may do odd things if
+    /// [`fill_buf()`] isn't called before calling it.
     ///
     /// The `amt` must be `<=` the number of bytes in the buffer returned by
-    /// `fill_buf`.
+    /// [`fill_buf()`].
     ///
     /// # Examples
     ///
-    /// Since `consume()` is meant to be used with [`fill_buf()`][fillbuf],
+    /// Since `consume()` is meant to be used with [`fill_buf()`],
     /// that method's example includes an example of `consume()`.
+    ///
+    /// [`fill_buf()`]: #tymethod.fill_buf
     #[stable(feature = "rust1", since = "1.0.0")]
     fn consume(&mut self, amt: usize);
 
-    /// Read all bytes into `buf` until the delimiter `byte` is reached.
+    /// Read all bytes into `buf` until the delimiter `byte` or EOF is reached.
     ///
     /// This function will read bytes from the underlying stream until the
     /// delimiter or EOF is found. Once found, all bytes up to, and including,
     /// the delimiter (if found) will be appended to `buf`.
     ///
-    /// If this reader is currently at EOF then this function will not modify
-    /// `buf` and will return `Ok(n)` where `n` is the number of bytes which
-    /// were read.
+    /// If successful, this function will return the total number of bytes read.
     ///
     /// # Errors
     ///
-    /// This function will ignore all instances of `ErrorKind::Interrupted` and
-    /// will otherwise return any errors returned by `fill_buf`.
+    /// This function will ignore all instances of [`ErrorKind::Interrupted`] and
+    /// will otherwise return any errors returned by [`fill_buf()`].
     ///
     /// If an I/O error is encountered then all bytes read so far will be
     /// present in `buf` and its length will have been adjusted appropriately.
@@ -1287,6 +1290,9 @@ pub trait BufRead: Read {
     /// A locked standard input implements `BufRead`. In this example, we'll
     /// read from standard input until we see an `a` byte.
     ///
+    /// [`fill_buf()`]: #tymethod.fill_buf
+    /// [`ErrorKind::Interrupted`]: enum.ErrorKind.html#variant.Interrupted
+    ///
     /// ```
     /// use std::io;
     /// use std::io::prelude::*;
@@ -1315,25 +1321,24 @@ pub trait BufRead: Read {
     /// up to, and including, the delimiter (if found) will be appended to
     /// `buf`.
     ///
-    /// If this reader is currently at EOF then this function will not modify
-    /// `buf` and will return `Ok(n)` where `n` is the number of bytes which
-    /// were read.
+    /// If successful, this function will return the total number of bytes read.
     ///
     /// # Errors
     ///
-    /// This function has the same error semantics as `read_until` and will also
-    /// return an error if the read bytes are not valid UTF-8. If an I/O error
-    /// is encountered then `buf` may contain some bytes already read in the
-    /// event that all data read so far was valid UTF-8.
+    /// This function has the same error semantics as [`read_until()`] and will
+    /// also return an error if the read bytes are not valid UTF-8. If an I/O
+    /// error is encountered then `buf` may contain some bytes already read in
+    /// the event that all data read so far was valid UTF-8.
     ///
     /// # Examples
     ///
     /// A locked standard input implements `BufRead`. In this example, we'll
     /// read all of the lines from standard input. If we were to do this in
-    /// an actual project, the [`lines()`][lines] method would be easier, of
+    /// an actual project, the [`lines()`] method would be easier, of
     /// course.
     ///
-    /// [lines]: #method.lines
+    /// [`lines()`]: #method.lines
+    /// [`read_until()`]: #method.read_until
     ///
     /// ```
     /// use std::io;
@@ -1362,17 +1367,21 @@ pub trait BufRead: Read {
     /// `byte`.
     ///
     /// The iterator returned from this function will return instances of
-    /// `io::Result<Vec<u8>>`. Each vector returned will *not* have the
-    /// delimiter byte at the end.
+    /// [`io::Result`]`<`[`Vec<u8>`]`>`. Each vector returned will *not* have
+    /// the delimiter byte at the end.
     ///
-    /// This function will yield errors whenever `read_until` would have also
-    /// yielded an error.
+    /// This function will yield errors whenever [`read_until()`] would have
+    /// also yielded an error.
     ///
     /// # Examples
     ///
     /// A locked standard input implements `BufRead`. In this example, we'll
     /// read some input from standard input, splitting on commas.
     ///
+    /// [`io::Result`]: type.Result.html
+    /// [`Vec<u8>`]: ../vec/struct.Vec.html
+    /// [`read_until()`]: #method.read_until
+    ///
     /// ```
     /// use std::io;
     /// use std::io::prelude::*;
@@ -1391,9 +1400,12 @@ pub trait BufRead: Read {
     /// Returns an iterator over the lines of this reader.
     ///
     /// The iterator returned from this function will yield instances of
-    /// `io::Result<String>`. Each string returned will *not* have a newline
+    /// [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline
     /// byte (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end.
     ///
+    /// [`io::Result`]: type.Result.html
+    /// [`String`]: ../string/struct.String.html
+    ///
     /// # Examples
     ///
     /// A locked standard input implements `BufRead`:
@@ -1416,10 +1428,10 @@ pub trait BufRead: Read {
 
 /// Adaptor to chain together two readers.
 ///
-/// This struct is generally created by calling [`chain()`][chain] on a reader.
-/// Please see the documentation of `chain()` for more details.
+/// This struct is generally created by calling [`chain()`] on a reader.
+/// Please see the documentation of [`chain()`] for more details.
 ///
-/// [chain]: trait.Read.html#method.chain
+/// [`chain()`]: trait.Read.html#method.chain
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Chain<T, U> {
     first: T,
@@ -1432,7 +1444,7 @@ impl<T: Read, U: Read> Read for Chain<T, U> {
     fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
         if !self.done_first {
             match self.first.read(buf)? {
-                0 => { self.done_first = true; }
+                0 if buf.len() != 0 => { self.done_first = true; }
                 n => return Ok(n),
             }
         }
@@ -1524,7 +1536,7 @@ impl<T> Take<T> {
     /// # Ok(())
     /// # }
     /// ```
-    #[unstable(feature = "io_take_into_inner", issue = "0")]
+    #[unstable(feature = "io_take_into_inner", issue = "23755")]
     pub fn into_inner(self) -> T {
         self.inner
     }
@@ -1580,10 +1592,10 @@ fn read_one_byte(reader: &mut Read) -> Option<Result<u8>> {
 
 /// An iterator over `u8` values of a reader.
 ///
-/// This struct is generally created by calling [`bytes()`][bytes] on a reader.
-/// Please see the documentation of `bytes()` for more details.
+/// This struct is generally created by calling [`bytes()`] on a reader.
+/// Please see the documentation of [`bytes()`] for more details.
 ///
-/// [bytes]: trait.Read.html#method.bytes
+/// [`bytes()`]: trait.Read.html#method.bytes
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Bytes<R> {
     inner: R,
@@ -1761,6 +1773,7 @@ mod tests {
     use super::repeat;
 
     #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn read_until() {
         let mut buf = Cursor::new(&b"12"[..]);
         let mut v = Vec::new();
@@ -1959,7 +1972,19 @@ mod tests {
         cmp_bufread(chain1, chain2, &testdata[..]);
     }
 
+    #[test]
+    fn chain_zero_length_read_is_not_eof() {
+        let a = b"A";
+        let b = b"B";
+        let mut s = String::new();
+        let mut chain = (&a[..]).chain(&b[..]);
+        chain.read(&mut []).unwrap();
+        chain.read_to_string(&mut s).unwrap();
+        assert_eq!("AB", s);
+    }
+
     #[bench]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn bench_read_to_end(b: &mut test::Bencher) {
         b.iter(|| {
             let mut lr = repeat(1).take(10000000);
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index 9a782e95f6e..c24ee8ff303 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -125,13 +125,10 @@ impl<R: io::Read> io::Read for Maybe<R> {
 }
 
 fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
-    #[cfg(windows)]
-    const ERR: i32 = ::sys::c::ERROR_INVALID_HANDLE as i32;
-    #[cfg(not(windows))]
-    const ERR: i32 = ::libc::EBADF as i32;
+    use sys::stdio::EBADF_ERR;
 
     match r {
-        Err(ref e) if e.raw_os_error() == Some(ERR) => Ok(default),
+        Err(ref e) if e.raw_os_error() == Some(EBADF_ERR) => Ok(default),
         r => r
     }
 }
@@ -593,11 +590,11 @@ impl<'a> Write for StderrLock<'a> {
                      with a more general mechanism",
            issue = "0")]
 #[doc(hidden)]
-pub fn set_panic(sink: Box<Write + Send>) -> Option<Box<Write + Send>> {
+pub fn set_panic(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> {
     use panicking::LOCAL_STDERR;
     use mem;
     LOCAL_STDERR.with(move |slot| {
-        mem::replace(&mut *slot.borrow_mut(), Some(sink))
+        mem::replace(&mut *slot.borrow_mut(), sink)
     }).and_then(|mut s| {
         let _ = s.flush();
         Some(s)
@@ -617,10 +614,10 @@ pub fn set_panic(sink: Box<Write + Send>) -> Option<Box<Write + Send>> {
                      with a more general mechanism",
            issue = "0")]
 #[doc(hidden)]
-pub fn set_print(sink: Box<Write + Send>) -> Option<Box<Write + Send>> {
+pub fn set_print(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> {
     use mem;
     LOCAL_STDOUT.with(move |slot| {
-        mem::replace(&mut *slot.borrow_mut(), Some(sink))
+        mem::replace(&mut *slot.borrow_mut(), sink)
     }).and_then(|mut s| {
         let _ = s.flush();
         Some(s)
@@ -668,6 +665,7 @@ mod tests {
     use super::*;
 
     #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn panic_doesnt_poison() {
         thread::spawn(|| {
             let _a = stdin();
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 115a24fc83c..e470690b7c6 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -218,12 +218,14 @@
 #![feature(associated_consts)]
 #![feature(borrow_state)]
 #![feature(box_syntax)]
+#![feature(cfg_target_has_atomic)]
 #![feature(cfg_target_thread_local)]
 #![feature(cfg_target_vendor)]
 #![feature(char_escape_debug)]
 #![feature(char_internals)]
 #![feature(collections)]
 #![feature(collections_bound)]
+#![feature(collections_range)]
 #![feature(compiler_builtins_lib)]
 #![feature(const_fn)]
 #![feature(core_float)]
@@ -239,6 +241,7 @@
 #![feature(heap_api)]
 #![feature(inclusive_range)]
 #![feature(int_error_internals)]
+#![feature(integer_atomics)]
 #![feature(into_cow)]
 #![feature(lang_items)]
 #![feature(libc)]
@@ -255,10 +258,9 @@
 #![feature(panic_unwind)]
 #![feature(placement_in_syntax)]
 #![feature(prelude_import)]
-#![feature(question_mark)]
+#![cfg_attr(stage0, feature(question_mark))]
 #![feature(rand)]
 #![feature(raw)]
-#![feature(reflect_marker)]
 #![feature(repr_simd)]
 #![feature(rustc_attrs)]
 #![feature(shared)]
@@ -273,12 +275,10 @@
 #![feature(str_utf16)]
 #![feature(test, rustc_private)]
 #![feature(thread_local)]
-#![feature(try_borrow)]
 #![feature(try_from)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
 #![feature(unique)]
-#![cfg_attr(stage0, feature(unsafe_no_drop_flag))]
 #![feature(unwind_attributes)]
 #![feature(vec_push_all)]
 #![feature(zero_one)]
@@ -304,8 +304,8 @@ use prelude::v1::*;
 // We want to reexport a few macros from core but libcore has already been
 // imported by the compiler (via our #[no_std] attribute) In this case we just
 // add a new crate name so we can attach the reexports to it.
-#[macro_reexport(assert, assert_eq, debug_assert, debug_assert_eq,
-                 unreachable, unimplemented, write, writeln, try)]
+#[macro_reexport(assert, assert_eq, assert_ne, debug_assert, debug_assert_eq,
+                 debug_assert_ne, unreachable, unimplemented, write, writeln, try)]
 extern crate core as __core;
 
 #[macro_use]
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index 6f0f6ecab5b..0ce6b0a9431 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -112,12 +112,14 @@ macro_rules! print {
 /// # Examples
 ///
 /// ```
+/// println!();
 /// println!("hello there!");
 /// println!("format {} arguments", "some");
 /// ```
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! println {
+    () => (print!("\n"));
     ($fmt:expr) => (print!(concat!($fmt, "\n")));
     ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
 }
@@ -193,12 +195,18 @@ macro_rules! assert_approx_eq {
 pub mod builtin {
     /// The core macro for formatted string creation & output.
     ///
-    /// This macro produces a value of type `fmt::Arguments`. This value can be
-    /// passed to the functions in `std::fmt` for performing useful functions.
-    /// All other formatting macros (`format!`, `write!`, `println!`, etc) are
+    /// This macro produces a value of type [`fmt::Arguments`]. This value can be
+    /// passed to the functions in [`std::fmt`] for performing useful functions.
+    /// All other formatting macros ([`format!`], [`write!`], [`println!`], etc) are
     /// proxied through this one.
     ///
-    /// For more information, see the documentation in `std::fmt`.
+    /// For more information, see the documentation in [`std::fmt`].
+    ///
+    /// [`fmt::Arguments`]: ../std/fmt/struct.Arguments.html
+    /// [`std::fmt`]: ../std/fmt/index.html
+    /// [`format!`]: ../std/macro.format.html
+    /// [`write!`]: ../std/macro.write.html
+    /// [`println!`]: ../std/macro.println.html
     ///
     /// # Examples
     ///
@@ -278,7 +286,7 @@ pub mod builtin {
     /// // fn concat_idents!(new, fun, name) { } // not usable in this way!
     /// # }
     /// ```
-    #[unstable(feature = "concat_idents", issue = "29599")]
+    #[unstable(feature = "concat_idents_macro", issue = "29599")]
     #[macro_export]
     macro_rules! concat_idents {
         ($($e:ident),*) => ({ /* compiler built-in */ })
@@ -373,9 +381,11 @@ pub mod builtin {
 
     /// Includes a utf8-encoded file as a string.
     ///
+    /// The file is located relative to the current file. (similarly to how
+    /// modules are found)
+    ///
     /// This macro will yield an expression of type `&'static str` which is the
-    /// contents of the filename specified. The file is located relative to the
-    /// current file (similarly to how modules are found),
+    /// contents of the file.
     ///
     /// # Examples
     ///
@@ -388,9 +398,11 @@ pub mod builtin {
 
     /// Includes a file as a reference to a byte array.
     ///
+    /// The file is located relative to the current file. (similarly to how
+    /// modules are found)
+    ///
     /// This macro will yield an expression of type `&'static [u8; N]` which is
-    /// the contents of the filename specified. The file is located relative to
-    /// the current file (similarly to how modules are found),
+    /// the contents of the file.
     ///
     /// # Examples
     ///
@@ -444,9 +456,17 @@ pub mod builtin {
     #[macro_export]
     macro_rules! cfg { ($($cfg:tt)*) => ({ /* compiler built-in */ }) }
 
-    /// Parse the current given file as an expression.
+    /// Parse a file as an expression or an item according to the context.
+    ///
+    /// The file is located relative to the current file. (similarly to how
+    /// modules are found)
     ///
-    /// This is generally a bad idea, because it's going to behave unhygienically.
+    /// Using this macro is often a bad idea, because if the file is
+    /// parsed as an expression, it is going to be placed in the
+    /// surrounding code unhygenically. This could result in variables
+    /// or functions being different from what the file expected if
+    /// there are variables or functions that have the same name in
+    /// the current file.
     ///
     /// # Examples
     ///
diff --git a/src/libstd/memchr.rs b/src/libstd/memchr.rs
index 03f55f7ad61..7c8c97a6caf 100644
--- a/src/libstd/memchr.rs
+++ b/src/libstd/memchr.rs
@@ -11,8 +11,6 @@
 // Original implementation taken from rust-memchr
 // Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
 
-
-
 /// A safe interface to `memchr`.
 ///
 /// Returns the index corresponding to the first occurrence of `needle` in
@@ -32,32 +30,9 @@
 /// let haystack = b"the quick brown fox";
 /// assert_eq!(memchr(b'k', haystack), Some(8));
 /// ```
+#[inline]
 pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
-    // libc memchr
-    #[cfg(not(target_os = "windows"))]
-    fn memchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
-        use libc;
-
-        let p = unsafe {
-            libc::memchr(
-                haystack.as_ptr() as *const libc::c_void,
-                needle as libc::c_int,
-                haystack.len() as libc::size_t)
-        };
-        if p.is_null() {
-            None
-        } else {
-            Some(p as usize - (haystack.as_ptr() as usize))
-        }
-    }
-
-    // use fallback on windows, since it's faster
-    #[cfg(target_os = "windows")]
-    fn memchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
-        fallback::memchr(needle, haystack)
-    }
-
-    memchr_specific(needle, haystack)
+    ::sys::memchr::memchr(needle, haystack)
 }
 
 /// A safe interface to `memrchr`.
@@ -75,251 +50,9 @@ pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
 /// let haystack = b"the quick brown fox";
 /// assert_eq!(memrchr(b'o', haystack), Some(17));
 /// ```
+#[inline]
 pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
-
-    #[cfg(target_os = "linux")]
-    fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
-        use libc;
-
-        // GNU's memrchr() will - unlike memchr() - error if haystack is empty.
-        if haystack.is_empty() {return None}
-        let p = unsafe {
-            libc::memrchr(
-                haystack.as_ptr() as *const libc::c_void,
-                needle as libc::c_int,
-                haystack.len() as libc::size_t)
-        };
-        if p.is_null() {
-            None
-        } else {
-            Some(p as usize - (haystack.as_ptr() as usize))
-        }
-    }
-
-    #[cfg(not(target_os = "linux"))]
-    fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
-        fallback::memrchr(needle, haystack)
-    }
-
-    memrchr_specific(needle, haystack)
-}
-
-#[allow(dead_code)]
-mod fallback {
-    use cmp;
-    use mem;
-
-    const LO_U64: u64 = 0x0101010101010101;
-    const HI_U64: u64 = 0x8080808080808080;
-
-    // use truncation
-    const LO_USIZE: usize = LO_U64 as usize;
-    const HI_USIZE: usize = HI_U64 as usize;
-
-    /// Return `true` if `x` contains any zero byte.
-    ///
-    /// From *Matters Computational*, J. Arndt
-    ///
-    /// "The idea is to subtract one from each of the bytes and then look for
-    /// bytes where the borrow propagated all the way to the most significant
-    /// bit."
-    #[inline]
-    fn contains_zero_byte(x: usize) -> bool {
-        x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0
-    }
-
-    #[cfg(target_pointer_width = "32")]
-    #[inline]
-    fn repeat_byte(b: u8) -> usize {
-        let mut rep = (b as usize) << 8 | b as usize;
-        rep = rep << 16 | rep;
-        rep
-    }
-
-    #[cfg(target_pointer_width = "64")]
-    #[inline]
-    fn repeat_byte(b: u8) -> usize {
-        let mut rep = (b as usize) << 8 | b as usize;
-        rep = rep << 16 | rep;
-        rep = rep << 32 | rep;
-        rep
-    }
-
-    /// Return the first index matching the byte `a` in `text`.
-    pub fn memchr(x: u8, text: &[u8]) -> Option<usize> {
-        // Scan for a single byte value by reading two `usize` words at a time.
-        //
-        // Split `text` in three parts
-        // - unaligned initial part, before the first word aligned address in text
-        // - body, scan by 2 words at a time
-        // - the last remaining part, < 2 word size
-        let len = text.len();
-        let ptr = text.as_ptr();
-        let usize_bytes = mem::size_of::<usize>();
-
-        // search up to an aligned boundary
-        let align = (ptr as usize) & (usize_bytes- 1);
-        let mut offset;
-        if align > 0 {
-            offset = cmp::min(usize_bytes - align, len);
-            if let Some(index) = text[..offset].iter().position(|elt| *elt == x) {
-                return Some(index);
-            }
-        } else {
-            offset = 0;
-        }
-
-        // search the body of the text
-        let repeated_x = repeat_byte(x);
-
-        if len >= 2 * usize_bytes {
-            while offset <= len - 2 * usize_bytes {
-                unsafe {
-                    let u = *(ptr.offset(offset as isize) as *const usize);
-                    let v = *(ptr.offset((offset + usize_bytes) as isize) as *const usize);
-
-                    // break if there is a matching byte
-                    let zu = contains_zero_byte(u ^ repeated_x);
-                    let zv = contains_zero_byte(v ^ repeated_x);
-                    if zu || zv {
-                        break;
-                    }
-                }
-                offset += usize_bytes * 2;
-            }
-        }
-
-        // find the byte after the point the body loop stopped
-        text[offset..].iter().position(|elt| *elt == x).map(|i| offset + i)
-    }
-
-    /// Return the last index matching the byte `a` in `text`.
-    pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
-        // Scan for a single byte value by reading two `usize` words at a time.
-        //
-        // Split `text` in three parts
-        // - unaligned tail, after the last word aligned address in text
-        // - body, scan by 2 words at a time
-        // - the first remaining bytes, < 2 word size
-        let len = text.len();
-        let ptr = text.as_ptr();
-        let usize_bytes = mem::size_of::<usize>();
-
-        // search to an aligned boundary
-        let end_align = (ptr as usize + len) & (usize_bytes - 1);
-        let mut offset;
-        if end_align > 0 {
-            offset = if end_align >= len { 0 } else { len - end_align };
-            if let Some(index) = text[offset..].iter().rposition(|elt| *elt == x) {
-                return Some(offset + index);
-            }
-        } else {
-            offset = len;
-        }
-
-        // search the body of the text
-        let repeated_x = repeat_byte(x);
-
-        while offset >= 2 * usize_bytes {
-            unsafe {
-                let u = *(ptr.offset(offset as isize - 2 * usize_bytes as isize) as *const usize);
-                let v = *(ptr.offset(offset as isize - usize_bytes as isize) as *const usize);
-
-                // break if there is a matching byte
-                let zu = contains_zero_byte(u ^ repeated_x);
-                let zv = contains_zero_byte(v ^ repeated_x);
-                if zu || zv {
-                    break;
-                }
-            }
-            offset -= 2 * usize_bytes;
-        }
-
-        // find the byte before the point the body loop stopped
-        text[..offset].iter().rposition(|elt| *elt == x)
-    }
-
-    // test fallback implementations on all platforms
-    #[test]
-    fn matches_one() {
-        assert_eq!(Some(0), memchr(b'a', b"a"));
-    }
-
-    #[test]
-    fn matches_begin() {
-        assert_eq!(Some(0), memchr(b'a', b"aaaa"));
-    }
-
-    #[test]
-    fn matches_end() {
-        assert_eq!(Some(4), memchr(b'z', b"aaaaz"));
-    }
-
-    #[test]
-    fn matches_nul() {
-        assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00"));
-    }
-
-    #[test]
-    fn matches_past_nul() {
-        assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z"));
-    }
-
-    #[test]
-    fn no_match_empty() {
-        assert_eq!(None, memchr(b'a', b""));
-    }
-
-    #[test]
-    fn no_match() {
-        assert_eq!(None, memchr(b'a', b"xyz"));
-    }
-
-    #[test]
-    fn matches_one_reversed() {
-        assert_eq!(Some(0), memrchr(b'a', b"a"));
-    }
-
-    #[test]
-    fn matches_begin_reversed() {
-        assert_eq!(Some(3), memrchr(b'a', b"aaaa"));
-    }
-
-    #[test]
-    fn matches_end_reversed() {
-        assert_eq!(Some(0), memrchr(b'z', b"zaaaa"));
-    }
-
-    #[test]
-    fn matches_nul_reversed() {
-        assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00"));
-    }
-
-    #[test]
-    fn matches_past_nul_reversed() {
-        assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa"));
-    }
-
-    #[test]
-    fn no_match_empty_reversed() {
-        assert_eq!(None, memrchr(b'a', b""));
-    }
-
-    #[test]
-    fn no_match_reversed() {
-        assert_eq!(None, memrchr(b'a', b"xyz"));
-    }
-
-    #[test]
-    fn each_alignment_reversed() {
-        let mut data = [1u8; 64];
-        let needle = 2;
-        let pos = 40;
-        data[pos] = needle;
-        for start in 0..16 {
-            assert_eq!(Some(pos - start), memrchr(needle, &data[start..]));
-        }
-    }
+    ::sys::memchr::memrchr(needle, haystack)
 }
 
 #[cfg(test)]
diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs
index d0b59b42c17..20dc5b3801b 100644
--- a/src/libstd/net/addr.rs
+++ b/src/libstd/net/addr.rs
@@ -93,6 +93,26 @@ impl SocketAddr {
             SocketAddr::V6(ref mut a) => a.set_port(new_port),
         }
     }
+
+    /// Returns true if the IP in this `SocketAddr` is a valid IPv4 address,
+    /// false if it's a valid IPv6 address.
+    #[unstable(feature = "sockaddr_checker", issue = "36949")]
+    pub fn is_ipv4(&self) -> bool {
+        match *self {
+            SocketAddr::V4(_) => true,
+            SocketAddr::V6(_) => false,
+        }
+    }
+
+    /// Returns true if the IP in this `SocketAddr` is a valid IPv6 address,
+    /// false if it's a valid IPv4 address.
+    #[unstable(feature = "sockaddr_checker", issue = "36949")]
+    pub fn is_ipv6(&self) -> bool {
+        match *self {
+            SocketAddr::V4(_) => false,
+            SocketAddr::V6(_) => true,
+        }
+    }
 }
 
 impl SocketAddrV4 {
@@ -519,7 +539,7 @@ impl<'a, T: ToSocketAddrs + ?Sized> ToSocketAddrs for &'a T {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use net::*;
     use net::test::{tsa, sa6, sa4};
@@ -631,4 +651,19 @@ mod tests {
         v6.set_scope_id(20);
         assert_eq!(v6.scope_id(), 20);
     }
+
+    #[test]
+    fn is_v4() {
+        let v4 = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80));
+        assert!(v4.is_ipv4());
+        assert!(!v4.is_ipv6());
+    }
+
+    #[test]
+    fn is_v6() {
+        let v6 = SocketAddr::V6(SocketAddrV6::new(
+                Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 10, 0));
+        assert!(!v6.is_ipv4());
+        assert!(v6.is_ipv6());
+    }
 }
diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs
index 05ef559422f..49080680fac 100644
--- a/src/libstd/net/ip.rs
+++ b/src/libstd/net/ip.rs
@@ -130,6 +130,24 @@ impl IpAddr {
             IpAddr::V6(ref a) => a.is_documentation(),
         }
     }
+
+    /// Returns true if this address is a valid IPv4 address, false if it's a valid IPv6 address.
+    #[unstable(feature = "ipaddr_checker", issue = "36949")]
+    pub fn is_ipv4(&self) -> bool {
+        match *self {
+            IpAddr::V4(_) => true,
+            IpAddr::V6(_) => false,
+        }
+    }
+
+    /// Returns true if this address is a valid IPv6 address, false if it's a valid IPv4 address.
+    #[unstable(feature = "ipaddr_checker", issue = "36949")]
+    pub fn is_ipv6(&self) -> bool {
+        match *self {
+            IpAddr::V4(_) => false,
+            IpAddr::V6(_) => true,
+        }
+    }
 }
 
 impl Ipv4Addr {
@@ -277,8 +295,7 @@ impl Ipv4Addr {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated)]
+#[stable(feature = "ip_addr", since = "1.7.0")]
 impl fmt::Display for IpAddr {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         match *self {
@@ -669,7 +686,7 @@ impl From<[u8; 16]> for Ipv6Addr {
 }
 
 // Tests for this module
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use net::*;
     use net::Ipv6MulticastScope::*;
@@ -1023,4 +1040,18 @@ mod tests {
         assert!("2001:db8:f00::1002".parse::<Ipv6Addr>().unwrap() <
                 "2001:db8:f00::2001".parse::<Ipv6Addr>().unwrap());
     }
+
+    #[test]
+    fn is_v4() {
+        let ip = IpAddr::V4(Ipv4Addr::new(100, 64, 3, 3));
+        assert!(ip.is_ipv4());
+        assert!(!ip.is_ipv6());
+    }
+
+    #[test]
+    fn is_v6() {
+        let ip = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678));
+        assert!(!ip.is_ipv4());
+        assert!(ip.is_ipv6());
+    }
 }
diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs
index 2a78afa85f7..56286fbe253 100644
--- a/src/libstd/net/mod.rs
+++ b/src/libstd/net/mod.rs
@@ -31,14 +31,15 @@ mod addr;
 mod tcp;
 mod udp;
 mod parser;
-#[cfg(test)] mod test;
+#[cfg(test)]
+mod test;
 
 /// Possible values which can be passed to the [`shutdown`] method of
 /// [`TcpStream`].
 ///
 /// [`shutdown`]: struct.TcpStream.html#method.shutdown
 /// [`TcpStream`]: struct.TcpStream.html
-#[derive(Copy, Clone, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum Shutdown {
     /// Indicates that the reading portion of this stream/socket should be shut
diff --git a/src/libstd/net/parser.rs b/src/libstd/net/parser.rs
index 854d87c4cbe..d86711c10ac 100644
--- a/src/libstd/net/parser.rs
+++ b/src/libstd/net/parser.rs
@@ -302,7 +302,7 @@ impl<'a> Parser<'a> {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "ip_addr", since = "1.7.0")]
 impl FromStr for IpAddr {
     type Err = AddrParseError;
     fn from_str(s: &str) -> Result<IpAddr, AddrParseError> {
@@ -370,7 +370,7 @@ impl FromStr for SocketAddr {
 
 /// An error returned when parsing an IP address or a socket address.
 #[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, PartialEq, Eq)]
 pub struct AddrParseError(());
 
 #[stable(feature = "addr_parse_error_error", since = "1.4.0")]
diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs
index 3c5f07c3e33..0e7c5b06713 100644
--- a/src/libstd/net/tcp.rs
+++ b/src/libstd/net/tcp.rs
@@ -428,7 +428,7 @@ impl fmt::Debug for TcpListener {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use io::ErrorKind;
     use io::prelude::*;
diff --git a/src/libstd/net/test.rs b/src/libstd/net/test.rs
index 98ac61f6461..3f2eacda7d6 100644
--- a/src/libstd/net/test.rs
+++ b/src/libstd/net/test.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#[allow(dead_code)] // not used on emscripten
+
 use env;
 use net::{SocketAddr, SocketAddrV4, SocketAddrV6, Ipv4Addr, Ipv6Addr, ToSocketAddrs};
 use sync::atomic::{AtomicUsize, Ordering};
diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs
index 781f026c12c..c03ac496adb 100644
--- a/src/libstd/net/udp.rs
+++ b/src/libstd/net/udp.rs
@@ -353,7 +353,7 @@ impl fmt::Debug for UdpSocket {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use io::ErrorKind;
     use net::*;
diff --git a/src/libstd/os/fuchsia/fs.rs b/src/libstd/os/fuchsia/fs.rs
new file mode 100644
index 00000000000..d22f9a628bd
--- /dev/null
+++ b/src/libstd/os/fuchsia/fs.rs
@@ -0,0 +1,103 @@
+// Copyright 2016 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.
+
+#![stable(feature = "metadata_ext", since = "1.1.0")]
+
+use fs::Metadata;
+use sys_common::AsInner;
+
+/// OS-specific extension methods for `fs::Metadata`
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+pub trait MetadataExt {
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_dev(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ino(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mode(&self) -> u32;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_nlink(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_uid(&self) -> u32;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_gid(&self) -> u32;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_rdev(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_size(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_atime(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_atime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mtime(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mtime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ctime(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ctime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_blksize(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_blocks(&self) -> u64;
+}
+
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+impl MetadataExt for Metadata {
+    fn st_dev(&self) -> u64 {
+        self.as_inner().as_inner().st_dev as u64
+    }
+    fn st_ino(&self) -> u64 {
+        self.as_inner().as_inner().st_ino as u64
+    }
+    fn st_mode(&self) -> u32 {
+        self.as_inner().as_inner().st_mode as u32
+    }
+    fn st_nlink(&self) -> u64 {
+        self.as_inner().as_inner().st_nlink as u64
+    }
+    fn st_uid(&self) -> u32 {
+        self.as_inner().as_inner().st_uid as u32
+    }
+    fn st_gid(&self) -> u32 {
+        self.as_inner().as_inner().st_gid as u32
+    }
+    fn st_rdev(&self) -> u64 {
+        self.as_inner().as_inner().st_rdev as u64
+    }
+    fn st_size(&self) -> u64 {
+        self.as_inner().as_inner().st_size as u64
+    }
+    fn st_atime(&self) -> i64 {
+        self.as_inner().as_inner().st_atime as i64
+    }
+    fn st_atime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_atime_nsec as i64
+    }
+    fn st_mtime(&self) -> i64 {
+        self.as_inner().as_inner().st_mtime as i64
+    }
+    fn st_mtime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_mtime_nsec as i64
+    }
+    fn st_ctime(&self) -> i64 {
+        self.as_inner().as_inner().st_ctime as i64
+    }
+    fn st_ctime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_ctime_nsec as i64
+    }
+    fn st_blksize(&self) -> u64 {
+        self.as_inner().as_inner().st_blksize as u64
+    }
+    fn st_blocks(&self) -> u64 {
+        self.as_inner().as_inner().st_blocks as u64
+    }
+}
diff --git a/src/libstd/os/fuchsia/mod.rs b/src/libstd/os/fuchsia/mod.rs
new file mode 100644
index 00000000000..1ebcbba9147
--- /dev/null
+++ b/src/libstd/os/fuchsia/mod.rs
@@ -0,0 +1,16 @@
+// Copyright 2015 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.
+
+//! Fuchsia-specific definitions
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+
+pub mod raw;
+pub mod fs;
diff --git a/src/libstd/os/fuchsia/raw.rs b/src/libstd/os/fuchsia/raw.rs
new file mode 100644
index 00000000000..5d017351492
--- /dev/null
+++ b/src/libstd/os/fuchsia/raw.rs
@@ -0,0 +1,270 @@
+// Copyright 2015 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.
+
+//! Fuchsia-specific raw type definitions
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+#![rustc_deprecated(since = "1.8.0",
+                    reason = "these type aliases are no longer supported by \
+                              the standard library, the `libc` crate on \
+                              crates.io should be used instead for the correct \
+                              definitions")]
+#![allow(deprecated)]
+
+use os::raw::c_ulong;
+
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_t = u64;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type mode_t = u32;
+
+#[stable(feature = "pthread_t", since = "1.8.0")]
+pub type pthread_t = c_ulong;
+
+#[doc(inline)]
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub use self::arch::{off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t};
+
+#[cfg(any(target_arch = "x86",
+          target_arch = "le32",
+          target_arch = "powerpc",
+          target_arch = "arm"))]
+mod arch {
+    use os::raw::{c_long, c_short, c_uint};
+
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type ino_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type nlink_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type off_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64;
+
+    #[repr(C)]
+    #[derive(Clone)]
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub struct stat {
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_dev: u64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __pad1: c_short,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __st_ino: u32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mode: u32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_nlink: u32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_uid: u32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_gid: u32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_rdev: u64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __pad2: c_uint,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_size: i64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_blksize: i32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_blocks: i64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_atime: i32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_atime_nsec: c_long,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mtime: i32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mtime_nsec: c_long,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ctime: i32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ctime_nsec: c_long,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ino: u64,
+    }
+}
+
+#[cfg(target_arch = "mips")]
+mod arch {
+    use os::raw::{c_long, c_ulong};
+
+    #[cfg(target_env = "musl")]
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = i64;
+    #[cfg(not(target_env = "musl"))]
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
+    #[cfg(target_env = "musl")]
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type ino_t = u64;
+    #[cfg(not(target_env = "musl"))]
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type ino_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type nlink_t = u64;
+    #[cfg(target_env = "musl")]
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type off_t = u64;
+    #[cfg(not(target_env = "musl"))]
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type off_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64;
+
+    #[repr(C)]
+    #[derive(Clone)]
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub struct stat {
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_dev: c_ulong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_pad1: [c_long; 3],
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ino: u64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mode: u32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_nlink: u32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_uid: u32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_gid: u32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_rdev: c_ulong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_pad2: [c_long; 2],
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_size: i64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_atime: i32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_atime_nsec: c_long,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mtime: i32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mtime_nsec: c_long,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ctime: i32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ctime_nsec: c_long,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_blksize: i32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_blocks: i64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_pad5: [c_long; 14],
+    }
+}
+
+#[cfg(target_arch = "mips64")]
+mod arch {
+    pub use libc::{off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t};
+}
+
+#[cfg(target_arch = "aarch64")]
+mod arch {
+    use os::raw::{c_long, c_int};
+
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type ino_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type nlink_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type off_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64;
+
+    #[repr(C)]
+    #[derive(Clone)]
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub struct stat {
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_dev: u64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ino: u64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mode: u32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_nlink: u32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_uid: u32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_gid: u32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_rdev: u64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __pad1: u64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_size: i64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_blksize: i32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __pad2: c_int,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_blocks: i64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_atime: i64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_atime_nsec: c_long,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mtime: i64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mtime_nsec: c_long,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ctime: i64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ctime_nsec: c_long,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __unused: [c_int; 2],
+    }
+}
+
+#[cfg(target_arch = "x86_64")]
+mod arch {
+    use os::raw::{c_long, c_int};
+
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type ino_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type nlink_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type off_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64;
+
+    #[repr(C)]
+    #[derive(Clone)]
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub struct stat {
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_dev: u64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ino: u64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_nlink: u64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mode: u32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_uid: u32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_gid: u32,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __pad0: c_int,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_rdev: u64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_size: i64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_blksize: i64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_blocks: i64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_atime: i64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_atime_nsec: c_long,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mtime: i64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mtime_nsec: c_long,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ctime: i64,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ctime_nsec: c_long,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __unused: [c_long; 3],
+    }
+}
diff --git a/src/libstd/os/haiku/fs.rs b/src/libstd/os/haiku/fs.rs
new file mode 100644
index 00000000000..54f8ea1b71b
--- /dev/null
+++ b/src/libstd/os/haiku/fs.rs
@@ -0,0 +1,138 @@
+// Copyright 2016 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.
+
+#![stable(feature = "metadata_ext", since = "1.1.0")]
+
+use libc;
+
+use fs::Metadata;
+use sys_common::AsInner;
+
+#[allow(deprecated)]
+use os::haiku::raw;
+
+/// OS-specific extension methods for `fs::Metadata`
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+pub trait MetadataExt {
+    /// Gain a reference to the underlying `stat` structure which contains
+    /// the raw information returned by the OS.
+    ///
+    /// The contents of the returned `stat` are **not** consistent across
+    /// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the
+    /// cross-Unix abstractions contained within the raw stat.
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    #[rustc_deprecated(since = "1.8.0",
+                       reason = "deprecated in favor of the accessor \
+                                 methods of this trait")]
+    #[allow(deprecated)]
+    fn as_raw_stat(&self) -> &raw::stat;
+
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_dev(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ino(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mode(&self) -> u32;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_nlink(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_uid(&self) -> u32;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_gid(&self) -> u32;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_rdev(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_size(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_atime(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_atime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mtime(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mtime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ctime(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ctime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_crtime(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_crtime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_blksize(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_blocks(&self) -> u64;
+}
+
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+impl MetadataExt for Metadata {
+    #[allow(deprecated)]
+    fn as_raw_stat(&self) -> &raw::stat {
+        unsafe {
+            &*(self.as_inner().as_inner() as *const libc::stat
+                                          as *const raw::stat)
+        }
+    }
+    fn st_dev(&self) -> u64 {
+        self.as_inner().as_inner().st_dev as u64
+    }
+    fn st_ino(&self) -> u64 {
+        self.as_inner().as_inner().st_ino as u64
+    }
+    fn st_mode(&self) -> u32 {
+        self.as_inner().as_inner().st_mode as u32
+    }
+    fn st_nlink(&self) -> u64 {
+        self.as_inner().as_inner().st_nlink as u64
+    }
+    fn st_uid(&self) -> u32 {
+        self.as_inner().as_inner().st_uid as u32
+    }
+    fn st_gid(&self) -> u32 {
+        self.as_inner().as_inner().st_gid as u32
+    }
+    fn st_rdev(&self) -> u64 {
+        self.as_inner().as_inner().st_rdev as u64
+    }
+    fn st_size(&self) -> u64 {
+        self.as_inner().as_inner().st_size as u64
+    }
+    fn st_atime(&self) -> i64 {
+        self.as_inner().as_inner().st_atime as i64
+    }
+    fn st_atime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_atime_nsec as i64
+    }
+    fn st_mtime(&self) -> i64 {
+        self.as_inner().as_inner().st_mtime as i64
+    }
+    fn st_mtime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_mtime_nsec as i64
+    }
+    fn st_ctime(&self) -> i64 {
+        self.as_inner().as_inner().st_ctime as i64
+    }
+    fn st_ctime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_ctime_nsec as i64
+    }
+    fn st_crtime(&self) -> i64 {
+        self.as_inner().as_inner().st_crtime as i64
+    }
+    fn st_crtime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_crtime_nsec as i64
+    }
+    fn st_blksize(&self) -> u64 {
+        self.as_inner().as_inner().st_blksize as u64
+    }
+    fn st_blocks(&self) -> u64 {
+        self.as_inner().as_inner().st_blocks as u64
+    }
+}
diff --git a/src/libstd/os/haiku/mod.rs b/src/libstd/os/haiku/mod.rs
new file mode 100644
index 00000000000..dd1675cc9b5
--- /dev/null
+++ b/src/libstd/os/haiku/mod.rs
@@ -0,0 +1,16 @@
+// Copyright 2015 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.
+
+//! Haiku-specific definitions
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+
+pub mod raw;
+pub mod fs;
diff --git a/src/libstd/os/haiku/raw.rs b/src/libstd/os/haiku/raw.rs
new file mode 100644
index 00000000000..95353d999f9
--- /dev/null
+++ b/src/libstd/os/haiku/raw.rs
@@ -0,0 +1,74 @@
+// Copyright 2015 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.
+
+//! Haiku-specific raw type definitions
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+
+#![allow(deprecated)]
+
+use os::raw::{c_long};
+use os::unix::raw::{uid_t, gid_t};
+
+// Use the direct definition of usize, instead of uintptr_t like in libc
+#[stable(feature = "pthread_t", since = "1.8.0")] pub type pthread_t = usize;
+
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = i64;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = i32;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_t = i32;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type ino_t = i64;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type mode_t = u32;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type nlink_t = i32;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type off_t = i64;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i32;
+
+#[repr(C)]
+#[derive(Clone)]
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub struct stat {
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_dev: dev_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_ino: ino_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_mode: mode_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_nlink: nlink_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_uid: uid_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_gid: gid_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_size: off_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_rdev: dev_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_blksize: blksize_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_atime: time_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_atime_nsec: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_mtime: time_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_mtime_nsec: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_ctime: time_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_ctime_nsec: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_crtime: time_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_crtime_nsec: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_type: u32,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_blocks: blkcnt_t,
+}
diff --git a/src/libstd/os/linux/raw.rs b/src/libstd/os/linux/raw.rs
index 1c19e58818d..e6a95bc831f 100644
--- a/src/libstd/os/linux/raw.rs
+++ b/src/libstd/os/linux/raw.rs
@@ -34,7 +34,8 @@ pub use self::arch::{off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t};
           target_arch = "le32",
           target_arch = "powerpc",
           target_arch = "arm",
-          target_arch = "asmjs"))]
+          target_arch = "asmjs",
+          target_arch = "wasm32"))]
 mod arch {
     use os::raw::{c_long, c_short, c_uint};
 
diff --git a/src/libstd/os/mod.rs b/src/libstd/os/mod.rs
index a91d251fc12..366a1674156 100644
--- a/src/libstd/os/mod.rs
+++ b/src/libstd/os/mod.rs
@@ -24,6 +24,7 @@ pub use sys::ext as windows;
 #[cfg(target_os = "bitrig")]    pub mod bitrig;
 #[cfg(target_os = "dragonfly")] pub mod dragonfly;
 #[cfg(target_os = "freebsd")]   pub mod freebsd;
+#[cfg(target_os = "haiku")]     pub mod haiku;
 #[cfg(target_os = "ios")]       pub mod ios;
 #[cfg(target_os = "linux")]     pub mod linux;
 #[cfg(target_os = "macos")]     pub mod macos;
@@ -32,5 +33,6 @@ pub use sys::ext as windows;
 #[cfg(target_os = "openbsd")]   pub mod openbsd;
 #[cfg(target_os = "solaris")]   pub mod solaris;
 #[cfg(target_os = "emscripten")] pub mod emscripten;
+#[cfg(target_os = "fuchsia")]    pub mod fuchsia;
 
 pub mod raw;
diff --git a/src/libstd/os/raw.rs b/src/libstd/os/raw.rs
index 6c5c1b90a4a..2a918d8aeb7 100644
--- a/src/libstd/os/raw.rs
+++ b/src/libstd/os/raw.rs
@@ -18,7 +18,8 @@
                                        target_arch = "arm",
                                        target_arch = "powerpc",
                                        target_arch = "powerpc64",
-                                       target_arch = "s390x"))))]
+                                       target_arch = "s390x")),
+          all(target_os = "fuchsia", target_arch = "aarch64")))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8;
 #[cfg(not(any(target_os = "android",
               target_os = "emscripten",
@@ -26,7 +27,8 @@
                                            target_arch = "arm",
                                            target_arch = "powerpc",
                                            target_arch = "powerpc64",
-                                           target_arch = "s390x")))))]
+                                           target_arch = "s390x")),
+              all(target_os = "fuchsia", target_arch = "aarch64"))))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8;
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8;
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8;
diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs
index 47f594a9b0c..a7e8c4fab37 100644
--- a/src/libstd/panic.rs
+++ b/src/libstd/panic.rs
@@ -18,7 +18,7 @@ use ops::{Deref, DerefMut};
 use panicking;
 use ptr::{Unique, Shared};
 use rc::Rc;
-use sync::{Arc, Mutex, RwLock};
+use sync::{Arc, Mutex, RwLock, atomic};
 use thread::Result;
 
 #[stable(feature = "panic_hooks", since = "1.10.0")]
@@ -196,9 +196,9 @@ impl<'a, T: RefUnwindSafe + ?Sized> UnwindSafe for &'a T {}
 impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *const T {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *mut T {}
-#[stable(feature = "catch_unwind", since = "1.9.0")]
+#[unstable(feature = "unique", issue = "27730")]
 impl<T: UnwindSafe> UnwindSafe for Unique<T> {}
-#[stable(feature = "catch_unwind", since = "1.9.0")]
+#[unstable(feature = "shared", issue = "27730")]
 impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Shared<T> {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T: ?Sized> UnwindSafe for Mutex<T> {}
@@ -231,6 +231,46 @@ impl<T: ?Sized> RefUnwindSafe for Mutex<T> {}
 #[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")]
 impl<T: ?Sized> RefUnwindSafe for RwLock<T> {}
 
+#[cfg(target_has_atomic = "ptr")]
+#[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
+impl RefUnwindSafe for atomic::AtomicIsize {}
+#[cfg(target_has_atomic = "8")]
+#[unstable(feature = "integer_atomics", issue = "32976")]
+impl RefUnwindSafe for atomic::AtomicI8 {}
+#[cfg(target_has_atomic = "16")]
+#[unstable(feature = "integer_atomics", issue = "32976")]
+impl RefUnwindSafe for atomic::AtomicI16 {}
+#[cfg(target_has_atomic = "32")]
+#[unstable(feature = "integer_atomics", issue = "32976")]
+impl RefUnwindSafe for atomic::AtomicI32 {}
+#[cfg(target_has_atomic = "64")]
+#[unstable(feature = "integer_atomics", issue = "32976")]
+impl RefUnwindSafe for atomic::AtomicI64 {}
+
+#[cfg(target_has_atomic = "ptr")]
+#[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
+impl RefUnwindSafe for atomic::AtomicUsize {}
+#[cfg(target_has_atomic = "8")]
+#[unstable(feature = "integer_atomics", issue = "32976")]
+impl RefUnwindSafe for atomic::AtomicU8 {}
+#[cfg(target_has_atomic = "16")]
+#[unstable(feature = "integer_atomics", issue = "32976")]
+impl RefUnwindSafe for atomic::AtomicU16 {}
+#[cfg(target_has_atomic = "32")]
+#[unstable(feature = "integer_atomics", issue = "32976")]
+impl RefUnwindSafe for atomic::AtomicU32 {}
+#[cfg(target_has_atomic = "64")]
+#[unstable(feature = "integer_atomics", issue = "32976")]
+impl RefUnwindSafe for atomic::AtomicU64 {}
+
+#[cfg(target_has_atomic = "8")]
+#[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
+impl RefUnwindSafe for atomic::AtomicBool {}
+
+#[cfg(target_has_atomic = "ptr")]
+#[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
+impl<T> RefUnwindSafe for atomic::AtomicPtr<T> {}
+
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T> Deref for AssertUnwindSafe<T> {
     type Target = T;
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index 0c10dcbdad6..1f5b3437b61 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -84,6 +84,20 @@ static mut HOOK: Hook = Hook::Default;
 /// # Panics
 ///
 /// Panics if called from a panicking thread.
+///
+/// # Examples
+///
+/// The following will print "Custom panic hook":
+///
+/// ```should_panic
+/// use std::panic;
+///
+/// panic::set_hook(Box::new(|_| {
+///     println!("Custom panic hook");
+/// }));
+///
+/// panic!("Normal panic");
+/// ```
 #[stable(feature = "panic_hooks", since = "1.10.0")]
 pub fn set_hook(hook: Box<Fn(&PanicInfo) + 'static + Sync + Send>) {
     if thread::panicking() {
@@ -109,6 +123,22 @@ pub fn set_hook(hook: Box<Fn(&PanicInfo) + 'static + Sync + Send>) {
 /// # Panics
 ///
 /// Panics if called from a panicking thread.
+///
+/// # Examples
+///
+/// The following will print "Normal panic":
+///
+/// ```should_panic
+/// use std::panic;
+///
+/// panic::set_hook(Box::new(|_| {
+///     println!("Custom panic hook");
+/// }));
+///
+/// let _ = panic::take_hook();
+///
+/// panic!("Normal panic");
+/// ```
 #[stable(feature = "panic_hooks", since = "1.10.0")]
 pub fn take_hook() -> Box<Fn(&PanicInfo) + 'static + Sync + Send> {
     if thread::panicking() {
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index bd27bcf48a0..a55318d3883 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -113,7 +113,7 @@ use ops::{self, Deref};
 
 use ffi::{OsStr, OsString};
 
-use self::platform::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix};
+use sys::path::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix};
 
 ////////////////////////////////////////////////////////////////////////////////
 // GENERAL NOTES
@@ -126,130 +126,6 @@ use self::platform::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix};
 // available.
 
 ////////////////////////////////////////////////////////////////////////////////
-// Platform-specific definitions
-////////////////////////////////////////////////////////////////////////////////
-
-// The following modules give the most basic tools for parsing paths on various
-// platforms. The bulk of the code is devoted to parsing prefixes on Windows.
-
-#[cfg(unix)]
-mod platform {
-    use super::Prefix;
-    use ffi::OsStr;
-
-    #[inline]
-    pub fn is_sep_byte(b: u8) -> bool {
-        b == b'/'
-    }
-
-    #[inline]
-    pub fn is_verbatim_sep(b: u8) -> bool {
-        b == b'/'
-    }
-
-    pub fn parse_prefix(_: &OsStr) -> Option<Prefix> {
-        None
-    }
-
-    pub const MAIN_SEP_STR: &'static str = "/";
-    pub const MAIN_SEP: char = '/';
-}
-
-#[cfg(windows)]
-mod platform {
-    use ascii::*;
-
-    use super::{os_str_as_u8_slice, u8_slice_as_os_str, Prefix};
-    use ffi::OsStr;
-
-    #[inline]
-    pub fn is_sep_byte(b: u8) -> bool {
-        b == b'/' || b == b'\\'
-    }
-
-    #[inline]
-    pub fn is_verbatim_sep(b: u8) -> bool {
-        b == b'\\'
-    }
-
-    pub fn parse_prefix<'a>(path: &'a OsStr) -> Option<Prefix> {
-        use super::Prefix::*;
-        unsafe {
-            // The unsafety here stems from converting between &OsStr and &[u8]
-            // and back. This is safe to do because (1) we only look at ASCII
-            // contents of the encoding and (2) new &OsStr values are produced
-            // only from ASCII-bounded slices of existing &OsStr values.
-            let mut path = os_str_as_u8_slice(path);
-
-            if path.starts_with(br"\\") {
-                // \\
-                path = &path[2..];
-                if path.starts_with(br"?\") {
-                    // \\?\
-                    path = &path[2..];
-                    if path.starts_with(br"UNC\") {
-                        // \\?\UNC\server\share
-                        path = &path[4..];
-                        let (server, share) = match parse_two_comps(path, is_verbatim_sep) {
-                            Some((server, share)) =>
-                                (u8_slice_as_os_str(server), u8_slice_as_os_str(share)),
-                            None => (u8_slice_as_os_str(path), u8_slice_as_os_str(&[])),
-                        };
-                        return Some(VerbatimUNC(server, share));
-                    } else {
-                        // \\?\path
-                        let idx = path.iter().position(|&b| b == b'\\');
-                        if idx == Some(2) && path[1] == b':' {
-                            let c = path[0];
-                            if c.is_ascii() && (c as char).is_alphabetic() {
-                                // \\?\C:\ path
-                                return Some(VerbatimDisk(c.to_ascii_uppercase()));
-                            }
-                        }
-                        let slice = &path[..idx.unwrap_or(path.len())];
-                        return Some(Verbatim(u8_slice_as_os_str(slice)));
-                    }
-                } else if path.starts_with(b".\\") {
-                    // \\.\path
-                    path = &path[2..];
-                    let pos = path.iter().position(|&b| b == b'\\');
-                    let slice = &path[..pos.unwrap_or(path.len())];
-                    return Some(DeviceNS(u8_slice_as_os_str(slice)));
-                }
-                match parse_two_comps(path, is_sep_byte) {
-                    Some((server, share)) if !server.is_empty() && !share.is_empty() => {
-                        // \\server\share
-                        return Some(UNC(u8_slice_as_os_str(server), u8_slice_as_os_str(share)));
-                    }
-                    _ => (),
-                }
-            } else if path.get(1) == Some(& b':') {
-                // C:
-                let c = path[0];
-                if c.is_ascii() && (c as char).is_alphabetic() {
-                    return Some(Disk(c.to_ascii_uppercase()));
-                }
-            }
-            return None;
-        }
-
-        fn parse_two_comps(mut path: &[u8], f: fn(u8) -> bool) -> Option<(&[u8], &[u8])> {
-            let first = match path.iter().position(|x| f(*x)) {
-                None => return None,
-                Some(x) => &path[..x],
-            };
-            path = &path[(first.len() + 1)..];
-            let idx = path.iter().position(|x| f(*x));
-            let second = &path[..idx.unwrap_or(path.len())];
-            Some((first, second))
-        }
-    }
-
-    pub const MAIN_SEP_STR: &'static str = "\\";
-    pub const MAIN_SEP: char = '\\';
-}
-
-////////////////////////////////////////////////////////////////////////////////
 // Windows Prefixes
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -373,7 +249,7 @@ pub fn is_separator(c: char) -> bool {
 
 /// The primary separator for the current platform
 #[stable(feature = "rust1", since = "1.0.0")]
-pub const MAIN_SEPARATOR: char = platform::MAIN_SEP;
+pub const MAIN_SEPARATOR: char = ::sys::path::MAIN_SEP;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Misc helpers
@@ -1418,14 +1294,18 @@ impl Into<OsString> for PathBuf {
 /// This type supports a number of operations for inspecting a path, including
 /// breaking the path into its components (separated by `/` or `\`, depending on
 /// the platform), extracting the file name, determining whether the path is
-/// absolute, and so on. More details about the overall approach can be found in
-/// the module documentation.
+/// absolute, and so on.
 ///
 /// This is an *unsized* type, meaning that it must always be used behind a
-/// pointer like `&` or [`Box`].
+/// pointer like `&` or [`Box`]. For an owned version of this type,
+/// see [`PathBuf`].
 ///
 /// [`str`]: ../primitive.str.html
 /// [`Box`]: ../boxed/struct.Box.html
+/// [`PathBuf`]: struct.PathBuf.html
+///
+/// More details about the overall approach can be found in
+/// the module documentation.
 ///
 /// # Examples
 ///
@@ -3511,10 +3391,11 @@ mod tests {
 
     #[test]
     pub fn test_compare() {
-        use hash::{Hash, Hasher, SipHasher};
+        use hash::{Hash, Hasher};
+        use collections::hash_map::DefaultHasher;
 
         fn hash<T: Hash>(t: T) -> u64 {
-            let mut s = SipHasher::new_with_keys(0, 0);
+            let mut s = DefaultHasher::new();
             t.hash(&mut s);
             s.finish()
         }
diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs
index fdc84467015..54dde6681e1 100644
--- a/src/libstd/primitive_docs.rs
+++ b/src/libstd/primitive_docs.rs
@@ -229,7 +229,7 @@ mod prim_unit { }
 ///
 /// fn main() {
 ///     unsafe {
-///         let my_num: *mut i32 = libc::malloc(mem::size_of::<i32>() as libc::size_t) as *mut i32;
+///         let my_num: *mut i32 = libc::malloc(mem::size_of::<i32>()) as *mut i32;
 ///         if my_num.is_null() {
 ///             panic!("failed to allocate memory");
 ///         }
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index f0c44430700..9d21a76e81b 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -8,7 +8,25 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Working with processes.
+//! A module for working with processes.
+//!
+//! # Examples
+//!
+//! Basic usage where we try to execute the `cat` shell command:
+//!
+//! ```should_panic
+//! use std::process::Command;
+//!
+//! let mut child = Command::new("/bin/cat")
+//!                         .arg("file.txt")
+//!                         .spawn()
+//!                         .expect("failed to execute child");
+//!
+//! let ecode = child.wait()
+//!                  .expect("failed to wait on child");
+//!
+//! assert!(ecode.success());
+//! ```
 
 #![stable(feature = "process", since = "1.0.0")]
 
@@ -807,7 +825,7 @@ pub fn exit(code: i32) -> ! {
     ::sys::os::exit(code)
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use io::prelude::*;
 
diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs
index 3f14fcd239f..f48325218fb 100644
--- a/src/libstd/rand/mod.rs
+++ b/src/libstd/rand/mod.rs
@@ -242,9 +242,10 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn test_os_rng_tasks() {
 
-        let mut txs = vec!();
+        let mut txs = vec![];
         for _ in 0..20 {
             let (tx, rx) = channel();
             txs.push(tx);
diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs
index e3de1efaa31..78d5aa597ba 100644
--- a/src/libstd/rt.rs
+++ b/src/libstd/rt.rs
@@ -51,7 +51,7 @@ fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize {
         thread_info::set(main_guard, thread);
 
         // Store our args if necessary in a squirreled away location
-        sys_common::args::init(argc, argv);
+        sys::args::init(argc, argv);
 
         // Let's run some code!
         let res = panic::catch_unwind(mem::transmute::<_, fn()>(main));
diff --git a/src/libstd/rtdeps.rs b/src/libstd/rtdeps.rs
index a11200873d5..5dc6ee2bc8c 100644
--- a/src/libstd/rtdeps.rs
+++ b/src/libstd/rtdeps.rs
@@ -62,3 +62,7 @@ extern {}
 #[cfg(target_os = "ios")]
 #[link(name = "System")]
 extern {}
+
+#[cfg(target_os = "haiku")]
+#[link(name = "network")]
+extern {}
diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs
index ac0f400379e..f46eab68484 100644
--- a/src/libstd/sync/barrier.rs
+++ b/src/libstd/sync/barrier.rs
@@ -118,6 +118,7 @@ mod tests {
     use thread;
 
     #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn test_barrier() {
         const N: usize = 10;
 
diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs
index 3db8b05b954..a983ae716a4 100644
--- a/src/libstd/sync/condvar.rs
+++ b/src/libstd/sync/condvar.rs
@@ -270,6 +270,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn notify_one() {
         let m = Arc::new(Mutex::new(()));
         let m2 = m.clone();
@@ -286,6 +287,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn notify_all() {
         const N: usize = 10;
 
@@ -322,6 +324,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn wait_timeout_ms() {
         let m = Arc::new(Mutex::new(()));
         let m2 = m.clone();
@@ -343,6 +346,7 @@ mod tests {
 
     #[test]
     #[should_panic]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn two_mutexes() {
         let m = Arc::new(Mutex::new(()));
         let m2 = m.clone();
diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs
index 3d9f81413dc..fce640e7c7a 100644
--- a/src/libstd/sync/mpsc/mod.rs
+++ b/src/libstd/sync/mpsc/mod.rs
@@ -270,7 +270,6 @@ use error;
 use fmt;
 use mem;
 use cell::UnsafeCell;
-use marker::Reflect;
 use time::{Duration, Instant};
 
 #[unstable(feature = "mpsc_select", issue = "27800")]
@@ -1163,7 +1162,7 @@ impl<T> fmt::Display for SendError<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send + Reflect> error::Error for SendError<T> {
+impl<T: Send> error::Error for SendError<T> {
     fn description(&self) -> &str {
         "sending on a closed channel"
     }
@@ -1198,7 +1197,7 @@ impl<T> fmt::Display for TrySendError<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send + Reflect> error::Error for TrySendError<T> {
+impl<T: Send> error::Error for TrySendError<T> {
 
     fn description(&self) -> &str {
         match *self {
@@ -1268,7 +1267,7 @@ impl error::Error for TryRecvError {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use env;
     use super::*;
@@ -1940,9 +1939,16 @@ mod tests {
         // wait for the child thread to exit before we exit
         rx2.recv().unwrap();
     }
+
+    #[test]
+    fn issue_32114() {
+        let (tx, _) = channel();
+        let _ = tx.send(123);
+        assert_eq!(tx.send(123), Err(SendError(123)));
+    }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod sync_tests {
     use env;
     use thread;
diff --git a/src/libstd/sync/mpsc/mpsc_queue.rs b/src/libstd/sync/mpsc/mpsc_queue.rs
index d926043fbbc..8d80f942ff7 100644
--- a/src/libstd/sync/mpsc/mpsc_queue.rs
+++ b/src/libstd/sync/mpsc/mpsc_queue.rs
@@ -146,7 +146,7 @@ impl<T> Drop for Queue<T> {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use sync::mpsc::channel;
     use super::{Queue, Data, Empty, Inconsistent};
diff --git a/src/libstd/sync/mpsc/oneshot.rs b/src/libstd/sync/mpsc/oneshot.rs
index 7389280b853..767e9f96ac8 100644
--- a/src/libstd/sync/mpsc/oneshot.rs
+++ b/src/libstd/sync/mpsc/oneshot.rs
@@ -113,6 +113,8 @@ impl<T> Packet<T> {
             // Couldn't send the data, the port hung up first. Return the data
             // back up the stack.
             DISCONNECTED => {
+                self.state.swap(DISCONNECTED, Ordering::SeqCst);
+                self.upgrade = NothingSent;
                 Err(self.data.take().unwrap())
             }
 
diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs
index 677544d335e..8b4da532af6 100644
--- a/src/libstd/sync/mpsc/select.rs
+++ b/src/libstd/sync/mpsc/select.rs
@@ -103,7 +103,7 @@ pub struct Handle<'rx, T:Send+'rx> {
 struct Packets { cur: *mut Handle<'static, ()> }
 
 #[doc(hidden)]
-#[derive(PartialEq)]
+#[derive(PartialEq, Eq)]
 pub enum StartResult {
     Installed,
     Abort,
@@ -352,22 +352,20 @@ impl Iterator for Packets {
     }
 }
 
-#[stable(feature = "mpsc_debug", since = "1.7.0")]
 impl fmt::Debug for Select {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "Select {{ .. }}")
     }
 }
 
-#[stable(feature = "mpsc_debug", since = "1.7.0")]
 impl<'rx, T:Send+'rx> fmt::Debug for Handle<'rx, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "Handle {{ .. }}")
     }
 }
 
-#[cfg(test)]
 #[allow(unused_imports)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use thread;
     use sync::mpsc::*;
diff --git a/src/libstd/sync/mpsc/spsc_queue.rs b/src/libstd/sync/mpsc/spsc_queue.rs
index 724d7b1be73..5858e4b6ddb 100644
--- a/src/libstd/sync/mpsc/spsc_queue.rs
+++ b/src/libstd/sync/mpsc/spsc_queue.rs
@@ -231,7 +231,7 @@ impl<T> Drop for Queue<T> {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use sync::Arc;
     use super::Queue;
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index 098a3e44258..812724c7a16 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -352,7 +352,7 @@ pub fn guard_poison<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a poison::Fla
     &guard.__lock.poison
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use sync::mpsc::channel;
     use sync::{Arc, Mutex, Condvar};
diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs
index 86d2986959c..71e163321ae 100644
--- a/src/libstd/sync/once.rs
+++ b/src/libstd/sync/once.rs
@@ -367,7 +367,7 @@ impl OnceState {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use panic;
     use sync::mpsc::channel;
@@ -387,7 +387,7 @@ mod tests {
     #[test]
     fn stampede_once() {
         static O: Once = Once::new();
-        static mut run: bool = false;
+        static mut RUN: bool = false;
 
         let (tx, rx) = channel();
         for _ in 0..10 {
@@ -396,10 +396,10 @@ mod tests {
                 for _ in 0..4 { thread::yield_now() }
                 unsafe {
                     O.call_once(|| {
-                        assert!(!run);
-                        run = true;
+                        assert!(!RUN);
+                        RUN = true;
                     });
-                    assert!(run);
+                    assert!(RUN);
                 }
                 tx.send(()).unwrap();
             });
@@ -407,10 +407,10 @@ mod tests {
 
         unsafe {
             O.call_once(|| {
-                assert!(!run);
-                run = true;
+                assert!(!RUN);
+                RUN = true;
             });
-            assert!(run);
+            assert!(RUN);
         }
 
         for _ in 0..10 {
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
index 7f053c6704b..f08b7641521 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -136,6 +136,10 @@ impl<T: ?Sized> RwLock<T> {
     /// This function will return an error if the RwLock is poisoned. An RwLock
     /// is poisoned whenever a writer panics while holding an exclusive lock.
     /// The failure will occur immediately after the lock has been acquired.
+    ///
+    /// # Panics
+    ///
+    /// This function might panic when called if the lock is already held by the current thread.
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn read(&self) -> LockResult<RwLockReadGuard<T>> {
@@ -188,6 +192,10 @@ impl<T: ?Sized> RwLock<T> {
     /// This function will return an error if the RwLock is poisoned. An RwLock
     /// is poisoned whenever a writer panics while holding an exclusive lock.
     /// An error will be returned when the lock is acquired.
+    ///
+    /// # Panics
+    ///
+    /// This function might panic when called if the lock is already held by the current thread.
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> {
@@ -380,7 +388,7 @@ impl<'a, T: ?Sized> Drop for RwLockWriteGuard<'a, T> {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     #![allow(deprecated)] // rand
 
diff --git a/src/libstd/sys/common/args.rs b/src/libstd/sys/common/args.rs
deleted file mode 100644
index fad2c277da4..00000000000
--- a/src/libstd/sys/common/args.rs
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2012-2015 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.
-
-#![allow(dead_code)] // different code on OSX/linux/etc
-
-/// One-time global initialization.
-pub unsafe fn init(argc: isize, argv: *const *const u8) { imp::init(argc, argv) }
-
-/// One-time global cleanup.
-pub unsafe fn cleanup() { imp::cleanup() }
-
-/// 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",
-          target_os = "bitrig",
-          target_os = "netbsd",
-          target_os = "openbsd",
-          target_os = "solaris",
-          target_os = "emscripten"))]
-mod imp {
-    use libc::c_char;
-    use mem;
-    use ffi::CStr;
-
-    use sys_common::mutex::Mutex;
-
-    static mut GLOBAL_ARGS_PTR: usize = 0;
-    static LOCK: Mutex = Mutex::new();
-
-    pub unsafe fn init(argc: isize, argv: *const *const u8) {
-        let args = (0..argc).map(|i| {
-            CStr::from_ptr(*argv.offset(i) as *const c_char).to_bytes().to_vec()
-        }).collect();
-
-        LOCK.lock();
-        let ptr = get_global_ptr();
-        assert!((*ptr).is_none());
-        (*ptr) = Some(box args);
-        LOCK.unlock();
-    }
-
-    pub unsafe fn cleanup() {
-        LOCK.lock();
-        *get_global_ptr() = None;
-        LOCK.unlock();
-    }
-
-    pub fn clone() -> Option<Vec<Vec<u8>>> {
-        unsafe {
-            LOCK.lock();
-            let ptr = get_global_ptr();
-            let ret = (*ptr).as_ref().map(|s| (**s).clone());
-            LOCK.unlock();
-            return ret
-        }
-    }
-
-    fn get_global_ptr() -> *mut Option<Box<Vec<Vec<u8>>>> {
-        unsafe { mem::transmute(&GLOBAL_ARGS_PTR) }
-    }
-
-}
-
-#[cfg(any(target_os = "macos",
-          target_os = "ios",
-          target_os = "windows"))]
-mod imp {
-    pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
-    }
-
-    pub fn cleanup() {
-    }
-
-    pub fn clone() -> Option<Vec<Vec<u8>>> {
-        panic!()
-    }
-}
diff --git a/src/libstd/sys/common/io.rs b/src/libstd/sys/common/io.rs
index 3cd70eddb85..0483725dd83 100644
--- a/src/libstd/sys/common/io.rs
+++ b/src/libstd/sys/common/io.rs
@@ -51,6 +51,7 @@ pub unsafe fn read_to_end_uninitialized(r: &mut Read, buf: &mut Vec<u8>) -> io::
 }
 
 #[cfg(test)]
+#[allow(dead_code)] // not used on emscripten
 pub mod test {
     use path::{Path, PathBuf};
     use env;
@@ -165,6 +166,7 @@ mod tests {
     }
 
     #[bench]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn bench_uninitialized(b: &mut ::test::Bencher) {
         b.iter(|| {
             let mut lr = repeat(1).take(10000000);
diff --git a/src/libstd/sys/common/memchr.rs b/src/libstd/sys/common/memchr.rs
new file mode 100644
index 00000000000..3824a5fb528
--- /dev/null
+++ b/src/libstd/sys/common/memchr.rs
@@ -0,0 +1,230 @@
+// Copyright 2015 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.
+//
+// Original implementation taken from rust-memchr
+// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
+
+#[allow(dead_code)]
+pub mod fallback {
+    use cmp;
+    use mem;
+
+    const LO_U64: u64 = 0x0101010101010101;
+    const HI_U64: u64 = 0x8080808080808080;
+
+    // use truncation
+    const LO_USIZE: usize = LO_U64 as usize;
+    const HI_USIZE: usize = HI_U64 as usize;
+
+    /// Return `true` if `x` contains any zero byte.
+    ///
+    /// From *Matters Computational*, J. Arndt
+    ///
+    /// "The idea is to subtract one from each of the bytes and then look for
+    /// bytes where the borrow propagated all the way to the most significant
+    /// bit."
+    #[inline]
+    fn contains_zero_byte(x: usize) -> bool {
+        x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0
+    }
+
+    #[cfg(target_pointer_width = "32")]
+    #[inline]
+    fn repeat_byte(b: u8) -> usize {
+        let mut rep = (b as usize) << 8 | b as usize;
+        rep = rep << 16 | rep;
+        rep
+    }
+
+    #[cfg(target_pointer_width = "64")]
+    #[inline]
+    fn repeat_byte(b: u8) -> usize {
+        let mut rep = (b as usize) << 8 | b as usize;
+        rep = rep << 16 | rep;
+        rep = rep << 32 | rep;
+        rep
+    }
+
+    /// Return the first index matching the byte `a` in `text`.
+    pub fn memchr(x: u8, text: &[u8]) -> Option<usize> {
+        // Scan for a single byte value by reading two `usize` words at a time.
+        //
+        // Split `text` in three parts
+        // - unaligned initial part, before the first word aligned address in text
+        // - body, scan by 2 words at a time
+        // - the last remaining part, < 2 word size
+        let len = text.len();
+        let ptr = text.as_ptr();
+        let usize_bytes = mem::size_of::<usize>();
+
+        // search up to an aligned boundary
+        let align = (ptr as usize) & (usize_bytes- 1);
+        let mut offset;
+        if align > 0 {
+            offset = cmp::min(usize_bytes - align, len);
+            if let Some(index) = text[..offset].iter().position(|elt| *elt == x) {
+                return Some(index);
+            }
+        } else {
+            offset = 0;
+        }
+
+        // search the body of the text
+        let repeated_x = repeat_byte(x);
+
+        if len >= 2 * usize_bytes {
+            while offset <= len - 2 * usize_bytes {
+                unsafe {
+                    let u = *(ptr.offset(offset as isize) as *const usize);
+                    let v = *(ptr.offset((offset + usize_bytes) as isize) as *const usize);
+
+                    // break if there is a matching byte
+                    let zu = contains_zero_byte(u ^ repeated_x);
+                    let zv = contains_zero_byte(v ^ repeated_x);
+                    if zu || zv {
+                        break;
+                    }
+                }
+                offset += usize_bytes * 2;
+            }
+        }
+
+        // find the byte after the point the body loop stopped
+        text[offset..].iter().position(|elt| *elt == x).map(|i| offset + i)
+    }
+
+    /// Return the last index matching the byte `a` in `text`.
+    pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
+        // Scan for a single byte value by reading two `usize` words at a time.
+        //
+        // Split `text` in three parts
+        // - unaligned tail, after the last word aligned address in text
+        // - body, scan by 2 words at a time
+        // - the first remaining bytes, < 2 word size
+        let len = text.len();
+        let ptr = text.as_ptr();
+        let usize_bytes = mem::size_of::<usize>();
+
+        // search to an aligned boundary
+        let end_align = (ptr as usize + len) & (usize_bytes - 1);
+        let mut offset;
+        if end_align > 0 {
+            offset = if end_align >= len { 0 } else { len - end_align };
+            if let Some(index) = text[offset..].iter().rposition(|elt| *elt == x) {
+                return Some(offset + index);
+            }
+        } else {
+            offset = len;
+        }
+
+        // search the body of the text
+        let repeated_x = repeat_byte(x);
+
+        while offset >= 2 * usize_bytes {
+            unsafe {
+                let u = *(ptr.offset(offset as isize - 2 * usize_bytes as isize) as *const usize);
+                let v = *(ptr.offset(offset as isize - usize_bytes as isize) as *const usize);
+
+                // break if there is a matching byte
+                let zu = contains_zero_byte(u ^ repeated_x);
+                let zv = contains_zero_byte(v ^ repeated_x);
+                if zu || zv {
+                    break;
+                }
+            }
+            offset -= 2 * usize_bytes;
+        }
+
+        // find the byte before the point the body loop stopped
+        text[..offset].iter().rposition(|elt| *elt == x)
+    }
+
+    // test fallback implementations on all platforms
+    #[test]
+    fn matches_one() {
+        assert_eq!(Some(0), memchr(b'a', b"a"));
+    }
+
+    #[test]
+    fn matches_begin() {
+        assert_eq!(Some(0), memchr(b'a', b"aaaa"));
+    }
+
+    #[test]
+    fn matches_end() {
+        assert_eq!(Some(4), memchr(b'z', b"aaaaz"));
+    }
+
+    #[test]
+    fn matches_nul() {
+        assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00"));
+    }
+
+    #[test]
+    fn matches_past_nul() {
+        assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z"));
+    }
+
+    #[test]
+    fn no_match_empty() {
+        assert_eq!(None, memchr(b'a', b""));
+    }
+
+    #[test]
+    fn no_match() {
+        assert_eq!(None, memchr(b'a', b"xyz"));
+    }
+
+    #[test]
+    fn matches_one_reversed() {
+        assert_eq!(Some(0), memrchr(b'a', b"a"));
+    }
+
+    #[test]
+    fn matches_begin_reversed() {
+        assert_eq!(Some(3), memrchr(b'a', b"aaaa"));
+    }
+
+    #[test]
+    fn matches_end_reversed() {
+        assert_eq!(Some(0), memrchr(b'z', b"zaaaa"));
+    }
+
+    #[test]
+    fn matches_nul_reversed() {
+        assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00"));
+    }
+
+    #[test]
+    fn matches_past_nul_reversed() {
+        assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa"));
+    }
+
+    #[test]
+    fn no_match_empty_reversed() {
+        assert_eq!(None, memrchr(b'a', b""));
+    }
+
+    #[test]
+    fn no_match_reversed() {
+        assert_eq!(None, memrchr(b'a', b"xyz"));
+    }
+
+    #[test]
+    fn each_alignment_reversed() {
+        let mut data = [1u8; 64];
+        let needle = 2;
+        let pos = 40;
+        data[pos] = needle;
+        for start in 0..16 {
+            assert_eq!(Some(pos - start), memrchr(needle, &data[start..]));
+        }
+    }
+}
diff --git a/src/libstd/sys/common/mod.rs b/src/libstd/sys/common/mod.rs
index d1ca6765107..2845f895f18 100644
--- a/src/libstd/sys/common/mod.rs
+++ b/src/libstd/sys/common/mod.rs
@@ -25,12 +25,12 @@ macro_rules! rtassert {
     })
 }
 
-pub mod args;
 pub mod at_exit_imp;
 #[cfg(any(not(cargobuild), feature = "backtrace"))]
 pub mod backtrace;
 pub mod condvar;
 pub mod io;
+pub mod memchr;
 pub mod mutex;
 pub mod net;
 pub mod poison;
@@ -91,7 +91,7 @@ pub fn at_exit<F: FnOnce() + Send + 'static>(f: F) -> Result<(), ()> {
 pub fn cleanup() {
     static CLEANUP: Once = Once::new();
     CLEANUP.call_once(|| unsafe {
-        args::cleanup();
+        sys::args::cleanup();
         sys::stack_overflow::cleanup();
         at_exit_imp::cleanup();
     });
diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs
index a777cfe35e5..10ad61f4c80 100644
--- a/src/libstd/sys/common/net.rs
+++ b/src/libstd/sys/common/net.rs
@@ -24,24 +24,35 @@ use time::Duration;
 #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
           target_os = "ios", target_os = "macos",
           target_os = "openbsd", target_os = "netbsd",
-          target_os = "solaris"))]
+          target_os = "solaris", target_os = "haiku"))]
 use sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
 #[cfg(not(any(target_os = "dragonfly", target_os = "freebsd",
               target_os = "ios", target_os = "macos",
               target_os = "openbsd", target_os = "netbsd",
-              target_os = "solaris")))]
+              target_os = "solaris", target_os = "haiku")))]
 use sys::net::netc::IPV6_ADD_MEMBERSHIP;
 #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
           target_os = "ios", target_os = "macos",
           target_os = "openbsd", target_os = "netbsd",
-          target_os = "solaris"))]
+          target_os = "solaris", target_os = "haiku"))]
 use sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
 #[cfg(not(any(target_os = "dragonfly", target_os = "freebsd",
               target_os = "ios", target_os = "macos",
               target_os = "openbsd", target_os = "netbsd",
-              target_os = "solaris")))]
+              target_os = "solaris", target_os = "haiku")))]
 use sys::net::netc::IPV6_DROP_MEMBERSHIP;
 
+#[cfg(any(target_os = "linux", target_os = "android",
+          target_os = "dragonfly", target_os = "freebsd",
+          target_os = "openbsd", target_os = "netbsd",
+          target_os = "haiku", target_os = "bitrig"))]
+use libc::MSG_NOSIGNAL;
+#[cfg(not(any(target_os = "linux", target_os = "android",
+              target_os = "dragonfly", target_os = "freebsd",
+              target_os = "openbsd", target_os = "netbsd",
+              target_os = "haiku", target_os = "bitrig")))]
+const MSG_NOSIGNAL: c_int = 0x0;
+
 ////////////////////////////////////////////////////////////////////////////////
 // sockaddr and misc bindings
 ////////////////////////////////////////////////////////////////////////////////
@@ -225,7 +236,7 @@ impl TcpStream {
             c::send(*self.inner.as_inner(),
                     buf.as_ptr() as *const c_void,
                     len,
-                    0)
+                    MSG_NOSIGNAL)
         })?;
         Ok(ret as usize)
     }
@@ -449,7 +460,7 @@ impl UdpSocket {
         let ret = cvt(unsafe {
             c::sendto(*self.inner.as_inner(),
                       buf.as_ptr() as *const c_void, len,
-                      0, dstp, dstlen)
+                      MSG_NOSIGNAL, dstp, dstlen)
         })?;
         Ok(ret as usize)
     }
@@ -573,7 +584,7 @@ impl UdpSocket {
             c::send(*self.inner.as_inner(),
                     buf.as_ptr() as *const c_void,
                     len,
-                    0)
+                    MSG_NOSIGNAL)
         })?;
         Ok(ret as usize)
     }
diff --git a/src/libstd/sys/common/poison.rs b/src/libstd/sys/common/poison.rs
index 55212bf35d6..bdc727f1dfc 100644
--- a/src/libstd/sys/common/poison.rs
+++ b/src/libstd/sys/common/poison.rs
@@ -10,7 +10,6 @@
 
 use error::{Error};
 use fmt;
-use marker::Reflect;
 use sync::atomic::{AtomicBool, Ordering};
 use thread;
 
@@ -117,7 +116,7 @@ impl<T> fmt::Display for PoisonError<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Reflect> Error for PoisonError<T> {
+impl<T> Error for PoisonError<T> {
     fn description(&self) -> &str {
         "poisoned lock: another task failed inside"
     }
@@ -174,7 +173,7 @@ impl<T> fmt::Display for TryLockError<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Reflect> Error for TryLockError<T> {
+impl<T> Error for TryLockError<T> {
     fn description(&self) -> &str {
         match *self {
             TryLockError::Poisoned(ref p) => p.description(),
diff --git a/src/libstd/sys/common/remutex.rs b/src/libstd/sys/common/remutex.rs
index cbdeaad7f6b..4d0407ccf6c 100644
--- a/src/libstd/sys/common/remutex.rs
+++ b/src/libstd/sys/common/remutex.rs
@@ -156,7 +156,7 @@ impl<'a, T> Drop for ReentrantMutexGuard<'a, T> {
 }
 
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
     use cell::RefCell;
diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs
index 8d357aa78c9..0a94ff1e958 100644
--- a/src/libstd/sys/common/wtf8.rs
+++ b/src/libstd/sys/common/wtf8.rs
@@ -206,10 +206,12 @@ impl Wtf8Buf {
     /// Copied from String::push
     /// This does **not** include the WTF-8 concatenation check.
     fn push_code_point_unchecked(&mut self, code_point: CodePoint) {
-        let bytes = unsafe {
-            char::from_u32_unchecked(code_point.value).encode_utf8()
+        let c = unsafe {
+            char::from_u32_unchecked(code_point.value)
         };
-        self.bytes.extend_from_slice(bytes.as_slice());
+        let mut bytes = [0; 4];
+        let bytes = c.encode_utf8(&mut bytes).as_bytes();
+        self.bytes.extend_from_slice(bytes)
     }
 
     #[inline]
@@ -738,15 +740,16 @@ impl<'a> Iterator for EncodeWide<'a> {
             return Some(tmp);
         }
 
+        let mut buf = [0; 2];
         self.code_points.next().map(|code_point| {
-            let n = unsafe {
-                char::from_u32_unchecked(code_point.value).encode_utf16()
+            let c = unsafe {
+                char::from_u32_unchecked(code_point.value)
             };
-            let n = n.as_slice();
-            if n.len() == 2 {
-                self.extra = n[1];
+            let n = c.encode_utf16(&mut buf).len();
+            if n == 2 {
+                self.extra = buf[1];
             }
-            n[0]
+            buf[0]
         })
     }
 
diff --git a/src/libstd/sys/unix/android.rs b/src/libstd/sys/unix/android.rs
index abbe3fc1846..10436723a81 100644
--- a/src/libstd/sys/unix/android.rs
+++ b/src/libstd/sys/unix/android.rs
@@ -28,10 +28,11 @@
 
 #![cfg(target_os = "android")]
 
-use libc::{c_int, sighandler_t};
+use libc::{c_int, c_void, sighandler_t, size_t, ssize_t};
+use libc::{ftruncate, pread, pwrite};
 
 use io;
-use sys::cvt_r;
+use super::{cvt, cvt_r};
 
 // The `log2` and `log2f` functions apparently appeared in android-18, or at
 // least you can see they're not present in the android-17 header [1] and they
@@ -96,13 +97,10 @@ pub unsafe fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t {
 //
 // If it doesn't we just fall back to `ftruncate`, generating an error for
 // too-large values.
+#[cfg(target_pointer_width = "32")]
 pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> {
     weak!(fn ftruncate64(c_int, i64) -> c_int);
 
-    extern {
-        fn ftruncate(fd: c_int, off: i32) -> c_int;
-    }
-
     unsafe {
         match ftruncate64.get() {
             Some(f) => cvt_r(|| f(fd, size as i64)).map(|_| ()),
@@ -117,3 +115,56 @@ pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> {
         }
     }
 }
+
+#[cfg(target_pointer_width = "64")]
+pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> {
+    unsafe {
+        cvt_r(|| ftruncate(fd, size as i64)).map(|_| ())
+    }
+}
+
+#[cfg(target_pointer_width = "32")]
+pub unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: size_t, offset: i64)
+    -> io::Result<ssize_t>
+{
+    use convert::TryInto;
+    weak!(fn pread64(c_int, *mut c_void, size_t, i64) -> ssize_t);
+    pread64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| {
+        if let Ok(o) = offset.try_into() {
+            cvt(pread(fd, buf, count, o))
+        } else {
+            Err(io::Error::new(io::ErrorKind::InvalidInput,
+                               "cannot pread >2GB"))
+        }
+    })
+}
+
+#[cfg(target_pointer_width = "32")]
+pub unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: size_t, offset: i64)
+    -> io::Result<ssize_t>
+{
+    use convert::TryInto;
+    weak!(fn pwrite64(c_int, *const c_void, size_t, i64) -> ssize_t);
+    pwrite64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| {
+        if let Ok(o) = offset.try_into() {
+            cvt(pwrite(fd, buf, count, o))
+        } else {
+            Err(io::Error::new(io::ErrorKind::InvalidInput,
+                               "cannot pwrite >2GB"))
+        }
+    })
+}
+
+#[cfg(target_pointer_width = "64")]
+pub unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: size_t, offset: i64)
+    -> io::Result<ssize_t>
+{
+    cvt(pread(fd, buf, count, offset))
+}
+
+#[cfg(target_pointer_width = "64")]
+pub unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: size_t, offset: i64)
+    -> io::Result<ssize_t>
+{
+    cvt(pwrite(fd, buf, count, offset))
+}
diff --git a/src/libstd/sys/unix/args.rs b/src/libstd/sys/unix/args.rs
new file mode 100644
index 00000000000..c04fd863674
--- /dev/null
+++ b/src/libstd/sys/unix/args.rs
@@ -0,0 +1,212 @@
+// Copyright 2012-2015 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 initialization and retreival of command line arguments.
+//!
+//! On some platforms these are stored during runtime startup,
+//! and on some they are retrieved from the system on demand.
+
+#![allow(dead_code)] // runtime init functions not used during testing
+
+use ffi::OsString;
+use marker::PhantomData;
+use vec;
+
+/// One-time global initialization.
+pub unsafe fn init(argc: isize, argv: *const *const u8) { imp::init(argc, argv) }
+
+/// One-time global cleanup.
+pub unsafe fn cleanup() { imp::cleanup() }
+
+/// Returns the command line arguments
+pub fn args() -> Args {
+    imp::args()
+}
+
+pub struct Args {
+    iter: vec::IntoIter<OsString>,
+    _dont_send_or_sync_me: PhantomData<*mut ()>,
+}
+
+impl Iterator for Args {
+    type Item = OsString;
+    fn next(&mut self) -> Option<OsString> { self.iter.next() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+}
+
+impl ExactSizeIterator for Args {
+    fn len(&self) -> usize { self.iter.len() }
+}
+
+impl DoubleEndedIterator for Args {
+    fn next_back(&mut self) -> Option<OsString> { self.iter.next_back() }
+}
+
+#[cfg(any(target_os = "linux",
+          target_os = "android",
+          target_os = "freebsd",
+          target_os = "dragonfly",
+          target_os = "bitrig",
+          target_os = "netbsd",
+          target_os = "openbsd",
+          target_os = "solaris",
+          target_os = "emscripten",
+          target_os = "haiku",
+          target_os = "fuchsia"))]
+mod imp {
+    use os::unix::prelude::*;
+    use mem;
+    use ffi::{CStr, OsString};
+    use marker::PhantomData;
+    use libc;
+    use super::Args;
+
+    use sys_common::mutex::Mutex;
+
+    static mut GLOBAL_ARGS_PTR: usize = 0;
+    static LOCK: Mutex = Mutex::new();
+
+    pub unsafe fn init(argc: isize, argv: *const *const u8) {
+        let args = (0..argc).map(|i| {
+            CStr::from_ptr(*argv.offset(i) as *const libc::c_char).to_bytes().to_vec()
+        }).collect();
+
+        LOCK.lock();
+        let ptr = get_global_ptr();
+        assert!((*ptr).is_none());
+        (*ptr) = Some(box args);
+        LOCK.unlock();
+    }
+
+    pub unsafe fn cleanup() {
+        LOCK.lock();
+        *get_global_ptr() = None;
+        LOCK.unlock();
+    }
+
+    pub fn args() -> Args {
+        let bytes = clone().unwrap_or(Vec::new());
+        let v: Vec<OsString> = bytes.into_iter().map(|v| {
+            OsStringExt::from_vec(v)
+        }).collect();
+        Args { iter: v.into_iter(), _dont_send_or_sync_me: PhantomData }
+    }
+
+    fn clone() -> Option<Vec<Vec<u8>>> {
+        unsafe {
+            LOCK.lock();
+            let ptr = get_global_ptr();
+            let ret = (*ptr).as_ref().map(|s| (**s).clone());
+            LOCK.unlock();
+            return ret
+        }
+    }
+
+    fn get_global_ptr() -> *mut Option<Box<Vec<Vec<u8>>>> {
+        unsafe { mem::transmute(&GLOBAL_ARGS_PTR) }
+    }
+
+}
+
+#[cfg(any(target_os = "macos",
+          target_os = "ios"))]
+mod imp {
+    use ffi::CStr;
+    use marker::PhantomData;
+    use libc;
+    use super::Args;
+
+    pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
+    }
+
+    pub fn cleanup() {
+    }
+
+    #[cfg(target_os = "macos")]
+    pub fn args() -> Args {
+        use os::unix::prelude::*;
+        extern {
+            // These functions are in crt_externs.h.
+            fn _NSGetArgc() -> *mut libc::c_int;
+            fn _NSGetArgv() -> *mut *mut *mut libc::c_char;
+        }
+
+        let vec = unsafe {
+            let (argc, argv) = (*_NSGetArgc() as isize,
+                                *_NSGetArgv() as *const *const libc::c_char);
+            (0.. argc as isize).map(|i| {
+                let bytes = CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec();
+                OsStringExt::from_vec(bytes)
+            }).collect::<Vec<_>>()
+        };
+        Args {
+            iter: vec.into_iter(),
+            _dont_send_or_sync_me: PhantomData,
+        }
+    }
+
+    // As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs
+    // and use underscores in their names - they're most probably
+    // are considered private and therefore should be avoided
+    // Here is another way to get arguments using Objective C
+    // runtime
+    //
+    // In general it looks like:
+    // res = Vec::new()
+    // let args = [[NSProcessInfo processInfo] arguments]
+    // for i in (0..[args count])
+    //      res.push([args objectAtIndex:i])
+    // res
+    #[cfg(target_os = "ios")]
+    pub fn args() -> Args {
+        use ffi::OsString;
+        use mem;
+        use str;
+
+        extern {
+            fn sel_registerName(name: *const libc::c_uchar) -> Sel;
+            fn objc_msgSend(obj: NsId, sel: Sel, ...) -> NsId;
+            fn objc_getClass(class_name: *const libc::c_uchar) -> NsId;
+        }
+
+        #[link(name = "Foundation", kind = "framework")]
+        #[link(name = "objc")]
+        #[cfg(not(cargobuild))]
+        extern {}
+
+        type Sel = *const libc::c_void;
+        type NsId = *const libc::c_void;
+
+        let mut res = Vec::new();
+
+        unsafe {
+            let process_info_sel = sel_registerName("processInfo\0".as_ptr());
+            let arguments_sel = sel_registerName("arguments\0".as_ptr());
+            let utf8_sel = sel_registerName("UTF8String\0".as_ptr());
+            let count_sel = sel_registerName("count\0".as_ptr());
+            let object_at_sel = sel_registerName("objectAtIndex:\0".as_ptr());
+
+            let klass = objc_getClass("NSProcessInfo\0".as_ptr());
+            let info = objc_msgSend(klass, process_info_sel);
+            let args = objc_msgSend(info, arguments_sel);
+
+            let cnt: usize = mem::transmute(objc_msgSend(args, count_sel));
+            for i in 0..cnt {
+                let tmp = objc_msgSend(args, object_at_sel, i);
+                let utf_c_str: *const libc::c_char =
+                    mem::transmute(objc_msgSend(tmp, utf8_sel));
+                let bytes = CStr::from_ptr(utf_c_str).to_bytes();
+                res.push(OsString::from(str::from_utf8(bytes).unwrap()))
+            }
+        }
+
+        Args { iter: res.into_iter(), _dont_send_or_sync_me: PhantomData }
+    }
+}
diff --git a/src/libstd/sys/unix/env.rs b/src/libstd/sys/unix/env.rs
new file mode 100644
index 00000000000..eff3a8c2a34
--- /dev/null
+++ b/src/libstd/sys/unix/env.rs
@@ -0,0 +1,184 @@
+// Copyright 2012-2015 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.
+
+#[cfg(target_os = "linux")]
+pub mod os {
+    pub const FAMILY: &'static str = "unix";
+    pub const OS: &'static str = "linux";
+    pub const DLL_PREFIX: &'static str = "lib";
+    pub const DLL_SUFFIX: &'static str = ".so";
+    pub const DLL_EXTENSION: &'static str = "so";
+    pub const EXE_SUFFIX: &'static str = "";
+    pub const EXE_EXTENSION: &'static str = "";
+}
+
+#[cfg(target_os = "macos")]
+pub mod os {
+    pub const FAMILY: &'static str = "unix";
+    pub const OS: &'static str = "macos";
+    pub const DLL_PREFIX: &'static str = "lib";
+    pub const DLL_SUFFIX: &'static str = ".dylib";
+    pub const DLL_EXTENSION: &'static str = "dylib";
+    pub const EXE_SUFFIX: &'static str = "";
+    pub const EXE_EXTENSION: &'static str = "";
+}
+
+#[cfg(target_os = "ios")]
+pub mod os {
+    pub const FAMILY: &'static str = "unix";
+    pub const OS: &'static str = "ios";
+    pub const DLL_PREFIX: &'static str = "lib";
+    pub const DLL_SUFFIX: &'static str = ".dylib";
+    pub const DLL_EXTENSION: &'static str = "dylib";
+    pub const EXE_SUFFIX: &'static str = "";
+    pub const EXE_EXTENSION: &'static str = "";
+}
+
+#[cfg(target_os = "freebsd")]
+pub mod os {
+    pub const FAMILY: &'static str = "unix";
+    pub const OS: &'static str = "freebsd";
+    pub const DLL_PREFIX: &'static str = "lib";
+    pub const DLL_SUFFIX: &'static str = ".so";
+    pub const DLL_EXTENSION: &'static str = "so";
+    pub const EXE_SUFFIX: &'static str = "";
+    pub const EXE_EXTENSION: &'static str = "";
+}
+
+#[cfg(target_os = "dragonfly")]
+pub mod os {
+    pub const FAMILY: &'static str = "unix";
+    pub const OS: &'static str = "dragonfly";
+    pub const DLL_PREFIX: &'static str = "lib";
+    pub const DLL_SUFFIX: &'static str = ".so";
+    pub const DLL_EXTENSION: &'static str = "so";
+    pub const EXE_SUFFIX: &'static str = "";
+    pub const EXE_EXTENSION: &'static str = "";
+}
+
+#[cfg(target_os = "bitrig")]
+pub mod os {
+    pub const FAMILY: &'static str = "unix";
+    pub const OS: &'static str = "bitrig";
+    pub const DLL_PREFIX: &'static str = "lib";
+    pub const DLL_SUFFIX: &'static str = ".so";
+    pub const DLL_EXTENSION: &'static str = "so";
+    pub const EXE_SUFFIX: &'static str = "";
+    pub const EXE_EXTENSION: &'static str = "";
+}
+
+#[cfg(target_os = "netbsd")]
+pub mod os {
+    pub const FAMILY: &'static str = "unix";
+    pub const OS: &'static str = "netbsd";
+    pub const DLL_PREFIX: &'static str = "lib";
+    pub const DLL_SUFFIX: &'static str = ".so";
+    pub const DLL_EXTENSION: &'static str = "so";
+    pub const EXE_SUFFIX: &'static str = "";
+    pub const EXE_EXTENSION: &'static str = "";
+}
+
+#[cfg(target_os = "openbsd")]
+pub mod os {
+    pub const FAMILY: &'static str = "unix";
+    pub const OS: &'static str = "openbsd";
+    pub const DLL_PREFIX: &'static str = "lib";
+    pub const DLL_SUFFIX: &'static str = ".so";
+    pub const DLL_EXTENSION: &'static str = "so";
+    pub const EXE_SUFFIX: &'static str = "";
+    pub const EXE_EXTENSION: &'static str = "";
+}
+
+#[cfg(target_os = "android")]
+pub mod os {
+    pub const FAMILY: &'static str = "unix";
+    pub const OS: &'static str = "android";
+    pub const DLL_PREFIX: &'static str = "lib";
+    pub const DLL_SUFFIX: &'static str = ".so";
+    pub const DLL_EXTENSION: &'static str = "so";
+    pub const EXE_SUFFIX: &'static str = "";
+    pub const EXE_EXTENSION: &'static str = "";
+}
+
+#[cfg(target_os = "solaris")]
+pub mod os {
+    pub const FAMILY: &'static str = "unix";
+    pub const OS: &'static str = "solaris";
+    pub const DLL_PREFIX: &'static str = "lib";
+    pub const DLL_SUFFIX: &'static str = ".so";
+    pub const DLL_EXTENSION: &'static str = "so";
+    pub const EXE_SUFFIX: &'static str = "";
+    pub const EXE_EXTENSION: &'static str = "";
+}
+
+#[cfg(all(target_os = "nacl", not(target_arch = "le32")))]
+pub mod os {
+    pub const FAMILY: &'static str = "unix";
+    pub const OS: &'static str = "nacl";
+    pub const DLL_PREFIX: &'static str = "lib";
+    pub const DLL_SUFFIX: &'static str = ".so";
+    pub const DLL_EXTENSION: &'static str = "so";
+    pub const EXE_SUFFIX: &'static str = ".nexe";
+    pub const EXE_EXTENSION: &'static str = "nexe";
+}
+#[cfg(all(target_os = "nacl", target_arch = "le32"))]
+pub mod os {
+    pub const FAMILY: &'static str = "unix";
+    pub const OS: &'static str = "pnacl";
+    pub const DLL_PREFIX: &'static str = "lib";
+    pub const DLL_SUFFIX: &'static str = ".pso";
+    pub const DLL_EXTENSION: &'static str = "pso";
+    pub const EXE_SUFFIX: &'static str = ".pexe";
+    pub const EXE_EXTENSION: &'static str = "pexe";
+}
+
+#[cfg(target_os = "haiku")]
+pub mod os {
+    pub const FAMILY: &'static str = "unix";
+    pub const OS: &'static str = "haiku";
+    pub const DLL_PREFIX: &'static str = "lib";
+    pub const DLL_SUFFIX: &'static str = ".so";
+    pub const DLL_EXTENSION: &'static str = "so";
+    pub const EXE_SUFFIX: &'static str = "";
+    pub const EXE_EXTENSION: &'static str = "";
+}
+
+#[cfg(all(target_os = "emscripten", target_arch = "asmjs"))]
+pub mod os {
+    pub const FAMILY: &'static str = "unix";
+    pub const OS: &'static str = "emscripten";
+    pub const DLL_PREFIX: &'static str = "lib";
+    pub const DLL_SUFFIX: &'static str = ".so";
+    pub const DLL_EXTENSION: &'static str = "so";
+    pub const EXE_SUFFIX: &'static str = ".js";
+    pub const EXE_EXTENSION: &'static str = "js";
+}
+
+#[cfg(all(target_os = "emscripten", target_arch = "wasm32"))]
+pub mod os {
+    pub const FAMILY: &'static str = "unix";
+    pub const OS: &'static str = "emscripten";
+    pub const DLL_PREFIX: &'static str = "lib";
+    pub const DLL_SUFFIX: &'static str = ".so";
+    pub const DLL_EXTENSION: &'static str = "so";
+    pub const EXE_SUFFIX: &'static str = ".js";
+    pub const EXE_EXTENSION: &'static str = "js";
+}
+
+#[cfg(target_os = "fuchsia")]
+pub mod os {
+    pub const FAMILY: &'static str = "unix";
+    pub const OS: &'static str = "fuchsia";
+    pub const DLL_PREFIX: &'static str = "lib";
+    pub const DLL_SUFFIX: &'static str = ".so";
+    pub const DLL_EXTENSION: &'static str = "so";
+    pub const EXE_SUFFIX: &'static str = "";
+    pub const EXE_EXTENSION: &'static str = "";
+}
diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs
index 77587918ac9..fcfab051588 100644
--- a/src/libstd/sys/unix/ext/fs.rs
+++ b/src/libstd/sys/unix/ext/fs.rs
@@ -20,6 +20,51 @@ use sys;
 use sys_common::{FromInner, AsInner, AsInnerMut};
 use sys::platform::fs::MetadataExt as UnixMetadataExt;
 
+/// Unix-specific extensions to `File`
+#[unstable(feature = "file_offset", issue = "35918")]
+pub trait FileExt {
+    /// Reads a number of bytes starting from a given offset.
+    ///
+    /// Returns the number of bytes read.
+    ///
+    /// The offset is relative to the start of the file and thus independent
+    /// from the current cursor.
+    ///
+    /// The current file cursor is not affected by this function.
+    ///
+    /// Note that similar to `File::read`, it is not an error to return with a
+    /// short read.
+    #[unstable(feature = "file_offset", issue = "35918")]
+    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
+
+    /// Writes a number of bytes starting from a given offset.
+    ///
+    /// Returns the number of bytes written.
+    ///
+    /// The offset is relative to the start of the file and thus independent
+    /// from the current cursor.
+    ///
+    /// The current file cursor is not affected by this function.
+    ///
+    /// When writing beyond the end of the file, the file is appropiately
+    /// extended and the intermediate bytes are initialized with the value 0.
+    ///
+    /// Note that similar to `File::write`, it is not an error to return a
+    /// short write.
+    #[unstable(feature = "file_offset", issue = "35918")]
+    fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
+}
+
+#[unstable(feature = "file_offset", issue = "35918")]
+impl FileExt for fs::File {
+    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
+        self.as_inner().read_at(buf, offset)
+    }
+    fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
+        self.as_inner().write_at(buf, offset)
+    }
+}
+
 /// Unix-specific extensions to `Permissions`
 #[stable(feature = "fs_ext", since = "1.1.0")]
 pub trait PermissionsExt {
diff --git a/src/libstd/sys/unix/ext/mod.rs b/src/libstd/sys/unix/ext/mod.rs
index 1be3d75d866..b2483f4e209 100644
--- a/src/libstd/sys/unix/ext/mod.rs
+++ b/src/libstd/sys/unix/ext/mod.rs
@@ -50,6 +50,8 @@ pub mod prelude {
     pub use super::fs::{PermissionsExt, OpenOptionsExt, MetadataExt, FileTypeExt};
     #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
     pub use super::fs::DirEntryExt;
+    #[doc(no_inline)] #[unstable(feature = "file_offset", issue = "35918")]
+    pub use super::fs::FileExt;
     #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
     pub use super::thread::JoinHandleExt;
     #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs
index 3f93fce1935..80f53da1cef 100644
--- a/src/libstd/sys/unix/ext/net.rs
+++ b/src/libstd/sys/unix/ext/net.rs
@@ -28,6 +28,17 @@ use sys::cvt;
 use sys::net::Socket;
 use sys_common::{AsInner, FromInner, IntoInner};
 
+#[cfg(any(target_os = "linux", target_os = "android",
+          target_os = "dragonfly", target_os = "freebsd",
+          target_os = "openbsd", target_os = "netbsd",
+          target_os = "haiku", target_os = "bitrig"))]
+use libc::MSG_NOSIGNAL;
+#[cfg(not(any(target_os = "linux", target_os = "android",
+              target_os = "dragonfly", target_os = "freebsd",
+              target_os = "openbsd", target_os = "netbsd",
+              target_os = "haiku", target_os = "bitrig")))]
+const MSG_NOSIGNAL: libc::c_int = 0x0;
+
 fn sun_path_offset() -> usize {
     unsafe {
         // Work with an actual instance of the type since using a null pointer is UB
@@ -690,7 +701,7 @@ impl UnixDatagram {
                 let count = cvt(libc::sendto(*d.0.as_inner(),
                                              buf.as_ptr() as *const _,
                                              buf.len(),
-                                             0,
+                                             MSG_NOSIGNAL,
                                              &addr as *const _ as *const _,
                                              len))?;
                 Ok(count as usize)
@@ -786,7 +797,7 @@ impl IntoRawFd for UnixDatagram {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod test {
     use thread;
     use io;
diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs
index 5bd92f2eb57..3a7c59d4e6d 100644
--- a/src/libstd/sys/unix/ext/process.rs
+++ b/src/libstd/sys/unix/ext/process.rs
@@ -161,21 +161,21 @@ impl AsRawFd for process::ChildStderr {
     }
 }
 
-#[stable(feature = "process_extensions", since = "1.2.0")]
+#[stable(feature = "into_raw_os", since = "1.4.0")]
 impl IntoRawFd for process::ChildStdin {
     fn into_raw_fd(self) -> RawFd {
         self.into_inner().into_fd().into_raw()
     }
 }
 
-#[stable(feature = "process_extensions", since = "1.2.0")]
+#[stable(feature = "into_raw_os", since = "1.4.0")]
 impl IntoRawFd for process::ChildStdout {
     fn into_raw_fd(self) -> RawFd {
         self.into_inner().into_fd().into_raw()
     }
 }
 
-#[stable(feature = "process_extensions", since = "1.2.0")]
+#[stable(feature = "into_raw_os", since = "1.4.0")]
 impl IntoRawFd for process::ChildStderr {
     fn into_raw_fd(self) -> RawFd {
         self.into_inner().into_fd().into_raw()
diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs
index b2b1f16f20a..41bb96fed16 100644
--- a/src/libstd/sys/unix/fd.rs
+++ b/src/libstd/sys/unix/fd.rs
@@ -11,7 +11,7 @@
 #![unstable(reason = "not public", issue = "0", feature = "fd")]
 
 use io::{self, Read};
-use libc::{self, c_int, size_t, c_void};
+use libc::{self, c_int, c_void};
 use mem;
 use sync::atomic::{AtomicBool, Ordering};
 use sys::cvt;
@@ -40,7 +40,7 @@ impl FileDesc {
         let ret = cvt(unsafe {
             libc::read(self.fd,
                        buf.as_mut_ptr() as *mut c_void,
-                       buf.len() as size_t)
+                       buf.len())
         })?;
         Ok(ret as usize)
     }
@@ -50,23 +50,77 @@ impl FileDesc {
         (&mut me).read_to_end(buf)
     }
 
+    pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
+        #[cfg(target_os = "android")]
+        use super::android::cvt_pread64;
+
+        #[cfg(not(target_os = "android"))]
+        unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: usize, offset: i64)
+            -> io::Result<isize>
+        {
+            #[cfg(any(target_os = "linux", target_os = "emscripten"))]
+            use libc::pread64;
+            #[cfg(not(any(target_os = "linux", target_os = "emscripten")))]
+            use libc::pread as pread64;
+            cvt(pread64(fd, buf, count, offset))
+        }
+
+        unsafe {
+            cvt_pread64(self.fd,
+                        buf.as_mut_ptr() as *mut c_void,
+                        buf.len(),
+                        offset as i64)
+                .map(|n| n as usize)
+        }
+    }
+
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         let ret = cvt(unsafe {
             libc::write(self.fd,
                         buf.as_ptr() as *const c_void,
-                        buf.len() as size_t)
+                        buf.len())
         })?;
         Ok(ret as usize)
     }
 
-    #[cfg(not(any(target_env = "newlib", target_os = "solaris", target_os = "emscripten")))]
+    pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
+        #[cfg(target_os = "android")]
+        use super::android::cvt_pwrite64;
+
+        #[cfg(not(target_os = "android"))]
+        unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: usize, offset: i64)
+            -> io::Result<isize>
+        {
+            #[cfg(any(target_os = "linux", target_os = "emscripten"))]
+            use libc::pwrite64;
+            #[cfg(not(any(target_os = "linux", target_os = "emscripten")))]
+            use libc::pwrite as pwrite64;
+            cvt(pwrite64(fd, buf, count, offset))
+        }
+
+        unsafe {
+            cvt_pwrite64(self.fd,
+                         buf.as_ptr() as *const c_void,
+                         buf.len(),
+                         offset as i64)
+                .map(|n| n as usize)
+        }
+    }
+
+    #[cfg(not(any(target_env = "newlib",
+                  target_os = "solaris",
+                  target_os = "emscripten",
+                  target_os = "haiku")))]
     pub fn set_cloexec(&self) -> io::Result<()> {
         unsafe {
             cvt(libc::ioctl(self.fd, libc::FIOCLEX))?;
             Ok(())
         }
     }
-    #[cfg(any(target_env = "newlib", target_os = "solaris", target_os = "emscripten"))]
+    #[cfg(any(target_env = "newlib",
+              target_os = "solaris",
+              target_os = "emscripten",
+              target_os = "haiku"))]
     pub fn set_cloexec(&self) -> io::Result<()> {
         unsafe {
             let previous = cvt(libc::fcntl(self.fd, libc::F_GETFD))?;
@@ -104,9 +158,9 @@ impl FileDesc {
         // resolve so we at least compile this.
         //
         // [1]: http://comments.gmane.org/gmane.linux.lib.musl.general/2963
-        #[cfg(target_os = "android")]
+        #[cfg(any(target_os = "android", target_os = "haiku"))]
         use libc::F_DUPFD as F_DUPFD_CLOEXEC;
-        #[cfg(not(target_os = "android"))]
+        #[cfg(not(any(target_os = "android", target_os="haiku")))]
         use libc::F_DUPFD_CLOEXEC;
 
         let make_filedesc = |fd| {
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index e6fe3eb112a..0b43fd2ac8c 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -193,6 +193,14 @@ impl FromInner<u32> for FilePermissions {
     }
 }
 
+impl fmt::Debug for ReadDir {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        // This will only be called from std::fs::ReadDir, which will add a "ReadDir()" frame.
+        // Thus the result will be e g 'ReadDir("/home")'
+        fmt::Debug::fmt(&*self.root, f)
+    }
+}
+
 impl Iterator for ReadDir {
     type Item = io::Result<DirEntry>;
 
@@ -279,7 +287,12 @@ impl DirEntry {
         stat(&self.path()).map(|m| m.file_type())
     }
 
-    #[cfg(not(target_os = "solaris"))]
+    #[cfg(target_os = "haiku")]
+    pub fn file_type(&self) -> io::Result<FileType> {
+        lstat(&self.path()).map(|m| m.file_type())
+    }
+
+    #[cfg(not(any(target_os = "solaris", target_os = "haiku")))]
     pub fn file_type(&self) -> io::Result<FileType> {
         match self.entry.d_type {
             libc::DT_CHR => Ok(FileType { mode: libc::S_IFCHR }),
@@ -298,7 +311,9 @@ impl DirEntry {
               target_os = "linux",
               target_os = "emscripten",
               target_os = "android",
-              target_os = "solaris"))]
+              target_os = "solaris",
+              target_os = "haiku",
+              target_os = "fuchsia"))]
     pub fn ino(&self) -> u64 {
         self.entry.d_ino as u64
     }
@@ -327,7 +342,9 @@ impl DirEntry {
     }
     #[cfg(any(target_os = "android",
               target_os = "linux",
-              target_os = "emscripten"))]
+              target_os = "emscripten",
+              target_os = "haiku",
+              target_os = "fuchsia"))]
     fn name_bytes(&self) -> &[u8] {
         unsafe {
             CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes()
@@ -476,10 +493,18 @@ impl File {
         self.0.read_to_end(buf)
     }
 
+    pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
+        self.0.read_at(buf, offset)
+    }
+
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         self.0.write(buf)
     }
 
+    pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
+        self.0.write_at(buf, offset)
+    }
+
     pub fn flush(&self) -> io::Result<()> { Ok(()) }
 
     pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
@@ -662,7 +687,7 @@ pub fn readlink(p: &Path) -> io::Result<PathBuf> {
 
     loop {
         let buf_read = cvt(unsafe {
-            libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity() as libc::size_t)
+            libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity())
         })? as usize;
 
         unsafe { buf.set_len(buf_read); }
diff --git a/src/libstd/sys/unix/memchr.rs b/src/libstd/sys/unix/memchr.rs
new file mode 100644
index 00000000000..aed04703ea1
--- /dev/null
+++ b/src/libstd/sys/unix/memchr.rs
@@ -0,0 +1,57 @@
+// Copyright 2015 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.
+//
+// Original implementation taken from rust-memchr
+// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
+
+pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
+    use libc;
+
+    let p = unsafe {
+        libc::memchr(
+            haystack.as_ptr() as *const libc::c_void,
+            needle as libc::c_int,
+            haystack.len())
+    };
+    if p.is_null() {
+        None
+    } else {
+        Some(p as usize - (haystack.as_ptr() as usize))
+    }
+}
+
+pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
+
+    #[cfg(target_os = "linux")]
+    fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
+        use libc;
+
+        // GNU's memrchr() will - unlike memchr() - error if haystack is empty.
+        if haystack.is_empty() {return None}
+        let p = unsafe {
+            libc::memrchr(
+                haystack.as_ptr() as *const libc::c_void,
+                needle as libc::c_int,
+                haystack.len())
+        };
+        if p.is_null() {
+            None
+        } else {
+            Some(p as usize - (haystack.as_ptr() as usize))
+        }
+    }
+
+    #[cfg(not(target_os = "linux"))]
+    fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
+        ::sys_common::memchr::fallback::memrchr(needle, haystack)
+    }
+
+    memrchr_specific(needle, haystack)
+}
diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs
index 23687e10e47..66bc9d4a491 100644
--- a/src/libstd/sys/unix/mod.rs
+++ b/src/libstd/sys/unix/mod.rs
@@ -17,6 +17,7 @@ use libc;
 #[cfg(target_os = "bitrig")]    pub use os::bitrig as platform;
 #[cfg(target_os = "dragonfly")] pub use os::dragonfly as platform;
 #[cfg(target_os = "freebsd")]   pub use os::freebsd as platform;
+#[cfg(target_os = "haiku")]     pub use os::haiku as platform;
 #[cfg(target_os = "ios")]       pub use os::ios as platform;
 #[cfg(target_os = "linux")]     pub use os::linux as platform;
 #[cfg(target_os = "macos")]     pub use os::macos as platform;
@@ -25,21 +26,26 @@ use libc;
 #[cfg(target_os = "openbsd")]   pub use os::openbsd as platform;
 #[cfg(target_os = "solaris")]   pub use os::solaris as platform;
 #[cfg(target_os = "emscripten")] pub use os::emscripten as platform;
+#[cfg(target_os = "fuchsia")]   pub use os::fuchsia as platform;
 
 #[macro_use]
 pub mod weak;
 
+pub mod args;
 pub mod android;
 #[cfg(any(not(cargobuild), feature = "backtrace"))]
 pub mod backtrace;
 pub mod condvar;
+pub mod env;
 pub mod ext;
 pub mod fd;
 pub mod fs;
+pub mod memchr;
 pub mod mutex;
 pub mod net;
 pub mod os;
 pub mod os_str;
+pub mod path;
 pub mod pipe;
 pub mod process;
 pub mod rand;
@@ -78,16 +84,16 @@ pub fn init() {
         unsafe {
             libc::write(libc::STDERR_FILENO,
                         msg.as_ptr() as *const libc::c_void,
-                        msg.len() as libc::size_t);
+                        msg.len());
             intrinsics::abort();
         }
     }
 
-    #[cfg(not(any(target_os = "nacl", target_os = "emscripten")))]
+    #[cfg(not(any(target_os = "nacl", target_os = "emscripten", target_os="fuchsia")))]
     unsafe fn reset_sigpipe() {
         assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != !0);
     }
-    #[cfg(any(target_os = "nacl", target_os = "emscripten"))]
+    #[cfg(any(target_os = "nacl", target_os = "emscripten", target_os="fuchsia"))]
     unsafe fn reset_sigpipe() {}
 }
 
diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs
index f124ea651ec..ad287bbec38 100644
--- a/src/libstd/sys/unix/net.rs
+++ b/src/libstd/sys/unix/net.rs
@@ -10,7 +10,7 @@
 
 use ffi::CStr;
 use io;
-use libc::{self, c_int, size_t, sockaddr, socklen_t};
+use libc::{self, c_int, size_t, sockaddr, socklen_t, EAI_SYSTEM};
 use net::{SocketAddr, Shutdown};
 use str;
 use sys::fd::FileDesc;
@@ -33,12 +33,25 @@ use libc::SOCK_CLOEXEC;
 #[cfg(not(target_os = "linux"))]
 const SOCK_CLOEXEC: c_int = 0;
 
+// Another conditional contant for name resolution: Macos et iOS use
+// SO_NOSIGPIPE as a setsockopt flag to disable SIGPIPE emission on socket.
+// Other platforms do otherwise.
+#[cfg(target_vendor = "apple")]
+use libc::SO_NOSIGPIPE;
+#[cfg(not(target_vendor = "apple"))]
+const SO_NOSIGPIPE: c_int = 0;
+
 pub struct Socket(FileDesc);
 
 pub fn init() {}
 
 pub fn cvt_gai(err: c_int) -> io::Result<()> {
-    if err == 0 { return Ok(()) }
+    if err == 0 {
+        return Ok(())
+    }
+    if err == EAI_SYSTEM {
+        return Err(io::Error::last_os_error())
+    }
 
     let detail = unsafe {
         str::from_utf8(CStr::from_ptr(libc::gai_strerror(err)).to_bytes()).unwrap()
@@ -76,7 +89,11 @@ impl Socket {
             let fd = cvt(libc::socket(fam, ty, 0))?;
             let fd = FileDesc::new(fd);
             fd.set_cloexec()?;
-            Ok(Socket(fd))
+            let socket = Socket(fd);
+            if cfg!(target_vendor = "apple") {
+                setsockopt(&socket, libc::SOL_SOCKET, SO_NOSIGPIPE, 1)?;
+            }
+            Ok(socket)
         }
     }
 
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
index 82606d2c728..e591f25cac1 100644
--- a/src/libstd/sys/unix/os.rs
+++ b/src/libstd/sys/unix/os.rs
@@ -38,7 +38,7 @@ static ENV_LOCK: Mutex = Mutex::new();
 
 extern {
     #[cfg(not(target_os = "dragonfly"))]
-    #[cfg_attr(any(target_os = "linux", target_os = "emscripten"),
+    #[cfg_attr(any(target_os = "linux", target_os = "emscripten", target_os = "fuchsia"),
                link_name = "__errno_location")]
     #[cfg_attr(any(target_os = "bitrig",
                    target_os = "netbsd",
@@ -51,6 +51,7 @@ extern {
                    target_os = "ios",
                    target_os = "freebsd"),
                link_name = "__error")]
+    #[cfg_attr(target_os = "haiku", link_name = "_errnop")]
     fn errno_location() -> *mut c_int;
 }
 
@@ -93,7 +94,7 @@ pub fn error_string(errno: i32) -> String {
 
     let p = buf.as_mut_ptr();
     unsafe {
-        if strerror_r(errno as c_int, p, buf.len() as libc::size_t) < 0 {
+        if strerror_r(errno as c_int, p, buf.len()) < 0 {
             panic!("strerror_r failure");
         }
 
@@ -107,7 +108,7 @@ pub fn getcwd() -> io::Result<PathBuf> {
     loop {
         unsafe {
             let ptr = buf.as_mut_ptr() as *mut libc::c_char;
-            if !libc::getcwd(ptr, buf.capacity() as libc::size_t).is_null() {
+            if !libc::getcwd(ptr, buf.capacity()).is_null() {
                 let len = CStr::from_ptr(buf.as_ptr() as *const libc::c_char).to_bytes().len();
                 buf.set_len(len);
                 buf.shrink_to_fit();
@@ -199,21 +200,20 @@ pub fn current_exe() -> io::Result<PathBuf> {
                        libc::KERN_PROC as c_int,
                        libc::KERN_PROC_PATHNAME as c_int,
                        -1 as c_int];
-        let mut sz: libc::size_t = 0;
+        let mut sz = 0;
         cvt(libc::sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
-                         ptr::null_mut(), &mut sz, ptr::null_mut(),
-                         0 as libc::size_t))?;
+                         ptr::null_mut(), &mut sz, ptr::null_mut(), 0))?;
         if sz == 0 {
             return Err(io::Error::last_os_error())
         }
-        let mut v: Vec<u8> = Vec::with_capacity(sz as usize);
+        let mut v: Vec<u8> = Vec::with_capacity(sz);
         cvt(libc::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(), 0 as libc::size_t))?;
+                         ptr::null_mut(), 0))?;
         if sz == 0 {
             return Err(io::Error::last_os_error());
         }
-        v.set_len(sz as usize - 1); // chop off trailing NUL
+        v.set_len(sz - 1); // chop off trailing NUL
         Ok(PathBuf::from(OsString::from_vec(v)))
     }
 }
@@ -303,123 +303,53 @@ pub fn current_exe() -> io::Result<PathBuf> {
     }
 }
 
-pub struct Args {
-    iter: vec::IntoIter<OsString>,
-    _dont_send_or_sync_me: PhantomData<*mut ()>,
-}
-
-impl Iterator for Args {
-    type Item = OsString;
-    fn next(&mut self) -> Option<OsString> { self.iter.next() }
-    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
-}
-
-impl ExactSizeIterator for Args {
-    fn len(&self) -> usize { self.iter.len() }
-}
-
-impl DoubleEndedIterator for Args {
-    fn next_back(&mut self) -> Option<OsString> { self.iter.next_back() }
-}
-
-/// Returns the command line arguments
-///
-/// Returns a list of the command line arguments.
-#[cfg(target_os = "macos")]
-pub fn args() -> Args {
-    extern {
-        // These functions are in crt_externs.h.
-        fn _NSGetArgc() -> *mut c_int;
-        fn _NSGetArgv() -> *mut *mut *mut c_char;
-    }
-
-    let vec = unsafe {
-        let (argc, argv) = (*_NSGetArgc() as isize,
-                            *_NSGetArgv() as *const *const c_char);
-        (0.. argc as isize).map(|i| {
-            let bytes = CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec();
-            OsStringExt::from_vec(bytes)
-        }).collect::<Vec<_>>()
-    };
-    Args {
-        iter: vec.into_iter(),
-        _dont_send_or_sync_me: PhantomData,
-    }
-}
-
-// As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs
-// and use underscores in their names - they're most probably
-// are considered private and therefore should be avoided
-// Here is another way to get arguments using Objective C
-// runtime
-//
-// In general it looks like:
-// res = Vec::new()
-// let args = [[NSProcessInfo processInfo] arguments]
-// for i in (0..[args count])
-//      res.push([args objectAtIndex:i])
-// res
-#[cfg(target_os = "ios")]
-pub fn args() -> Args {
-    use mem;
-
-    extern {
-        fn sel_registerName(name: *const libc::c_uchar) -> Sel;
-        fn objc_msgSend(obj: NsId, sel: Sel, ...) -> NsId;
-        fn objc_getClass(class_name: *const libc::c_uchar) -> NsId;
+#[cfg(target_os = "haiku")]
+pub fn current_exe() -> io::Result<PathBuf> {
+    // Use Haiku's image info functions
+    #[repr(C)]
+    struct image_info {
+        id: i32,
+        type_: i32,
+        sequence: i32,
+        init_order: i32,
+        init_routine: *mut libc::c_void,    // function pointer
+        term_routine: *mut libc::c_void,    // function pointer
+        device: libc::dev_t,
+        node: libc::ino_t,
+        name: [libc::c_char; 1024],         // MAXPATHLEN
+        text: *mut libc::c_void,
+        data: *mut libc::c_void,
+        text_size: i32,
+        data_size: i32,
+        api_version: i32,
+        abi: i32,
     }
 
-    #[link(name = "Foundation", kind = "framework")]
-    #[link(name = "objc")]
-    #[cfg(not(cargobuild))]
-    extern {}
-
-    type Sel = *const libc::c_void;
-    type NsId = *const libc::c_void;
-
-    let mut res = Vec::new();
-
     unsafe {
-        let process_info_sel = sel_registerName("processInfo\0".as_ptr());
-        let arguments_sel = sel_registerName("arguments\0".as_ptr());
-        let utf8_sel = sel_registerName("UTF8String\0".as_ptr());
-        let count_sel = sel_registerName("count\0".as_ptr());
-        let object_at_sel = sel_registerName("objectAtIndex:\0".as_ptr());
-
-        let klass = objc_getClass("NSProcessInfo\0".as_ptr());
-        let info = objc_msgSend(klass, process_info_sel);
-        let args = objc_msgSend(info, arguments_sel);
-
-        let cnt: usize = mem::transmute(objc_msgSend(args, count_sel));
-        for i in 0..cnt {
-            let tmp = objc_msgSend(args, object_at_sel, i);
-            let utf_c_str: *const libc::c_char =
-                mem::transmute(objc_msgSend(tmp, utf8_sel));
-            let bytes = CStr::from_ptr(utf_c_str).to_bytes();
-            res.push(OsString::from(str::from_utf8(bytes).unwrap()))
+        extern {
+            fn _get_next_image_info(team_id: i32, cookie: *mut i32,
+                info: *mut image_info, size: i32) -> i32;
         }
-    }
 
-    Args { iter: res.into_iter(), _dont_send_or_sync_me: PhantomData }
+        let mut info: image_info = mem::zeroed();
+        let mut cookie: i32 = 0;
+        // the executable can be found at team id 0
+        let result = _get_next_image_info(0, &mut cookie, &mut info,
+            mem::size_of::<image_info>() as i32);
+        if result != 0 {
+            use io::ErrorKind;
+            Err(io::Error::new(ErrorKind::Other, "Error getting executable path"))
+        } else {
+            let name = CStr::from_ptr(info.name.as_ptr()).to_bytes();
+            Ok(PathBuf::from(OsStr::from_bytes(name)))
+        }
+    }
 }
 
-#[cfg(any(target_os = "linux",
-          target_os = "android",
-          target_os = "freebsd",
-          target_os = "dragonfly",
-          target_os = "bitrig",
-          target_os = "netbsd",
-          target_os = "openbsd",
-          target_os = "solaris",
-          target_os = "nacl",
-          target_os = "emscripten"))]
-pub fn args() -> Args {
-    use sys_common;
-    let bytes = sys_common::args::clone().unwrap_or(Vec::new());
-    let v: Vec<OsString> = bytes.into_iter().map(|v| {
-        OsStringExt::from_vec(v)
-    }).collect();
-    Args { iter: v.into_iter(), _dont_send_or_sync_me: PhantomData }
+#[cfg(target_os = "fuchsia")]
+pub fn current_exe() -> io::Result<PathBuf> {
+    use io::ErrorKind;
+    Err(io::Error::new(ErrorKind::Other, "Not yet implemented on fuchsia"))
 }
 
 pub struct Env {
@@ -563,7 +493,7 @@ pub fn home_dir() -> Option<PathBuf> {
                               buf: &mut Vec<c_char>) -> Option<()> {
             let mut result = ptr::null_mut();
             match libc::getpwuid_r(me, passwd, buf.as_mut_ptr(),
-                                   buf.capacity() as libc::size_t,
+                                   buf.capacity(),
                                    &mut result) {
                 0 if !result.is_null() => Some(()),
                 _ => None
@@ -576,7 +506,7 @@ pub fn home_dir() -> Option<PathBuf> {
             // getpwuid_r semantics is different on Illumos/Solaris:
             // http://illumos.org/man/3c/getpwuid_r
             let result = libc::getpwuid_r(me, passwd, buf.as_mut_ptr(),
-                                          buf.capacity() as libc::size_t);
+                                          buf.capacity());
             if result.is_null() { None } else { Some(()) }
         }
 
diff --git a/src/libstd/sys/unix/path.rs b/src/libstd/sys/unix/path.rs
new file mode 100644
index 00000000000..bf9af7a4353
--- /dev/null
+++ b/src/libstd/sys/unix/path.rs
@@ -0,0 +1,29 @@
+// Copyright 2015 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 path::Prefix;
+use ffi::OsStr;
+
+#[inline]
+pub fn is_sep_byte(b: u8) -> bool {
+    b == b'/'
+}
+
+#[inline]
+pub fn is_verbatim_sep(b: u8) -> bool {
+    b == b'/'
+}
+
+pub fn parse_prefix(_: &OsStr) -> Option<Prefix> {
+    None
+}
+
+pub const MAIN_SEP_STR: &'static str = "/";
+pub const MAIN_SEP: char = '/';
diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs
index 50014f51f6c..dafc11d9cc8 100644
--- a/src/libstd/sys/unix/process.rs
+++ b/src/libstd/sys/unix/process.rs
@@ -369,7 +369,7 @@ impl Command {
         }
 
         // NaCl has no signal support.
-        if cfg!(not(target_os = "nacl")) {
+        if cfg!(not(any(target_os = "nacl", target_os = "emscripten"))) {
             // Reset signal handling so the child process starts in a
             // standardized state. libstd ignores SIGPIPE, and signal-handling
             // libraries often set a mask. Child processes inherit ignored
@@ -589,7 +589,7 @@ impl Process {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use super::*;
 
diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs
index 6b50ca9bcdf..3aebb8c18ec 100644
--- a/src/libstd/sys/unix/rand.rs
+++ b/src/libstd/sys/unix/rand.rs
@@ -27,7 +27,8 @@ fn next_u64(mut fill_buf: &mut FnMut(&mut [u8])) -> u64 {
 #[cfg(all(unix,
           not(target_os = "ios"),
           not(target_os = "openbsd"),
-          not(target_os = "freebsd")))]
+          not(target_os = "freebsd"),
+          not(target_os = "fuchsia")))]
 mod imp {
     use self::OsRngInner::*;
     use super::{next_u32, next_u64};
@@ -97,8 +98,8 @@ mod imp {
                     // full entropy pool
                     let reader = File::open("/dev/urandom").expect("Unable to open /dev/urandom");
                     let mut reader_rng = ReaderRng::new(reader);
-                    reader_rng.fill_bytes(& mut v[read..]);
-                    read += v.len() as usize;
+                    reader_rng.fill_bytes(&mut v[read..]);
+                    read += v.len();
                 } else {
                     panic!("unexpected getrandom error: {}", err);
                 }
@@ -281,7 +282,7 @@ mod imp {
         }
         fn fill_bytes(&mut self, v: &mut [u8]) {
             let ret = unsafe {
-                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t,
+                SecRandomCopyBytes(kSecRandomDefault, v.len(),
                                    v.as_mut_ptr())
             };
             if ret == -1 {
@@ -339,3 +340,54 @@ mod imp {
         }
     }
 }
+
+#[cfg(target_os = "fuchsia")]
+mod imp {
+    use super::{next_u32, next_u64};
+
+    use io;
+    use rand::Rng;
+
+    #[link(name = "magenta")]
+    extern {
+        fn mx_cprng_draw(buffer: *mut u8, len: usize) -> isize;
+    }
+
+    fn getrandom(buf: &mut [u8]) -> isize {
+        unsafe { mx_cprng_draw(buf.as_mut_ptr(), buf.len()) }
+    }
+
+    pub struct OsRng {
+        // dummy field to ensure that this struct cannot be constructed outside
+        // of this module
+        _dummy: (),
+    }
+
+    impl OsRng {
+        /// Create a new `OsRng`.
+        pub fn new() -> io::Result<OsRng> {
+            Ok(OsRng { _dummy: () })
+        }
+    }
+
+    impl Rng for OsRng {
+        fn next_u32(&mut self) -> u32 {
+            next_u32(&mut |v| self.fill_bytes(v))
+        }
+        fn next_u64(&mut self) -> u64 {
+            next_u64(&mut |v| self.fill_bytes(v))
+        }
+        fn fill_bytes(&mut self, v: &mut [u8]) {
+            let mut buf = v;
+            while !buf.is_empty() {
+                let ret = getrandom(buf);
+                if ret < 0 {
+                    panic!("kernel mx_cprng_draw call failed! (returned {}, buf.len() {})",
+                        ret, buf.len());
+                }
+                let move_buf = buf;
+                buf = &mut move_buf[(ret as usize)..];
+            }
+        }
+    }
+}
diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs
index 972bdbc3818..947ba2cc752 100644
--- a/src/libstd/sys/unix/stdio.rs
+++ b/src/libstd/sys/unix/stdio.rs
@@ -65,3 +65,5 @@ impl io::Write for Stderr {
     }
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
 }
+
+pub const EBADF_ERR: i32 = ::libc::EBADF as i32;
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index 5db7086e427..1642baa34d6 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -29,6 +29,20 @@ pub struct Thread {
 unsafe impl Send for Thread {}
 unsafe impl Sync for Thread {}
 
+// The pthread_attr_setstacksize symbol doesn't exist in the emscripten libc,
+// so we have to not link to it to satisfy emcc's ERROR_ON_UNDEFINED_SYMBOLS.
+#[cfg(not(target_os = "emscripten"))]
+unsafe fn pthread_attr_setstacksize(attr: *mut libc::pthread_attr_t,
+                                    stack_size: libc::size_t) -> libc::c_int {
+    libc::pthread_attr_setstacksize(attr, stack_size)
+}
+
+#[cfg(target_os = "emscripten")]
+unsafe fn pthread_attr_setstacksize(_attr: *mut libc::pthread_attr_t,
+                                    _stack_size: libc::size_t) -> libc::c_int {
+    panic!()
+}
+
 impl Thread {
     pub unsafe fn new<'a>(stack: usize, p: Box<FnBox() + 'a>)
                           -> io::Result<Thread> {
@@ -38,8 +52,8 @@ impl Thread {
         assert_eq!(libc::pthread_attr_init(&mut attr), 0);
 
         let stack_size = cmp::max(stack, min_stack_size(&attr));
-        match libc::pthread_attr_setstacksize(&mut attr,
-                                              stack_size as libc::size_t) {
+        match pthread_attr_setstacksize(&mut attr,
+                                        stack_size) {
             0 => {}
             n => {
                 assert_eq!(n, libc::EINVAL);
@@ -50,7 +64,6 @@ impl Thread {
                 let page_size = os::page_size();
                 let stack_size = (stack_size + page_size - 1) &
                                  (-(page_size as isize - 1) as usize - 1);
-                let stack_size = stack_size as libc::size_t;
                 assert_eq!(libc::pthread_attr_setstacksize(&mut attr,
                                                            stack_size), 0);
             }
@@ -115,9 +128,16 @@ impl Thread {
                                      name.as_ptr() as *mut libc::c_void);
         }
     }
-    #[cfg(any(target_env = "newlib", target_os = "solaris", target_os = "emscripten"))]
+    #[cfg(any(target_env = "newlib",
+              target_os = "solaris",
+              target_os = "haiku",
+              target_os = "emscripten"))]
+    pub fn set_name(_name: &CStr) {
+        // Newlib, Illumos, Haiku, and Emscripten have no way to set a thread name.
+    }
+    #[cfg(target_os = "fuchsia")]
     pub fn set_name(_name: &CStr) {
-        // Newlib, Illumos and Emscripten have no way to set a thread name.
+        // FIXME: determine whether Fuchsia has a way to set a thread name.
     }
 
     pub fn sleep(dur: Duration) {
@@ -247,12 +267,8 @@ pub mod guard {
         // Rellocate the last page of the stack.
         // This ensures SIGBUS will be raised on
         // stack overflow.
-        let result = mmap(stackaddr,
-                          psize as libc::size_t,
-                          PROT_NONE,
-                          MAP_PRIVATE | MAP_ANON | MAP_FIXED,
-                          -1,
-                          0);
+        let result = mmap(stackaddr, psize, PROT_NONE,
+                          MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
 
         if result != stackaddr || result == MAP_FAILED {
             panic!("failed to allocate a guard page");
@@ -276,8 +292,8 @@ pub mod guard {
 
     #[cfg(target_os = "macos")]
     pub unsafe fn current() -> Option<usize> {
-        Some((libc::pthread_get_stackaddr_np(libc::pthread_self()) as libc::size_t -
-              libc::pthread_get_stacksize_np(libc::pthread_self())) as usize)
+        Some((libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize -
+              libc::pthread_get_stacksize_np(libc::pthread_self())))
     }
 
     #[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
@@ -289,10 +305,10 @@ pub mod guard {
         let extra = if cfg!(target_os = "bitrig") {3} else {1} * os::page_size();
         Some(if libc::pthread_main_np() == 1 {
             // main thread
-            current_stack.ss_sp as usize - current_stack.ss_size as usize + extra
+            current_stack.ss_sp as usize - current_stack.ss_size + extra
         } else {
             // new thread
-            current_stack.ss_sp as usize - current_stack.ss_size as usize
+            current_stack.ss_sp as usize - current_stack.ss_size
         })
     }
 
@@ -318,11 +334,11 @@ pub mod guard {
                                                    &mut size), 0);
 
             ret = if cfg!(target_os = "freebsd") {
-                Some(stackaddr as usize - guardsize as usize)
+                Some(stackaddr as usize - guardsize)
             } else if cfg!(target_os = "netbsd") {
                 Some(stackaddr as usize)
             } else {
-                Some(stackaddr as usize + guardsize as usize)
+                Some(stackaddr as usize + guardsize)
             };
         }
         assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
@@ -341,8 +357,8 @@ fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize {
     weak!(fn __pthread_get_minstack(*const libc::pthread_attr_t) -> libc::size_t);
 
     match __pthread_get_minstack.get() {
-        None => libc::PTHREAD_STACK_MIN as usize,
-        Some(f) => unsafe { f(attr) as usize },
+        None => libc::PTHREAD_STACK_MIN,
+        Some(f) => unsafe { f(attr) },
     }
 }
 
@@ -351,7 +367,7 @@ fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize {
 #[cfg(all(not(target_os = "linux"),
           not(target_os = "netbsd")))]
 fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
-    libc::PTHREAD_STACK_MIN as usize
+    libc::PTHREAD_STACK_MIN
 }
 
 #[cfg(target_os = "netbsd")]
diff --git a/src/libstd/sys/windows/args.rs b/src/libstd/sys/windows/args.rs
new file mode 100644
index 00000000000..aa61f9adb82
--- /dev/null
+++ b/src/libstd/sys/windows/args.rs
@@ -0,0 +1,76 @@
+// Copyright 2012-2015 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(dead_code)] // runtime init functions not used during testing
+
+use os::windows::prelude::*;
+use sys::c;
+use slice;
+use ops::Range;
+use ffi::OsString;
+use libc::{c_int, c_void};
+
+pub unsafe fn init(_argc: isize, _argv: *const *const u8) { }
+
+pub unsafe fn cleanup() { }
+
+pub fn args() -> Args {
+    unsafe {
+        let mut nArgs: c_int = 0;
+        let lpCmdLine = c::GetCommandLineW();
+        let szArgList = c::CommandLineToArgvW(lpCmdLine, &mut nArgs);
+
+        // szArcList can be NULL if CommandLinToArgvW failed,
+        // but in that case nArgs is 0 so we won't actually
+        // try to read a null pointer
+        Args { cur: szArgList, range: 0..(nArgs as isize) }
+    }
+}
+
+pub struct Args {
+    range: Range<isize>,
+    cur: *mut *mut u16,
+}
+
+unsafe fn os_string_from_ptr(ptr: *mut u16) -> OsString {
+    let mut len = 0;
+    while *ptr.offset(len) != 0 { len += 1; }
+
+    // Push it onto the list.
+    let ptr = ptr as *const u16;
+    let buf = slice::from_raw_parts(ptr, len as usize);
+    OsStringExt::from_wide(buf)
+}
+
+impl Iterator for Args {
+    type Item = OsString;
+    fn next(&mut self) -> Option<OsString> {
+        self.range.next().map(|i| unsafe { os_string_from_ptr(*self.cur.offset(i)) } )
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
+}
+
+impl DoubleEndedIterator for Args {
+    fn next_back(&mut self) -> Option<OsString> {
+        self.range.next_back().map(|i| unsafe { os_string_from_ptr(*self.cur.offset(i)) } )
+    }
+}
+
+impl ExactSizeIterator for Args {
+    fn len(&self) -> usize { self.range.len() }
+}
+
+impl Drop for Args {
+    fn drop(&mut self) {
+        // self.cur can be null if CommandLineToArgvW previously failed,
+        // but LocalFree ignores NULL pointers
+        unsafe { c::LocalFree(self.cur as *mut c_void); }
+    }
+}
diff --git a/src/libstd/sys/windows/env.rs b/src/libstd/sys/windows/env.rs
new file mode 100644
index 00000000000..e6d74895774
--- /dev/null
+++ b/src/libstd/sys/windows/env.rs
@@ -0,0 +1,19 @@
+// Copyright 2012-2015 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.
+
+pub mod os {
+    pub const FAMILY: &'static str = "windows";
+    pub const OS: &'static str = "windows";
+    pub const DLL_PREFIX: &'static str = "";
+    pub const DLL_SUFFIX: &'static str = ".dll";
+    pub const DLL_EXTENSION: &'static str = "dll";
+    pub const EXE_SUFFIX: &'static str = ".exe";
+    pub const EXE_EXTENSION: &'static str = "exe";
+}
diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs
index 4388a0bdff2..1e2b8bf38fa 100644
--- a/src/libstd/sys/windows/ext/fs.rs
+++ b/src/libstd/sys/windows/ext/fs.rs
@@ -12,12 +12,61 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use fs::{OpenOptions, Metadata};
+use fs::{self, OpenOptions, Metadata};
 use io;
 use path::Path;
 use sys;
 use sys_common::{AsInnerMut, AsInner};
 
+/// Windows-specific extensions to `File`
+#[unstable(feature = "file_offset", issue = "35918")]
+pub trait FileExt {
+    /// Seeks to a given position and reads a number of bytes.
+    ///
+    /// Returns the number of bytes read.
+    ///
+    /// The offset is relative to the start of the file and thus independent
+    /// from the current cursor. The current cursor **is** affected by this
+    /// function, it is set to the end of the read.
+    ///
+    /// Reading beyond the end of the file will always return with a length of
+    /// 0.
+    ///
+    /// Note that similar to `File::read`, it is not an error to return with a
+    /// short read. When returning from such a short read, the file pointer is
+    /// still updated.
+    #[unstable(feature = "file_offset", issue = "35918")]
+    fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
+
+    /// Seeks to a given position and writes a number of bytes.
+    ///
+    /// Returns the number of bytes written.
+    ///
+    /// The offset is relative to the start of the file and thus independent
+    /// from the current cursor. The current cursor **is** affected by this
+    /// function, it is set to the end of the write.
+    ///
+    /// When writing beyond the end of the file, the file is appropiately
+    /// extended and the intermediate bytes are left uninitialized.
+    ///
+    /// Note that similar to `File::write`, it is not an error to return a
+    /// short write. When returning from such a short write, the file pointer
+    /// is still updated.
+    #[unstable(feature = "file_offset", issue = "35918")]
+    fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
+}
+
+#[unstable(feature = "file_offset", issue = "35918")]
+impl FileExt for fs::File {
+    fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
+        self.as_inner().read_at(buf, offset)
+    }
+
+    fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
+        self.as_inner().write_at(buf, offset)
+    }
+}
+
 /// Windows-specific extensions to `OpenOptions`
 #[stable(feature = "open_options_ext", since = "1.10.0")]
 pub trait OpenOptionsExt {
diff --git a/src/libstd/sys/windows/ext/mod.rs b/src/libstd/sys/windows/ext/mod.rs
index c3578fdfdb1..932bb5e9564 100644
--- a/src/libstd/sys/windows/ext/mod.rs
+++ b/src/libstd/sys/windows/ext/mod.rs
@@ -36,4 +36,6 @@ pub mod prelude {
     pub use super::ffi::{OsStrExt, OsStringExt};
     #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
     pub use super::fs::{OpenOptionsExt, MetadataExt};
+    #[doc(no_inline)] #[unstable(feature = "file_offset", issue = "35918")]
+    pub use super::fs::FileExt;
 }
diff --git a/src/libstd/sys/windows/ext/process.rs b/src/libstd/sys/windows/ext/process.rs
index 98166bf8cda..bce32959a23 100644
--- a/src/libstd/sys/windows/ext/process.rs
+++ b/src/libstd/sys/windows/ext/process.rs
@@ -33,7 +33,7 @@ impl AsRawHandle for process::Child {
     }
 }
 
-#[stable(feature = "process_extensions", since = "1.2.0")]
+#[stable(feature = "into_raw_os", since = "1.4.0")]
 impl IntoRawHandle for process::Child {
     fn into_raw_handle(self) -> RawHandle {
         self.into_inner().into_handle().into_raw() as *mut _
@@ -61,21 +61,21 @@ impl AsRawHandle for process::ChildStderr {
     }
 }
 
-#[stable(feature = "process_extensions", since = "1.2.0")]
+#[stable(feature = "into_raw_os", since = "1.4.0")]
 impl IntoRawHandle for process::ChildStdin {
     fn into_raw_handle(self) -> RawHandle {
         self.into_inner().into_handle().into_raw() as *mut _
     }
 }
 
-#[stable(feature = "process_extensions", since = "1.2.0")]
+#[stable(feature = "into_raw_os", since = "1.4.0")]
 impl IntoRawHandle for process::ChildStdout {
     fn into_raw_handle(self) -> RawHandle {
         self.into_inner().into_handle().into_raw() as *mut _
     }
 }
 
-#[stable(feature = "process_extensions", since = "1.2.0")]
+#[stable(feature = "into_raw_os", since = "1.4.0")]
 impl IntoRawHandle for process::ChildStderr {
     fn into_raw_handle(self) -> RawHandle {
         self.into_inner().into_handle().into_raw() as *mut _
@@ -91,7 +91,7 @@ pub trait ExitStatusExt {
     fn from_raw(raw: u32) -> Self;
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "exit_status_from", since = "1.12.0")]
 impl ExitStatusExt for process::ExitStatus {
     fn from_raw(raw: u32) -> Self {
         process::ExitStatus::from_inner(From::from(raw))
diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs
index 90a16853d56..98fd15f863b 100644
--- a/src/libstd/sys/windows/fs.rs
+++ b/src/libstd/sys/windows/fs.rs
@@ -81,6 +81,14 @@ pub struct FilePermissions { attrs: c::DWORD }
 
 pub struct DirBuilder;
 
+impl fmt::Debug for ReadDir {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        // This will only be called from std::fs::ReadDir, which will add a "ReadDir()" frame.
+        // Thus the result will be e g 'ReadDir("C:\")'
+        fmt::Debug::fmt(&*self.root, f)
+    }
+}
+
 impl Iterator for ReadDir {
     type Item = io::Result<DirEntry>;
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
@@ -311,6 +319,10 @@ impl File {
         self.handle.read(buf)
     }
 
+    pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
+        self.handle.read_at(buf, offset)
+    }
+
     pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
         self.handle.read_to_end(buf)
     }
@@ -319,6 +331,10 @@ impl File {
         self.handle.write(buf)
     }
 
+    pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
+        self.handle.write_at(buf, offset)
+    }
+
     pub fn flush(&self) -> io::Result<()> { Ok(()) }
 
     pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs
index 97e746ee345..10b86ba44bc 100644
--- a/src/libstd/sys/windows/handle.rs
+++ b/src/libstd/sys/windows/handle.rs
@@ -104,6 +104,23 @@ impl RawHandle {
         }
     }
 
+    pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
+        let mut read = 0;
+        let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
+        let res = unsafe {
+            let mut overlapped: c::OVERLAPPED = mem::zeroed();
+            overlapped.Offset = offset as u32;
+            overlapped.OffsetHigh = (offset >> 32) as u32;
+            cvt(c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID,
+                            len, &mut read, &mut overlapped))
+        };
+        match res {
+            Ok(_) => Ok(read as usize),
+            Err(ref e) if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32) => Ok(0),
+            Err(e) => Err(e),
+        }
+    }
+
     pub unsafe fn read_overlapped(&self,
                                   buf: &mut [u8],
                                   overlapped: *mut c::OVERLAPPED)
@@ -174,6 +191,19 @@ impl RawHandle {
         Ok(amt as usize)
     }
 
+    pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
+        let mut written = 0;
+        let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
+        unsafe {
+            let mut overlapped: c::OVERLAPPED = mem::zeroed();
+            overlapped.Offset = offset as u32;
+            overlapped.OffsetHigh = (offset >> 32) as u32;
+            cvt(c::WriteFile(self.0, buf.as_ptr() as c::LPVOID,
+                             len, &mut written, &mut overlapped))?;
+        }
+        Ok(written as usize)
+    }
+
     pub fn duplicate(&self, access: c::DWORD, inherit: bool,
                      options: c::DWORD) -> io::Result<Handle> {
         let mut ret = 0 as c::HANDLE;
diff --git a/src/libstd/sys/windows/memchr.rs b/src/libstd/sys/windows/memchr.rs
new file mode 100644
index 00000000000..5a5386acaa5
--- /dev/null
+++ b/src/libstd/sys/windows/memchr.rs
@@ -0,0 +1,15 @@
+// Copyright 2015 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.
+//
+// Original implementation taken from rust-memchr
+// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
+
+// Fallback memchr is fastest on windows
+pub use sys_common::memchr::fallback::{memchr, memrchr};
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs
index 9741a704e8f..9cd6e6ca176 100644
--- a/src/libstd/sys/windows/mod.rs
+++ b/src/libstd/sys/windows/mod.rs
@@ -18,17 +18,21 @@ use time::Duration;
 
 #[macro_use] pub mod compat;
 
+pub mod args;
 pub mod backtrace;
 pub mod c;
 pub mod condvar;
 pub mod dynamic_lib;
+pub mod env;
 pub mod ext;
 pub mod fs;
 pub mod handle;
+pub mod memchr;
 pub mod mutex;
 pub mod net;
 pub mod os;
 pub mod os_str;
+pub mod path;
 pub mod pipe;
 pub mod process;
 pub mod rand;
diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs
index 260fc3c4db6..7e28dd1e259 100644
--- a/src/libstd/sys/windows/os.rs
+++ b/src/libstd/sys/windows/os.rs
@@ -18,8 +18,6 @@ use error::Error as StdError;
 use ffi::{OsString, OsStr};
 use fmt;
 use io;
-use libc::{c_int, c_void};
-use ops::Range;
 use os::windows::ffi::EncodeWide;
 use path::{self, PathBuf};
 use ptr;
@@ -272,60 +270,6 @@ pub fn unsetenv(n: &OsStr) -> io::Result<()> {
     }).map(|_| ())
 }
 
-pub struct Args {
-    range: Range<isize>,
-    cur: *mut *mut u16,
-}
-
-unsafe fn os_string_from_ptr(ptr: *mut u16) -> OsString {
-    let mut len = 0;
-    while *ptr.offset(len) != 0 { len += 1; }
-
-    // Push it onto the list.
-    let ptr = ptr as *const u16;
-    let buf = slice::from_raw_parts(ptr, len as usize);
-    OsStringExt::from_wide(buf)
-}
-
-impl Iterator for Args {
-    type Item = OsString;
-    fn next(&mut self) -> Option<OsString> {
-        self.range.next().map(|i| unsafe { os_string_from_ptr(*self.cur.offset(i)) } )
-    }
-    fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
-}
-
-impl DoubleEndedIterator for Args {
-    fn next_back(&mut self) -> Option<OsString> {
-        self.range.next_back().map(|i| unsafe { os_string_from_ptr(*self.cur.offset(i)) } )
-    }
-}
-
-impl ExactSizeIterator for Args {
-    fn len(&self) -> usize { self.range.len() }
-}
-
-impl Drop for Args {
-    fn drop(&mut self) {
-        // self.cur can be null if CommandLineToArgvW previously failed,
-        // but LocalFree ignores NULL pointers
-        unsafe { c::LocalFree(self.cur as *mut c_void); }
-    }
-}
-
-pub fn args() -> Args {
-    unsafe {
-        let mut nArgs: c_int = 0;
-        let lpCmdLine = c::GetCommandLineW();
-        let szArgList = c::CommandLineToArgvW(lpCmdLine, &mut nArgs);
-
-        // szArcList can be NULL if CommandLinToArgvW failed,
-        // but in that case nArgs is 0 so we won't actually
-        // try to read a null pointer
-        Args { cur: szArgList, range: 0..(nArgs as isize) }
-    }
-}
-
 pub fn temp_dir() -> PathBuf {
     super::fill_utf16_buf(|buf, sz| unsafe {
         c::GetTempPathW(sz, buf)
diff --git a/src/libstd/sys/windows/path.rs b/src/libstd/sys/windows/path.rs
new file mode 100644
index 00000000000..2b47808451b
--- /dev/null
+++ b/src/libstd/sys/windows/path.rs
@@ -0,0 +1,108 @@
+// Copyright 2015 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 ascii::*;
+
+use path::Prefix;
+use ffi::OsStr;
+use mem;
+
+fn os_str_as_u8_slice(s: &OsStr) -> &[u8] {
+    unsafe { mem::transmute(s) }
+}
+unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr {
+    mem::transmute(s)
+}
+
+#[inline]
+pub fn is_sep_byte(b: u8) -> bool {
+    b == b'/' || b == b'\\'
+}
+
+#[inline]
+pub fn is_verbatim_sep(b: u8) -> bool {
+    b == b'\\'
+}
+
+pub fn parse_prefix<'a>(path: &'a OsStr) -> Option<Prefix> {
+    use path::Prefix::*;
+    unsafe {
+        // The unsafety here stems from converting between &OsStr and &[u8]
+        // and back. This is safe to do because (1) we only look at ASCII
+        // contents of the encoding and (2) new &OsStr values are produced
+        // only from ASCII-bounded slices of existing &OsStr values.
+        let mut path = os_str_as_u8_slice(path);
+
+        if path.starts_with(br"\\") {
+            // \\
+            path = &path[2..];
+            if path.starts_with(br"?\") {
+                // \\?\
+                path = &path[2..];
+                if path.starts_with(br"UNC\") {
+                    // \\?\UNC\server\share
+                    path = &path[4..];
+                    let (server, share) = match parse_two_comps(path, is_verbatim_sep) {
+                        Some((server, share)) =>
+                            (u8_slice_as_os_str(server), u8_slice_as_os_str(share)),
+                        None => (u8_slice_as_os_str(path), u8_slice_as_os_str(&[])),
+                    };
+                    return Some(VerbatimUNC(server, share));
+                } else {
+                    // \\?\path
+                    let idx = path.iter().position(|&b| b == b'\\');
+                    if idx == Some(2) && path[1] == b':' {
+                        let c = path[0];
+                        if c.is_ascii() && (c as char).is_alphabetic() {
+                            // \\?\C:\ path
+                            return Some(VerbatimDisk(c.to_ascii_uppercase()));
+                        }
+                    }
+                    let slice = &path[..idx.unwrap_or(path.len())];
+                    return Some(Verbatim(u8_slice_as_os_str(slice)));
+                }
+            } else if path.starts_with(b".\\") {
+                // \\.\path
+                path = &path[2..];
+                let pos = path.iter().position(|&b| b == b'\\');
+                let slice = &path[..pos.unwrap_or(path.len())];
+                return Some(DeviceNS(u8_slice_as_os_str(slice)));
+            }
+            match parse_two_comps(path, is_sep_byte) {
+                Some((server, share)) if !server.is_empty() && !share.is_empty() => {
+                    // \\server\share
+                    return Some(UNC(u8_slice_as_os_str(server), u8_slice_as_os_str(share)));
+                }
+                _ => (),
+            }
+        } else if path.get(1) == Some(& b':') {
+            // C:
+            let c = path[0];
+            if c.is_ascii() && (c as char).is_alphabetic() {
+                return Some(Disk(c.to_ascii_uppercase()));
+            }
+        }
+        return None;
+    }
+
+    fn parse_two_comps(mut path: &[u8], f: fn(u8) -> bool) -> Option<(&[u8], &[u8])> {
+        let first = match path.iter().position(|x| f(*x)) {
+            None => return None,
+            Some(x) => &path[..x],
+        };
+        path = &path[(first.len() + 1)..];
+        let idx = path.iter().position(|x| f(*x));
+        let second = &path[..idx.unwrap_or(path.len())];
+        Some((first, second))
+    }
+}
+
+pub const MAIN_SEP_STR: &'static str = "\\";
+pub const MAIN_SEP: char = '\\';
diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs
index 01249f05f62..5f097d2631d 100644
--- a/src/libstd/sys/windows/stdio.rs
+++ b/src/libstd/sys/windows/stdio.rs
@@ -205,3 +205,5 @@ impl Output {
 fn invalid_encoding() -> io::Error {
     io::Error::new(io::ErrorKind::InvalidData, "text was not valid unicode")
 }
+
+pub const EBADF_ERR: i32 = ::sys::c::ERROR_INVALID_HANDLE as i32;
diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs
index c44dee49f14..54d3f793045 100644
--- a/src/libstd/thread/local.rs
+++ b/src/libstd/thread/local.rs
@@ -358,36 +358,8 @@ pub mod elf {
         }
     }
 
-    // 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 {
-            #[linkage = "extern_weak"]
-            static __dso_handle: *mut u8;
-            #[linkage = "extern_weak"]
-            static __cxa_thread_atexit_impl: *const libc::c_void;
-        }
-        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 libc::c_void, F>(__cxa_thread_atexit_impl)
-            (dtor, t, &__dso_handle as *const _ as *mut _);
-            return
-        }
-
+    #[cfg(any(target_os = "linux", target_os = "fuchsia"))]
+    unsafe fn register_dtor_fallback(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
         // 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.
@@ -397,6 +369,8 @@ pub mod elf {
         // *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.
+        use sys_common::thread_local as os;
+
         static DTORS: os::StaticKey = os::StaticKey::new(Some(run_dtors));
         type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>;
         if DTORS.get().is_null() {
@@ -418,6 +392,37 @@ pub mod elf {
         }
     }
 
+    // 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;
+
+        extern {
+            #[linkage = "extern_weak"]
+            static __dso_handle: *mut u8;
+            #[linkage = "extern_weak"]
+            static __cxa_thread_atexit_impl: *const libc::c_void;
+        }
+        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 libc::c_void, F>(__cxa_thread_atexit_impl)
+            (dtor, t, &__dso_handle as *const _ as *mut _);
+            return
+        }
+        register_dtor_fallback(t, dtor);
+    }
+
     // 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.
@@ -430,6 +435,13 @@ pub mod elf {
         _tlv_atexit(dtor, t);
     }
 
+    // Just use the thread_local fallback implementation, at least until there's
+    // a more direct implementation.
+    #[cfg(target_os = "fuchsia")]
+    unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
+        register_dtor_fallback(t, dtor);
+    }
+
     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
@@ -524,7 +536,7 @@ pub mod os {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use sync::mpsc::{channel, Sender};
     use cell::{Cell, UnsafeCell};
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index d8e021bb04f..150482e4af4 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -151,7 +151,7 @@
 //!
 //! [`Cell`]: ../cell/struct.Cell.html
 //! [`RefCell`]: ../cell/struct.RefCell.html
-//! [`thread_local!`]: ../macro.thread_local!.html
+//! [`thread_local!`]: ../macro.thread_local.html
 //! [`with`]: struct.LocalKey.html#method.with
 
 #![stable(feature = "rust1", since = "1.0.0")]
@@ -166,6 +166,7 @@ use panicking;
 use str;
 use sync::{Mutex, Condvar, Arc};
 use sys::thread as imp;
+use sys_common::mutex;
 use sys_common::thread_info;
 use sys_common::util;
 use sys_common::{AsInner, IntoInner};
@@ -525,12 +526,52 @@ pub fn park_timeout(dur: Duration) {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+// ThreadId
+////////////////////////////////////////////////////////////////////////////////
+
+/// A unique identifier for a running thread.
+///
+/// A `ThreadId` is an opaque object that has a unique value for each thread
+/// that creates one. `ThreadId`s do not correspond to a thread's system-
+/// designated identifier.
+#[unstable(feature = "thread_id", issue = "21507")]
+#[derive(Eq, PartialEq, Copy, Clone)]
+pub struct ThreadId(u64);
+
+impl ThreadId {
+    // Generate a new unique thread ID.
+    fn new() -> ThreadId {
+        static GUARD: mutex::Mutex = mutex::Mutex::new();
+        static mut COUNTER: u64 = 0;
+
+        unsafe {
+            GUARD.lock();
+
+            // If we somehow use up all our bits, panic so that we're not
+            // covering up subtle bugs of IDs being reused.
+            if COUNTER == ::u64::MAX {
+                GUARD.unlock();
+                panic!("failed to generate unique thread ID: bitspace exhausted");
+            }
+
+            let id = COUNTER;
+            COUNTER += 1;
+
+            GUARD.unlock();
+
+            ThreadId(id)
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
 // Thread
 ////////////////////////////////////////////////////////////////////////////////
 
 /// The internal representation of a `Thread` handle
 struct Inner {
     name: Option<CString>,      // Guaranteed to be UTF-8
+    id: ThreadId,
     lock: Mutex<bool>,          // true when there is a buffered unpark
     cvar: Condvar,
 }
@@ -551,6 +592,7 @@ impl Thread {
         Thread {
             inner: Arc::new(Inner {
                 name: cname,
+                id: ThreadId::new(),
                 lock: Mutex::new(false),
                 cvar: Condvar::new(),
             })
@@ -569,6 +611,12 @@ impl Thread {
         }
     }
 
+    /// Gets the thread's unique identifier.
+    #[unstable(feature = "thread_id", issue = "21507")]
+    pub fn id(&self) -> ThreadId {
+        self.inner.id
+    }
+
     /// Gets the thread's name.
     ///
     /// # Examples
@@ -741,7 +789,7 @@ fn _assert_sync_and_send() {
 // Tests
 ////////////////////////////////////////////////////////////////////////////////
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use any::Any;
     use sync::mpsc::{channel, Sender};
@@ -977,6 +1025,17 @@ mod tests {
         thread::sleep(Duration::from_millis(2));
     }
 
+    #[test]
+    fn test_thread_id_equal() {
+        assert!(thread::current().id() == thread::current().id());
+    }
+
+    #[test]
+    fn test_thread_id_not_equal() {
+        let spawned_id = thread::spawn(|| thread::current().id()).join().unwrap();
+        assert!(thread::current().id() != spawned_id);
+    }
+
     // NOTE: the corresponding test for stderr is in run-pass/thread-stderr, due
     // to the test harness apparently interfering with stderr configuration.
 }
diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs
index 246c57ab238..10a0c567e14 100644
--- a/src/libstd/time/duration.rs
+++ b/src/libstd/time/duration.rs
@@ -83,7 +83,7 @@ impl Duration {
 
     /// Returns the number of whole seconds represented by this duration.
     ///
-    /// The extra precision represented by this duration is ignored (e.g. extra
+    /// The extra precision represented by this duration is ignored (i.e. extra
     /// nanoseconds are not represented in the returned value).
     #[stable(feature = "duration", since = "1.3.0")]
     #[inline]
@@ -93,7 +93,7 @@ impl Duration {
     ///
     /// This method does **not** return the length of the duration when
     /// represented by nanoseconds. The returned number always represents a
-    /// fractional portion of a second (e.g. it is less than one billion).
+    /// fractional portion of a second (i.e. it is less than one billion).
     #[stable(feature = "duration", since = "1.3.0")]
     #[inline]
     pub fn subsec_nanos(&self) -> u32 { self.nanos }
diff --git a/src/libstd/time/mod.rs b/src/libstd/time/mod.rs
index 154f603c84f..6854f1e14fa 100644
--- a/src/libstd/time/mod.rs
+++ b/src/libstd/time/mod.rs
@@ -118,7 +118,7 @@ pub struct Instant(time::Instant);
 pub struct SystemTime(time::SystemTime);
 
 /// An error returned from the `duration_since` method on `SystemTime`,
-/// used to learn about why how far in the opposite direction a timestamp lies.
+/// used to learn how far in the opposite direction a system time lies.
 #[derive(Clone, Debug)]
 #[stable(feature = "time2", since = "1.8.0")]
 pub struct SystemTimeError(Duration);