about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/Cargo.toml9
-rw-r--r--src/libstd/ascii.rs807
-rw-r--r--src/libstd/build.rs20
-rw-r--r--src/libstd/collections/hash/map.rs115
-rw-r--r--src/libstd/collections/hash/table.rs36
-rw-r--r--src/libstd/env.rs4
-rw-r--r--src/libstd/error.rs16
-rw-r--r--src/libstd/f32.rs185
-rw-r--r--src/libstd/f64.rs125
-rw-r--r--src/libstd/ffi/c_str.rs331
-rw-r--r--src/libstd/ffi/mod.rs151
-rw-r--r--src/libstd/ffi/os_str.rs126
-rw-r--r--src/libstd/fs.rs21
-rw-r--r--src/libstd/heap.rs11
-rw-r--r--src/libstd/io/buffered.rs25
-rw-r--r--src/libstd/io/cursor.rs25
-rw-r--r--src/libstd/io/impls.rs8
-rw-r--r--src/libstd/io/mod.rs57
-rw-r--r--src/libstd/io/stdio.rs4
-rw-r--r--src/libstd/lib.rs35
-rw-r--r--src/libstd/macros.rs60
-rw-r--r--src/libstd/net/addr.rs2
-rw-r--r--src/libstd/net/ip.rs3
-rw-r--r--src/libstd/net/tcp.rs96
-rw-r--r--src/libstd/net/udp.rs39
-rw-r--r--src/libstd/os/linux/fs.rs242
-rw-r--r--src/libstd/os/mod.rs79
-rw-r--r--src/libstd/os/nacl/fs.rs128
-rw-r--r--src/libstd/os/nacl/raw.rs56
-rw-r--r--src/libstd/panic.rs6
-rw-r--r--src/libstd/path.rs85
-rw-r--r--src/libstd/primitive_docs.rs7
-rw-r--r--src/libstd/process.rs265
-rw-r--r--src/libstd/rand/mod.rs286
-rw-r--r--src/libstd/rt.rs1
-rw-r--r--src/libstd/sync/mpsc/cache_aligned.rs37
-rw-r--r--src/libstd/sync/mpsc/mod.rs118
-rw-r--r--src/libstd/sync/mpsc/select.rs18
-rw-r--r--src/libstd/sync/mpsc/spsc_queue.rs153
-rw-r--r--src/libstd/sync/mpsc/stream.rs105
-rw-r--r--src/libstd/sync/mutex.rs48
-rw-r--r--src/libstd/sync/once.rs95
-rw-r--r--src/libstd/sync/rwlock.rs41
-rw-r--r--src/libstd/sys/mod.rs106
-rw-r--r--src/libstd/sys/redox/backtrace/tracing.rs4
-rw-r--r--src/libstd/sys/redox/cmath.rs43
-rw-r--r--src/libstd/sys/redox/condvar.rs57
-rw-r--r--src/libstd/sys/redox/fast_thread_local.rs2
-rw-r--r--src/libstd/sys/redox/fs.rs3
-rw-r--r--src/libstd/sys/redox/mod.rs4
-rw-r--r--src/libstd/sys/redox/os.rs8
-rw-r--r--src/libstd/sys/redox/os_str.rs24
-rw-r--r--src/libstd/sys/redox/rand.rs48
-rw-r--r--src/libstd/sys/redox/stdio.rs5
-rw-r--r--src/libstd/sys/unix/backtrace/printing/dladdr.rs5
-rw-r--r--src/libstd/sys/unix/backtrace/printing/mod.rs2
-rw-r--r--src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs4
-rw-r--r--src/libstd/sys/unix/backtrace/tracing/gcc_s.rs4
-rw-r--r--src/libstd/sys/unix/cmath.rs43
-rw-r--r--src/libstd/sys/unix/condvar.rs5
-rw-r--r--src/libstd/sys/unix/env.rs21
-rw-r--r--src/libstd/sys/unix/ext/fs.rs362
-rw-r--r--src/libstd/sys/unix/ext/mod.rs10
-rw-r--r--src/libstd/sys/unix/ext/process.rs6
-rw-r--r--src/libstd/sys/unix/fs.rs4
-rw-r--r--src/libstd/sys/unix/l4re.rs4
-rw-r--r--src/libstd/sys/unix/mod.rs9
-rw-r--r--src/libstd/sys/unix/net.rs92
-rw-r--r--src/libstd/sys/unix/os.rs39
-rw-r--r--src/libstd/sys/unix/os_str.rs24
-rw-r--r--src/libstd/sys/unix/process/process_common.rs1
-rw-r--r--src/libstd/sys/unix/process/process_fuchsia.rs10
-rw-r--r--src/libstd/sys/unix/process/process_unix.rs4
-rw-r--r--src/libstd/sys/unix/process/zircon.rs25
-rw-r--r--src/libstd/sys/unix/rand.rs340
-rw-r--r--src/libstd/sys/unix/stdio.rs5
-rw-r--r--src/libstd/sys/unix/thread.rs4
-rw-r--r--src/libstd/sys/unix/time.rs4
-rw-r--r--src/libstd/sys/wasm/args.rs90
-rw-r--r--src/libstd/sys/wasm/backtrace.rs37
-rw-r--r--src/libstd/sys/wasm/cmath.rs119
-rw-r--r--src/libstd/sys/wasm/condvar.rs43
-rw-r--r--src/libstd/sys/wasm/env.rs19
-rw-r--r--src/libstd/sys/wasm/fs.rs304
-rw-r--r--src/libstd/sys/wasm/memchr.rs (renamed from src/libstd/os/nacl/mod.rs)9
-rw-r--r--src/libstd/sys/wasm/mod.rs104
-rw-r--r--src/libstd/sys/wasm/mutex.rs79
-rw-r--r--src/libstd/sys/wasm/net.rs337
-rw-r--r--src/libstd/sys/wasm/os.rs136
-rw-r--r--src/libstd/sys/wasm/os_str.rs183
-rw-r--r--src/libstd/sys/wasm/path.rs29
-rw-r--r--src/libstd/sys/wasm/pipe.rs35
-rw-r--r--src/libstd/sys/wasm/process.rs151
-rw-r--r--src/libstd/sys/wasm/rwlock.rs82
-rw-r--r--src/libstd/sys/wasm/stack_overflow.rs23
-rw-r--r--src/libstd/sys/wasm/stdio.rs92
-rw-r--r--src/libstd/sys/wasm/thread.rs48
-rw-r--r--src/libstd/sys/wasm/thread_local.rs50
-rw-r--r--src/libstd/sys/wasm/time.rs63
-rw-r--r--src/libstd/sys/windows/backtrace/mod.rs4
-rw-r--r--src/libstd/sys/windows/backtrace/printing/msvc.rs6
-rw-r--r--src/libstd/sys/windows/c.rs33
-rw-r--r--src/libstd/sys/windows/cmath.rs103
-rw-r--r--src/libstd/sys/windows/ext/ffi.rs56
-rw-r--r--src/libstd/sys/windows/ext/fs.rs6
-rw-r--r--src/libstd/sys/windows/fs.rs8
-rw-r--r--src/libstd/sys/windows/mod.rs6
-rw-r--r--src/libstd/sys/windows/os.rs4
-rw-r--r--src/libstd/sys/windows/os_str.rs24
-rw-r--r--src/libstd/sys/windows/path.rs2
-rw-r--r--src/libstd/sys/windows/pipe.rs18
-rw-r--r--src/libstd/sys/windows/process.rs2
-rw-r--r--src/libstd/sys/windows/rand.rs70
-rw-r--r--src/libstd/sys/windows/stdio.rs5
-rw-r--r--src/libstd/sys/windows/thread.rs2
-rw-r--r--src/libstd/sys/windows/thread_local.rs3
-rw-r--r--src/libstd/sys_common/backtrace.rs35
-rw-r--r--src/libstd/sys_common/gnu/libbacktrace.rs8
-rw-r--r--src/libstd/sys_common/mod.rs14
-rw-r--r--src/libstd/sys_common/net.rs13
-rw-r--r--src/libstd/sys_common/poison.rs57
-rw-r--r--src/libstd/sys_common/remutex.rs13
-rw-r--r--src/libstd/sys_common/thread.rs6
-rw-r--r--src/libstd/sys_common/thread_local.rs2
-rw-r--r--src/libstd/sys_common/wtf8.rs14
-rw-r--r--src/libstd/thread/local.rs10
-rw-r--r--src/libstd/thread/mod.rs113
127 files changed, 5628 insertions, 2454 deletions
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index fb276448ffa..3430ecabcbe 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -3,6 +3,9 @@ authors = ["The Rust Project Developers"]
 name = "std"
 version = "0.0.0"
 build = "build.rs"
+license = "MIT/Apache-2.0"
+repository = "https://github.com/rust-lang/rust.git"
+description = "The Rust Standard Library"
 
 [lib]
 name = "std"
@@ -15,15 +18,16 @@ alloc_jemalloc = { path = "../liballoc_jemalloc", optional = true }
 alloc_system = { path = "../liballoc_system" }
 panic_unwind = { path = "../libpanic_unwind", optional = true }
 panic_abort = { path = "../libpanic_abort" }
-collections = { path = "../libcollections" }
 core = { path = "../libcore" }
 libc = { path = "../rustc/libc_shim" }
-rand = { path = "../librand" }
 compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
 profiler_builtins = { path = "../libprofiler_builtins", optional = true }
 std_unicode = { path = "../libstd_unicode" }
 unwind = { path = "../libunwind" }
 
+[dev-dependencies]
+rand = "0.3"
+
 [target.x86_64-apple-darwin.dependencies]
 rustc_asan = { path = "../librustc_asan" }
 rustc_tsan = { path = "../librustc_tsan" }
@@ -36,7 +40,6 @@ rustc_tsan = { path = "../librustc_tsan" }
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-cc = "1.0"
 
 [features]
 backtrace = []
diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs
index 4e3781ecafa..92507a73bae 100644
--- a/src/libstd/ascii.rs
+++ b/src/libstd/ascii.rs
@@ -38,8 +38,8 @@ use iter::FusedIterator;
 /// ```
 /// use std::ascii::AsciiExt;
 ///
-/// assert_eq!("café".to_ascii_uppercase(), "CAFÉ");
-/// assert_eq!("café".to_ascii_uppercase(), "CAFé");
+/// assert_eq!(AsciiExt::to_ascii_uppercase("café"), "CAFÉ");
+/// assert_eq!(AsciiExt::to_ascii_uppercase("café"), "CAFé");
 /// ```
 ///
 /// In the first example, the lowercased string is represented `"cafe\u{301}"`
@@ -60,19 +60,10 @@ pub trait AsciiExt {
 
     /// Checks if the value is within the ASCII range.
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// use std::ascii::AsciiExt;
-    ///
-    /// let ascii = 'a';
-    /// let non_ascii = '❤';
-    /// let int_ascii = 97;
-    ///
-    /// assert!(ascii.is_ascii());
-    /// assert!(!non_ascii.is_ascii());
-    /// assert!(int_ascii.is_ascii());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn is_ascii(&self) -> bool;
 
@@ -86,19 +77,10 @@ pub trait AsciiExt {
     /// To uppercase ASCII characters in addition to non-ASCII characters, use
     /// [`str::to_uppercase`].
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ascii::AsciiExt;
-    ///
-    /// let ascii = 'a';
-    /// let non_ascii = '❤';
-    /// let int_ascii = 97;
+    /// # Note
     ///
-    /// assert_eq!('A', ascii.to_ascii_uppercase());
-    /// assert_eq!('❤', non_ascii.to_ascii_uppercase());
-    /// assert_eq!(65, int_ascii.to_ascii_uppercase());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     ///
     /// [`make_ascii_uppercase`]: #tymethod.make_ascii_uppercase
     /// [`str::to_uppercase`]: ../primitive.str.html#method.to_uppercase
@@ -115,19 +97,10 @@ pub trait AsciiExt {
     /// To lowercase ASCII characters in addition to non-ASCII characters, use
     /// [`str::to_lowercase`].
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// use std::ascii::AsciiExt;
-    ///
-    /// let ascii = 'A';
-    /// let non_ascii = '❤';
-    /// let int_ascii = 65;
-    ///
-    /// assert_eq!('a', ascii.to_ascii_lowercase());
-    /// assert_eq!('❤', non_ascii.to_ascii_lowercase());
-    /// assert_eq!(97, int_ascii.to_ascii_lowercase());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     ///
     /// [`make_ascii_lowercase`]: #tymethod.make_ascii_lowercase
     /// [`str::to_lowercase`]: ../primitive.str.html#method.to_lowercase
@@ -139,20 +112,10 @@ pub trait AsciiExt {
     /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
     /// but without allocating and copying temporaries.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ascii::AsciiExt;
+    /// # Note
     ///
-    /// let ascii1 = 'A';
-    /// let ascii2 = 'a';
-    /// let ascii3 = 'A';
-    /// let ascii4 = 'z';
-    ///
-    /// assert!(ascii1.eq_ignore_ascii_case(&ascii2));
-    /// assert!(ascii1.eq_ignore_ascii_case(&ascii3));
-    /// assert!(!ascii1.eq_ignore_ascii_case(&ascii4));
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn eq_ignore_ascii_case(&self, other: &Self) -> bool;
 
@@ -164,17 +127,10 @@ pub trait AsciiExt {
     /// To return a new uppercased value without modifying the existing one, use
     /// [`to_ascii_uppercase`].
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ascii::AsciiExt;
-    ///
-    /// let mut ascii = 'a';
+    /// # Note
     ///
-    /// ascii.make_ascii_uppercase();
-    ///
-    /// assert_eq!('A', ascii);
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     ///
     /// [`to_ascii_uppercase`]: #tymethod.to_ascii_uppercase
     #[stable(feature = "ascii", since = "1.9.0")]
@@ -188,17 +144,10 @@ pub trait AsciiExt {
     /// To return a new lowercased value without modifying the existing one, use
     /// [`to_ascii_lowercase`].
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ascii::AsciiExt;
-    ///
-    /// let mut ascii = 'A';
+    /// # Note
     ///
-    /// ascii.make_ascii_lowercase();
-    ///
-    /// assert_eq!('a', ascii);
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     ///
     /// [`to_ascii_lowercase`]: #tymethod.to_ascii_lowercase
     #[stable(feature = "ascii", since = "1.9.0")]
@@ -209,32 +158,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII alphabetic.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
+    /// # Note
     ///
-    /// assert!(A.is_ascii_alphabetic());
-    /// assert!(G.is_ascii_alphabetic());
-    /// assert!(a.is_ascii_alphabetic());
-    /// assert!(g.is_ascii_alphabetic());
-    /// assert!(!zero.is_ascii_alphabetic());
-    /// assert!(!percent.is_ascii_alphabetic());
-    /// assert!(!space.is_ascii_alphabetic());
-    /// assert!(!lf.is_ascii_alphabetic());
-    /// assert!(!esc.is_ascii_alphabetic());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_alphabetic(&self) -> bool { unimplemented!(); }
 
@@ -243,32 +170,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII uppercase.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
+    /// # Note
     ///
-    /// assert!(A.is_ascii_uppercase());
-    /// assert!(G.is_ascii_uppercase());
-    /// assert!(!a.is_ascii_uppercase());
-    /// assert!(!g.is_ascii_uppercase());
-    /// assert!(!zero.is_ascii_uppercase());
-    /// assert!(!percent.is_ascii_uppercase());
-    /// assert!(!space.is_ascii_uppercase());
-    /// assert!(!lf.is_ascii_uppercase());
-    /// assert!(!esc.is_ascii_uppercase());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_uppercase(&self) -> bool { unimplemented!(); }
 
@@ -277,32 +182,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII lowercase.
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
-    ///
-    /// assert!(!A.is_ascii_lowercase());
-    /// assert!(!G.is_ascii_lowercase());
-    /// assert!(a.is_ascii_lowercase());
-    /// assert!(g.is_ascii_lowercase());
-    /// assert!(!zero.is_ascii_lowercase());
-    /// assert!(!percent.is_ascii_lowercase());
-    /// assert!(!space.is_ascii_lowercase());
-    /// assert!(!lf.is_ascii_lowercase());
-    /// assert!(!esc.is_ascii_lowercase());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_lowercase(&self) -> bool { unimplemented!(); }
 
@@ -312,32 +195,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII alphanumeric.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
+    /// # Note
     ///
-    /// assert!(A.is_ascii_alphanumeric());
-    /// assert!(G.is_ascii_alphanumeric());
-    /// assert!(a.is_ascii_alphanumeric());
-    /// assert!(g.is_ascii_alphanumeric());
-    /// assert!(zero.is_ascii_alphanumeric());
-    /// assert!(!percent.is_ascii_alphanumeric());
-    /// assert!(!space.is_ascii_alphanumeric());
-    /// assert!(!lf.is_ascii_alphanumeric());
-    /// assert!(!esc.is_ascii_alphanumeric());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_alphanumeric(&self) -> bool { unimplemented!(); }
 
@@ -346,32 +207,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII digits.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
+    /// # Note
     ///
-    /// assert!(!A.is_ascii_digit());
-    /// assert!(!G.is_ascii_digit());
-    /// assert!(!a.is_ascii_digit());
-    /// assert!(!g.is_ascii_digit());
-    /// assert!(zero.is_ascii_digit());
-    /// assert!(!percent.is_ascii_digit());
-    /// assert!(!space.is_ascii_digit());
-    /// assert!(!lf.is_ascii_digit());
-    /// assert!(!esc.is_ascii_digit());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_digit(&self) -> bool { unimplemented!(); }
 
@@ -381,69 +220,27 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII hex digits.
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
-    ///
-    /// assert!(A.is_ascii_hexdigit());
-    /// assert!(!G.is_ascii_hexdigit());
-    /// assert!(a.is_ascii_hexdigit());
-    /// assert!(!g.is_ascii_hexdigit());
-    /// assert!(zero.is_ascii_hexdigit());
-    /// assert!(!percent.is_ascii_hexdigit());
-    /// assert!(!space.is_ascii_hexdigit());
-    /// assert!(!lf.is_ascii_hexdigit());
-    /// assert!(!esc.is_ascii_hexdigit());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_hexdigit(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII punctuation character:
+    ///
     /// U+0021 ... U+002F `! " # $ % & ' ( ) * + , - . /`
     /// U+003A ... U+0040 `: ; < = > ? @`
-    /// U+005B ... U+0060 `[ \\ ] ^ _ \``
+    /// U+005B ... U+0060 ``[ \\ ] ^ _ ` ``
     /// U+007B ... U+007E `{ | } ~`
+    ///
     /// For strings, true if all characters in the string are
     /// ASCII punctuation.
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
-    ///
-    /// assert!(!A.is_ascii_punctuation());
-    /// assert!(!G.is_ascii_punctuation());
-    /// assert!(!a.is_ascii_punctuation());
-    /// assert!(!g.is_ascii_punctuation());
-    /// assert!(!zero.is_ascii_punctuation());
-    /// assert!(percent.is_ascii_punctuation());
-    /// assert!(!space.is_ascii_punctuation());
-    /// assert!(!lf.is_ascii_punctuation());
-    /// assert!(!esc.is_ascii_punctuation());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_punctuation(&self) -> bool { unimplemented!(); }
 
@@ -452,32 +249,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII punctuation.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
+    /// # Note
     ///
-    /// assert!(A.is_ascii_graphic());
-    /// assert!(G.is_ascii_graphic());
-    /// assert!(a.is_ascii_graphic());
-    /// assert!(g.is_ascii_graphic());
-    /// assert!(zero.is_ascii_graphic());
-    /// assert!(percent.is_ascii_graphic());
-    /// assert!(!space.is_ascii_graphic());
-    /// assert!(!lf.is_ascii_graphic());
-    /// assert!(!esc.is_ascii_graphic());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_graphic(&self) -> bool { unimplemented!(); }
 
@@ -503,32 +278,10 @@ pub trait AsciiExt {
     /// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
     /// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
+    /// # Note
     ///
-    /// assert!(!A.is_ascii_whitespace());
-    /// assert!(!G.is_ascii_whitespace());
-    /// assert!(!a.is_ascii_whitespace());
-    /// assert!(!g.is_ascii_whitespace());
-    /// assert!(!zero.is_ascii_whitespace());
-    /// assert!(!percent.is_ascii_whitespace());
-    /// assert!(space.is_ascii_whitespace());
-    /// assert!(lf.is_ascii_whitespace());
-    /// assert!(!esc.is_ascii_whitespace());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_whitespace(&self) -> bool { unimplemented!(); }
 
@@ -537,168 +290,91 @@ pub trait AsciiExt {
     /// Note that most ASCII whitespace characters are control
     /// characters, but SPACE is not.
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
-    ///
-    /// assert!(!A.is_ascii_control());
-    /// assert!(!G.is_ascii_control());
-    /// assert!(!a.is_ascii_control());
-    /// assert!(!g.is_ascii_control());
-    /// assert!(!zero.is_ascii_control());
-    /// assert!(!percent.is_ascii_control());
-    /// assert!(!space.is_ascii_control());
-    /// assert!(lf.is_ascii_control());
-    /// assert!(esc.is_ascii_control());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_control(&self) -> bool { unimplemented!(); }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsciiExt for str {
-    type Owned = String;
-
-    #[inline]
-    fn is_ascii(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii())
-    }
+macro_rules! delegating_ascii_methods {
+    () => {
+        #[inline]
+        fn is_ascii(&self) -> bool { self.is_ascii() }
 
-    #[inline]
-    fn to_ascii_uppercase(&self) -> String {
-        let mut bytes = self.as_bytes().to_vec();
-        bytes.make_ascii_uppercase();
-        // make_ascii_uppercase() preserves the UTF-8 invariant.
-        unsafe { String::from_utf8_unchecked(bytes) }
-    }
+        #[inline]
+        fn to_ascii_uppercase(&self) -> Self::Owned { self.to_ascii_uppercase() }
 
-    #[inline]
-    fn to_ascii_lowercase(&self) -> String {
-        let mut bytes = self.as_bytes().to_vec();
-        bytes.make_ascii_lowercase();
-        // make_ascii_uppercase() preserves the UTF-8 invariant.
-        unsafe { String::from_utf8_unchecked(bytes) }
-    }
+        #[inline]
+        fn to_ascii_lowercase(&self) -> Self::Owned { self.to_ascii_lowercase() }
 
-    #[inline]
-    fn eq_ignore_ascii_case(&self, other: &str) -> bool {
-        self.as_bytes().eq_ignore_ascii_case(other.as_bytes())
-    }
+        #[inline]
+        fn eq_ignore_ascii_case(&self, o: &Self) -> bool { self.eq_ignore_ascii_case(o) }
 
-    fn make_ascii_uppercase(&mut self) {
-        let me = unsafe { self.as_bytes_mut() };
-        me.make_ascii_uppercase()
-    }
+        #[inline]
+        fn make_ascii_uppercase(&mut self) { self.make_ascii_uppercase(); }
 
-    fn make_ascii_lowercase(&mut self) {
-        let me = unsafe { self.as_bytes_mut() };
-        me.make_ascii_lowercase()
+        #[inline]
+        fn make_ascii_lowercase(&mut self) { self.make_ascii_lowercase(); }
     }
+}
 
-    #[inline]
-    fn is_ascii_alphabetic(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_alphabetic())
-    }
+macro_rules! delegating_ascii_ctype_methods {
+    () => {
+        #[inline]
+        fn is_ascii_alphabetic(&self) -> bool { self.is_ascii_alphabetic() }
 
-    #[inline]
-    fn is_ascii_uppercase(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_uppercase())
-    }
+        #[inline]
+        fn is_ascii_uppercase(&self) -> bool { self.is_ascii_uppercase() }
 
-    #[inline]
-    fn is_ascii_lowercase(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_lowercase())
-    }
+        #[inline]
+        fn is_ascii_lowercase(&self) -> bool { self.is_ascii_lowercase() }
 
-    #[inline]
-    fn is_ascii_alphanumeric(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_alphanumeric())
-    }
+        #[inline]
+        fn is_ascii_alphanumeric(&self) -> bool { self.is_ascii_alphanumeric() }
 
-    #[inline]
-    fn is_ascii_digit(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_digit())
-    }
+        #[inline]
+        fn is_ascii_digit(&self) -> bool { self.is_ascii_digit() }
 
-    #[inline]
-    fn is_ascii_hexdigit(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_hexdigit())
-    }
+        #[inline]
+        fn is_ascii_hexdigit(&self) -> bool { self.is_ascii_hexdigit() }
 
-    #[inline]
-    fn is_ascii_punctuation(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_punctuation())
-    }
+        #[inline]
+        fn is_ascii_punctuation(&self) -> bool { self.is_ascii_punctuation() }
 
-    #[inline]
-    fn is_ascii_graphic(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_graphic())
-    }
+        #[inline]
+        fn is_ascii_graphic(&self) -> bool { self.is_ascii_graphic() }
 
-    #[inline]
-    fn is_ascii_whitespace(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_whitespace())
-    }
+        #[inline]
+        fn is_ascii_whitespace(&self) -> bool { self.is_ascii_whitespace() }
 
-    #[inline]
-    fn is_ascii_control(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_control())
+        #[inline]
+        fn is_ascii_control(&self) -> bool { self.is_ascii_control() }
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl AsciiExt for [u8] {
-    type Owned = Vec<u8>;
-    #[inline]
-    fn is_ascii(&self) -> bool {
-        self.iter().all(|b| b.is_ascii())
-    }
+impl AsciiExt for u8 {
+    type Owned = u8;
 
-    #[inline]
-    fn to_ascii_uppercase(&self) -> Vec<u8> {
-        let mut me = self.to_vec();
-        me.make_ascii_uppercase();
-        return me
-    }
+    delegating_ascii_methods!();
+    delegating_ascii_ctype_methods!();
+}
 
-    #[inline]
-    fn to_ascii_lowercase(&self) -> Vec<u8> {
-        let mut me = self.to_vec();
-        me.make_ascii_lowercase();
-        return me
-    }
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsciiExt for char {
+    type Owned = char;
 
-    #[inline]
-    fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool {
-        self.len() == other.len() &&
-        self.iter().zip(other).all(|(a, b)| {
-            a.eq_ignore_ascii_case(b)
-        })
-    }
+    delegating_ascii_methods!();
+    delegating_ascii_ctype_methods!();
+}
 
-    fn make_ascii_uppercase(&mut self) {
-        for byte in self {
-            byte.make_ascii_uppercase();
-        }
-    }
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsciiExt for [u8] {
+    type Owned = Vec<u8>;
 
-    fn make_ascii_lowercase(&mut self) {
-        for byte in self {
-            byte.make_ascii_lowercase();
-        }
-    }
+    delegating_ascii_methods!();
 
     #[inline]
     fn is_ascii_alphabetic(&self) -> bool {
@@ -752,198 +428,59 @@ impl AsciiExt for [u8] {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl AsciiExt for u8 {
-    type Owned = u8;
-    #[inline]
-    fn is_ascii(&self) -> bool { *self & 128 == 0 }
-    #[inline]
-    fn to_ascii_uppercase(&self) -> u8 { ASCII_UPPERCASE_MAP[*self as usize] }
-    #[inline]
-    fn to_ascii_lowercase(&self) -> u8 { ASCII_LOWERCASE_MAP[*self as usize] }
-    #[inline]
-    fn eq_ignore_ascii_case(&self, other: &u8) -> bool {
-        self.to_ascii_lowercase() == other.to_ascii_lowercase()
-    }
-    #[inline]
-    fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); }
-    #[inline]
-    fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); }
-
-    #[inline]
-    fn is_ascii_alphabetic(&self) -> bool {
-        if *self >= 0x80 { return false; }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            L|Lx|U|Ux => true,
-            _ => false
-        }
-    }
-
-    #[inline]
-    fn is_ascii_uppercase(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            U|Ux => true,
-            _ => false
-        }
-    }
-
-    #[inline]
-    fn is_ascii_lowercase(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            L|Lx => true,
-            _ => false
-        }
-    }
-
-    #[inline]
-    fn is_ascii_alphanumeric(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            D|L|Lx|U|Ux => true,
-            _ => false
-        }
-    }
-
-    #[inline]
-    fn is_ascii_digit(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            D => true,
-            _ => false
-        }
-    }
-
-    #[inline]
-    fn is_ascii_hexdigit(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            D|Lx|Ux => true,
-            _ => false
-        }
-    }
-
-    #[inline]
-    fn is_ascii_punctuation(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            P => true,
-            _ => false
-        }
-    }
-
-    #[inline]
-    fn is_ascii_graphic(&self) -> bool {
-        if *self >= 0x80 { return false; }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            Ux|U|Lx|L|D|P => true,
-            _ => false
-        }
-    }
-
-    #[inline]
-    fn is_ascii_whitespace(&self) -> bool {
-        if *self >= 0x80 { return false; }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            Cw|W => true,
-            _ => false
-        }
-    }
-
-    #[inline]
-    fn is_ascii_control(&self) -> bool {
-        if *self >= 0x80 { return false; }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            C|Cw => true,
-            _ => false
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsciiExt for char {
-    type Owned = char;
-    #[inline]
-    fn is_ascii(&self) -> bool {
-        *self as u32 <= 0x7F
-    }
-
-    #[inline]
-    fn to_ascii_uppercase(&self) -> char {
-        if self.is_ascii() {
-            (*self as u8).to_ascii_uppercase() as char
-        } else {
-            *self
-        }
-    }
-
-    #[inline]
-    fn to_ascii_lowercase(&self) -> char {
-        if self.is_ascii() {
-            (*self as u8).to_ascii_lowercase() as char
-        } else {
-            *self
-        }
-    }
-
-    #[inline]
-    fn eq_ignore_ascii_case(&self, other: &char) -> bool {
-        self.to_ascii_lowercase() == other.to_ascii_lowercase()
-    }
+impl AsciiExt for str {
+    type Owned = String;
 
-    #[inline]
-    fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); }
-    #[inline]
-    fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); }
+    delegating_ascii_methods!();
 
     #[inline]
     fn is_ascii_alphabetic(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_alphabetic()
+        self.bytes().all(|b| b.is_ascii_alphabetic())
     }
 
     #[inline]
     fn is_ascii_uppercase(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_uppercase()
+        self.bytes().all(|b| b.is_ascii_uppercase())
     }
 
     #[inline]
     fn is_ascii_lowercase(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_lowercase()
+        self.bytes().all(|b| b.is_ascii_lowercase())
     }
 
     #[inline]
     fn is_ascii_alphanumeric(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_alphanumeric()
+        self.bytes().all(|b| b.is_ascii_alphanumeric())
     }
 
     #[inline]
     fn is_ascii_digit(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_digit()
+        self.bytes().all(|b| b.is_ascii_digit())
     }
 
     #[inline]
     fn is_ascii_hexdigit(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_hexdigit()
+        self.bytes().all(|b| b.is_ascii_hexdigit())
     }
 
     #[inline]
     fn is_ascii_punctuation(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_punctuation()
+        self.bytes().all(|b| b.is_ascii_punctuation())
     }
 
     #[inline]
     fn is_ascii_graphic(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_graphic()
+        self.bytes().all(|b| b.is_ascii_graphic())
     }
 
     #[inline]
     fn is_ascii_whitespace(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_whitespace()
+        self.bytes().all(|b| b.is_ascii_whitespace())
     }
 
     #[inline]
     fn is_ascii_control(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_control()
+        self.bytes().all(|b| b.is_ascii_control())
     }
 }
 
@@ -1064,112 +601,12 @@ impl fmt::Debug for EscapeDefault {
 }
 
 
-static ASCII_LOWERCASE_MAP: [u8; 256] = [
-    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-    b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
-    b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
-    b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
-    b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
-    b'@',
-
-          b'a', b'b', b'c', b'd', b'e', b'f', b'g',
-    b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
-    b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
-    b'x', b'y', b'z',
-
-                      b'[', b'\\', b']', b'^', b'_',
-    b'`', b'a', b'b', b'c', b'd', b'e', b'f', b'g',
-    b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
-    b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
-    b'x', b'y', b'z', b'{', b'|', b'}', b'~', 0x7f,
-    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
-    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
-    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
-    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
-    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
-    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
-    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
-    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
-    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
-    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
-    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
-    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
-    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
-    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
-    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
-];
-
-static ASCII_UPPERCASE_MAP: [u8; 256] = [
-    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-    b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
-    b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
-    b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
-    b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
-    b'@', b'A', b'B', b'C', b'D', b'E', b'F', b'G',
-    b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
-    b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
-    b'X', b'Y', b'Z', b'[', b'\\', b']', b'^', b'_',
-    b'`',
-
-          b'A', b'B', b'C', b'D', b'E', b'F', b'G',
-    b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
-    b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
-    b'X', b'Y', b'Z',
-
-                      b'{', b'|', b'}', b'~', 0x7f,
-    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
-    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
-    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
-    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
-    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
-    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
-    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
-    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
-    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
-    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
-    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
-    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
-    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
-    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
-    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
-];
-
-enum AsciiCharacterClass {
-    C,  // control
-    Cw, // control whitespace
-    W,  // whitespace
-    D,  // digit
-    L,  // lowercase
-    Lx, // lowercase hex digit
-    U,  // uppercase
-    Ux, // uppercase hex digit
-    P,  // punctuation
-}
-use self::AsciiCharacterClass::*;
-
-static ASCII_CHARACTER_CLASS: [AsciiCharacterClass; 128] = [
-//  _0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _a _b _c _d _e _f
-    C, C, C, C, C, C, C, C, C, Cw,Cw,C, Cw,Cw,C, C, // 0_
-    C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // 1_
-    W, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, // 2_
-    D, D, D, D, D, D, D, D, D, D, P, P, P, P, P, P, // 3_
-    P, Ux,Ux,Ux,Ux,Ux,Ux,U, U, U, U, U, U, U, U, U, // 4_
-    U, U, U, U, U, U, U, U, U, U, U, P, P, P, P, P, // 5_
-    P, Lx,Lx,Lx,Lx,Lx,Lx,L, L, L, L, L, L, L, L, L, // 6_
-    L, L, L, L, L, L, L, L, L, L, L, P, P, P, P, C, // 7_
-];
-
 #[cfg(test)]
 mod tests {
-    use super::*;
+    //! Note that most of these tests are not testing `AsciiExt` methods, but
+    //! test inherent ascii methods of char, u8, str and [u8]. `AsciiExt` is
+    //! just using those methods, though.
+    use super::AsciiExt;
     use char::from_u32;
 
     #[test]
diff --git a/src/libstd/build.rs b/src/libstd/build.rs
index 7ca762c801a..06f11c8deb4 100644
--- a/src/libstd/build.rs
+++ b/src/libstd/build.rs
@@ -11,7 +11,6 @@
 #![deny(warnings)]
 
 extern crate build_helper;
-extern crate cc;
 
 use std::env;
 use std::process::Command;
@@ -20,8 +19,12 @@ use build_helper::{run, native_lib_boilerplate, BuildExpectation};
 fn main() {
     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("msvc") &&
-        !target.contains("emscripten") && !target.contains("fuchsia") {
+    if cfg!(feature = "backtrace") &&
+        !target.contains("msvc") &&
+        !target.contains("emscripten") &&
+        !target.contains("fuchsia") &&
+        !target.contains("wasm32")
+    {
         let _ = build_libbacktrace(&host, &target);
     }
 
@@ -77,12 +80,6 @@ fn main() {
 fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> {
     let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", ".libs")?;
 
-    let compiler = cc::Build::new().get_compiler();
-    // only msvc returns None for ar so unwrap is okay
-    let ar = build_helper::cc2ar(compiler.path(), target).unwrap();
-    let mut cflags = compiler.args().iter().map(|s| s.to_str().unwrap())
-                             .collect::<Vec<_>>().join(" ");
-    cflags.push_str(" -fvisibility=hidden");
     run(Command::new("sh")
                 .current_dir(&native.out_dir)
                 .arg(native.src_dir.join("configure").to_str().unwrap()
@@ -94,10 +91,7 @@ fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> {
                 .arg("--disable-host-shared")
                 .arg(format!("--host={}", build_helper::gnu_target(target)))
                 .arg(format!("--build={}", build_helper::gnu_target(host)))
-                .env("CC", compiler.path())
-                .env("AR", &ar)
-                .env("RANLIB", format!("{} s", ar.display()))
-                .env("CFLAGS", cflags),
+                .env("CFLAGS", env::var("CFLAGS").unwrap_or_default() + " -fvisibility=hidden"),
         BuildExpectation::None);
 
     run(Command::new(build_helper::make(host))
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 026b863b963..7a79a472d58 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -20,8 +20,8 @@ use hash::{Hash, Hasher, BuildHasher, SipHasher13};
 use iter::{FromIterator, FusedIterator};
 use mem::{self, replace};
 use ops::{Deref, Index, InPlace, Place, Placer};
-use rand::{self, Rng};
 use ptr;
+use sys;
 
 use super::table::{self, Bucket, EmptyBucket, FullBucket, FullBucketMut, RawTable, SafeHash};
 use super::table::BucketState::{Empty, Full};
@@ -691,6 +691,17 @@ impl<K, V, S> HashMap<K, V, S>
     /// Returns a reference to the map's [`BuildHasher`].
     ///
     /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    /// use std::collections::hash_map::RandomState;
+    ///
+    /// let hasher = RandomState::new();
+    /// let map: HashMap<isize, isize> = HashMap::with_hasher(hasher);
+    /// let hasher: &RandomState = map.hasher();
+    /// ```
     #[stable(feature = "hashmap_public_hasher", since = "1.9.0")]
     pub fn hasher(&self) -> &S {
         &self.hash_builder
@@ -1102,6 +1113,7 @@ impl<K, V, S> HashMap<K, V, S>
     /// assert_eq!(map.get(&2), None);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
         where K: Borrow<Q>,
               Q: Hash + Eq
@@ -1350,7 +1362,7 @@ pub struct Iter<'a, K: 'a, V: 'a> {
     inner: table::Iter<'a, K, V>,
 }
 
-// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
+// FIXME(#26925) 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> {
@@ -1403,7 +1415,7 @@ pub struct Keys<'a, K: 'a, V: 'a> {
     inner: Iter<'a, K, V>,
 }
 
-// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
+// FIXME(#26925) 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> {
@@ -1432,7 +1444,7 @@ pub struct Values<'a, K: 'a, V: 'a> {
     inner: Iter<'a, K, V>,
 }
 
-// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
+// FIXME(#26925) 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> {
@@ -2002,6 +2014,41 @@ impl<'a, K, V> Entry<'a, K, V> {
             Vacant(ref entry) => entry.key(),
         }
     }
+
+    /// Provides in-place mutable access to an occupied entry before any
+    /// potential inserts into the map.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(entry_and_modify)]
+    /// use std::collections::HashMap;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    ///
+    /// map.entry("poneyland")
+    ///    .and_modify(|e| { *e += 1 })
+    ///    .or_insert(42);
+    /// assert_eq!(map["poneyland"], 42);
+    ///
+    /// map.entry("poneyland")
+    ///    .and_modify(|e| { *e += 1 })
+    ///    .or_insert(42);
+    /// assert_eq!(map["poneyland"], 43);
+    /// ```
+    #[unstable(feature = "entry_and_modify", issue = "44733")]
+    pub fn and_modify<F>(self, mut f: F) -> Self
+        where F: FnMut(&mut V)
+    {
+        match self {
+            Occupied(mut entry) => {
+                f(entry.get_mut());
+                Occupied(entry)
+            },
+            Vacant(entry) => Vacant(entry),
+        }
+    }
+
 }
 
 impl<'a, K, V: Default> Entry<'a, K, V> {
@@ -2192,28 +2239,29 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
         self.key.take()
     }
 
-    /// Replaces the entry, returning the old key and value.
+    /// Replaces the entry, returning the old key and value. The new key in the hash map will be
+    /// the key used to create this entry.
     ///
     /// # Examples
     ///
     /// ```
     /// #![feature(map_entry_replace)]
-    /// use std::collections::HashMap;
-    /// use std::collections::hash_map::Entry;
+    /// use std::collections::hash_map::{Entry, HashMap};
+    /// use std::rc::Rc;
+    ///
+    /// let mut map: HashMap<Rc<String>, u32> = HashMap::new();
+    /// map.insert(Rc::new("Stringthing".to_string()), 15);
     ///
-    /// let mut map: HashMap<String, u32> = HashMap::new();
-    /// map.insert("poneyland".to_string(), 15);
+    /// let my_key = Rc::new("Stringthing".to_string());
     ///
-    /// if let Entry::Occupied(entry) = map.entry("poneyland".to_string()) {
-    ///     let (old_key, old_value): (String, u32) = entry.replace(16);
-    ///     assert_eq!(old_key, "poneyland");
-    ///     assert_eq!(old_value, 15);
+    /// if let Entry::Occupied(entry) = map.entry(my_key) {
+    ///     // Also replace the key with a handle to our other key.
+    ///     let (old_key, old_value): (Rc<String>, u32) = entry.replace_entry(16);
     /// }
     ///
-    /// assert_eq!(map.get("poneyland"), Some(&16));
     /// ```
     #[unstable(feature = "map_entry_replace", issue = "44286")]
-    pub fn replace(mut self, value: V) -> (K, V) {
+    pub fn replace_entry(mut self, value: V) -> (K, V) {
         let (old_key, old_value) = self.elem.read_mut();
 
         let old_key = mem::replace(old_key, self.key.unwrap());
@@ -2221,6 +2269,37 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
 
         (old_key, old_value)
     }
+
+    /// Replaces the key in the hash map with the key used to create this entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(map_entry_replace)]
+    /// use std::collections::hash_map::{Entry, HashMap};
+    /// use std::rc::Rc;
+    ///
+    /// let mut map: HashMap<Rc<String>, u32> = HashMap::new();
+    /// let mut known_strings: Vec<Rc<String>> = Vec::new();
+    ///
+    /// // Initialise known strings, run program, etc.
+    ///
+    /// reclaim_memory(&mut map, &known_strings);
+    ///
+    /// fn reclaim_memory(map: &mut HashMap<Rc<String>, u32>, known_strings: &[Rc<String>] ) {
+    ///     for s in known_strings {
+    ///         if let Entry::Occupied(entry) = map.entry(s.clone()) {
+    ///             // Replaces the entry's key with our version of it in `known_strings`.
+    ///             entry.replace_key();
+    ///         }
+    ///     }
+    /// }
+    /// ```
+    #[unstable(feature = "map_entry_replace", issue = "44286")]
+    pub fn replace_key(mut self) -> K {
+        let (old_key, _) = self.elem.read_mut();
+        mem::replace(old_key, self.key.unwrap())
+    }
 }
 
 impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
@@ -2414,9 +2493,7 @@ impl RandomState {
         // increment one of the seeds on every RandomState creation, giving
         // every corresponding HashMap a different iteration order.
         thread_local!(static KEYS: Cell<(u64, u64)> = {
-            let r = rand::OsRng::new();
-            let mut r = r.expect("failed to create an OS RNG");
-            Cell::new((r.gen(), r.gen()))
+            Cell::new(sys::hashmap_random_keys())
         });
 
         KEYS.with(|keys| {
@@ -2508,6 +2585,7 @@ impl<K, S, Q: ?Sized> super::Recover<Q> for HashMap<K, (), S>
 {
     type Key = K;
 
+    #[inline]
     fn get(&self, key: &Q) -> Option<&K> {
         self.search(key).into_occupied_bucket().map(|bucket| bucket.into_refs().0)
     }
@@ -2520,6 +2598,7 @@ impl<K, S, Q: ?Sized> super::Recover<Q> for HashMap<K, (), S>
         self.search_mut(key).into_occupied_bucket().map(|bucket| pop_internal(bucket).0)
     }
 
+    #[inline]
     fn replace(&mut self, key: K) -> Option<K> {
         self.reserve(1);
 
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index f1e8ff66af1..7e623a0af17 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -717,26 +717,25 @@ fn calculate_offsets(hashes_size: usize,
     (pairs_offset, end_of_pairs, oflo)
 }
 
-// Returns a tuple of (minimum required malloc alignment, hash_offset,
+// Returns a tuple of (minimum required malloc alignment,
 // array_size), from the start of a mallocated array.
 fn calculate_allocation(hash_size: usize,
                         hash_align: usize,
                         pairs_size: usize,
                         pairs_align: usize)
-                        -> (usize, usize, usize, bool) {
-    let hash_offset = 0;
+                        -> (usize, usize, bool) {
     let (_, end_of_pairs, oflo) = calculate_offsets(hash_size, pairs_size, pairs_align);
 
     let align = cmp::max(hash_align, pairs_align);
 
-    (align, hash_offset, end_of_pairs, oflo)
+    (align, end_of_pairs, oflo)
 }
 
 #[test]
 fn test_offset_calculation() {
-    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_allocation(128, 8, 16, 8), (8, 144, false));
+    assert_eq!(calculate_allocation(3, 1, 2, 1), (1, 5, false));
+    assert_eq!(calculate_allocation(6, 2, 12, 4), (4, 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));
@@ -768,10 +767,10 @@ 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 (alignment, hash_offset, size, oflo) = calculate_allocation(hashes_size,
-                                                                        align_of::<HashUint>(),
-                                                                        pairs_size,
-                                                                        align_of::<(K, V)>());
+        let (alignment, 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.
@@ -784,7 +783,7 @@ impl<K, V> RawTable<K, V> {
         let buffer = Heap.alloc(Layout::from_size_align(size, alignment).unwrap())
             .unwrap_or_else(|e| Heap.oom(e));
 
-        let hashes = buffer.offset(hash_offset as isize) as *mut HashUint;
+        let hashes = buffer as *mut HashUint;
 
         RawTable {
             capacity_mask: capacity.wrapping_sub(1),
@@ -925,7 +924,7 @@ struct RawBuckets<'a, K, V> {
     marker: marker::PhantomData<&'a ()>,
 }
 
-// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
+// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
 impl<'a, K, V> Clone for RawBuckets<'a, K, V> {
     fn clone(&self) -> RawBuckets<'a, K, V> {
         RawBuckets {
@@ -976,7 +975,7 @@ pub struct Iter<'a, K: 'a, V: 'a> {
 unsafe impl<'a, K: Sync, V: Sync> Sync for Iter<'a, K, V> {}
 unsafe impl<'a, K: Sync, V: Sync> Send for Iter<'a, K, V> {}
 
-// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
+// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
 impl<'a, K, V> Clone for Iter<'a, K, V> {
     fn clone(&self) -> Iter<'a, K, V> {
         Iter {
@@ -1157,6 +1156,7 @@ impl<K: Clone, V: Clone> Clone for RawTable<K, V> {
             }
 
             new_ht.size = self.size();
+            new_ht.set_tag(self.tag());
 
             new_ht
         }
@@ -1183,10 +1183,10 @@ unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable<K, 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::<HashUint>(),
-                                                          pairs_size,
-                                                          align_of::<(K, V)>());
+        let (align, size, oflo) = calculate_allocation(hashes_size,
+                                                       align_of::<HashUint>(),
+                                                       pairs_size,
+                                                       align_of::<(K, V)>());
 
         debug_assert!(!oflo, "should be impossible");
 
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index f81adad3ebe..457c6e1409d 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -671,6 +671,10 @@ pub struct ArgsOs { inner: sys::args::Args }
 /// set to arbitrary text, and may not even exist. This means this property should
 /// not be relied upon for security purposes.
 ///
+/// On Unix systems shell usually expands unquoted arguments with glob patterns
+/// (such as `*` and `?`). On Windows this is not done, and such arguments are
+/// passed as-is.
+///
 /// # Panics
 ///
 /// The returned iterator will panic during iteration if any argument to the
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 6d64ea0d503..231b0be9276 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -56,6 +56,8 @@ use any::TypeId;
 use borrow::Cow;
 use cell;
 use char;
+use convert;
+use core::array;
 use fmt::{self, Debug, Display};
 use mem::transmute;
 use num;
@@ -281,6 +283,13 @@ impl Error for num::TryFromIntError {
     }
 }
 
+#[unstable(feature = "try_from", issue = "33417")]
+impl Error for array::TryFromSliceError {
+    fn description(&self) -> &str {
+        self.__description()
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Error for num::ParseFloatError {
     fn description(&self) -> &str {
@@ -362,6 +371,13 @@ impl Error for char::ParseCharError {
     }
 }
 
+#[unstable(feature = "try_from", issue = "33417")]
+impl Error for convert::Infallible {
+    fn description(&self) -> &str {
+        match *self {
+        }
+    }
+}
 
 // copied from any.rs
 impl Error + 'static {
diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index 0135cd0a588..e5b1394f070 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -9,8 +9,9 @@
 // except according to those terms.
 
 //! This module provides constants which are specific to the implementation
-//! of the `f32` floating point data type. Mathematically significant
-//! numbers are provided in the `consts` sub-module.
+//! of the `f32` floating point data type.
+//!
+//! Mathematically significant numbers are provided in the `consts` sub-module.
 //!
 //! *[See also the `f32` primitive type](../primitive.f32.html).*
 
@@ -23,7 +24,8 @@ use core::num;
 use intrinsics;
 #[cfg(not(test))]
 use num::FpCategory;
-
+#[cfg(not(test))]
+use sys::cmath;
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON};
@@ -36,92 +38,6 @@ pub use core::f32::{MIN, MIN_POSITIVE, MAX};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::f32::consts;
 
-#[allow(dead_code)]
-mod cmath {
-    use libc::{c_float, c_int};
-
-    extern {
-        pub fn cbrtf(n: c_float) -> c_float;
-        pub fn erff(n: c_float) -> c_float;
-        pub fn erfcf(n: c_float) -> c_float;
-        pub fn expm1f(n: c_float) -> c_float;
-        pub fn fdimf(a: c_float, b: c_float) -> c_float;
-        pub fn fmodf(a: c_float, b: c_float) -> c_float;
-        pub fn ilogbf(n: c_float) -> c_int;
-        pub fn logbf(n: c_float) -> c_float;
-        pub fn log1pf(n: c_float) -> c_float;
-        pub fn modff(n: c_float, iptr: &mut c_float) -> c_float;
-        pub fn nextafterf(x: c_float, y: c_float) -> c_float;
-        pub fn tgammaf(n: c_float) -> c_float;
-
-        #[cfg_attr(all(windows, target_env = "msvc"), link_name = "__lgammaf_r")]
-        pub fn lgammaf_r(n: c_float, sign: &mut c_int) -> c_float;
-        #[cfg_attr(all(windows, target_env = "msvc"), link_name = "_hypotf")]
-        pub fn hypotf(x: c_float, y: c_float) -> c_float;
-    }
-
-    // See the comments in the `floor` function for why MSVC is special
-    // here.
-    #[cfg(not(target_env = "msvc"))]
-    extern {
-        pub fn acosf(n: c_float) -> c_float;
-        pub fn asinf(n: c_float) -> c_float;
-        pub fn atan2f(a: c_float, b: c_float) -> c_float;
-        pub fn atanf(n: c_float) -> c_float;
-        pub fn coshf(n: c_float) -> c_float;
-        pub fn sinhf(n: c_float) -> c_float;
-        pub fn tanf(n: c_float) -> c_float;
-        pub fn tanhf(n: c_float) -> c_float;
-    }
-
-    #[cfg(target_env = "msvc")]
-    pub use self::shims::*;
-    #[cfg(target_env = "msvc")]
-    mod shims {
-        use libc::c_float;
-
-        #[inline]
-        pub unsafe fn acosf(n: c_float) -> c_float {
-            f64::acos(n as f64) as c_float
-        }
-
-        #[inline]
-        pub unsafe fn asinf(n: c_float) -> c_float {
-            f64::asin(n as f64) as c_float
-        }
-
-        #[inline]
-        pub unsafe fn atan2f(n: c_float, b: c_float) -> c_float {
-            f64::atan2(n as f64, b as f64) as c_float
-        }
-
-        #[inline]
-        pub unsafe fn atanf(n: c_float) -> c_float {
-            f64::atan(n as f64) as c_float
-        }
-
-        #[inline]
-        pub unsafe fn coshf(n: c_float) -> c_float {
-            f64::cosh(n as f64) as c_float
-        }
-
-        #[inline]
-        pub unsafe fn sinhf(n: c_float) -> c_float {
-            f64::sinh(n as f64) as c_float
-        }
-
-        #[inline]
-        pub unsafe fn tanf(n: c_float) -> c_float {
-            f64::tan(n as f64) as c_float
-        }
-
-        #[inline]
-        pub unsafe fn tanhf(n: c_float) -> c_float {
-            f64::tanh(n as f64) as c_float
-        }
-    }
-}
-
 #[cfg(not(test))]
 #[lang = "f32"]
 impl f32 {
@@ -1082,10 +998,13 @@ impl f32 {
 
     /// Raw transmutation to `u32`.
     ///
-    /// Converts the `f32` into its raw memory representation,
-    /// similar to the `transmute` function.
+    /// This is currently identical to `transmute::<f32, u32>(self)` on all platforms.
+    ///
+    /// See `from_bits` for some discussion of the portability of this operation
+    /// (there are almost no issues).
     ///
-    /// Note that this function is distinct from casting.
+    /// Note that this function is distinct from `as` casting, which attempts to
+    /// preserve the *numeric* value, and not the bitwise value.
     ///
     /// # Examples
     ///
@@ -1102,17 +1021,33 @@ impl f32 {
 
     /// Raw transmutation from `u32`.
     ///
-    /// Converts the given `u32` containing the float's raw memory
-    /// representation into the `f32` type, similar to the
-    /// `transmute` function.
+    /// This is currently identical to `transmute::<u32, f32>(v)` on all platforms.
+    /// It turns out this is incredibly portable, for two reasons:
+    ///
+    /// * Floats and Ints have the same endianess on all supported platforms.
+    /// * IEEE-754 very precisely specifies the bit layout of floats.
+    ///
+    /// However there is one caveat: prior to the 2008 version of IEEE-754, how
+    /// to interpret the NaN signaling bit wasn't actually specified. Most platforms
+    /// (notably x86 and ARM) picked the interpretation that was ultimately
+    /// standardized in 2008, but some didn't (notably MIPS). As a result, all
+    /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
     ///
-    /// There is only one difference to a bare `transmute`:
-    /// Due to the implications onto Rust's safety promises being
-    /// uncertain, if the representation of a signaling NaN "sNaN" float
-    /// is passed to the function, the implementation is allowed to
-    /// return a quiet NaN instead.
+    /// Rather than trying to preserve signaling-ness cross-platform, this
+    /// implementation favours preserving the exact bits. This means that
+    /// any payloads encoded in NaNs will be preserved even if the result of
+    /// this method is sent over the network from an x86 machine to a MIPS one.
     ///
-    /// Note that this function is distinct from casting.
+    /// If the results of this method are only manipulated by the same
+    /// architecture that produced them, then there is no portability concern.
+    ///
+    /// If the input isn't NaN, then there is no portability concern.
+    ///
+    /// If you don't care about signalingness (very likely), then there is no
+    /// portability concern.
+    ///
+    /// Note that this function is distinct from `as` casting, which attempts to
+    /// preserve the *numeric* value, and not the bitwise value.
     ///
     /// # Examples
     ///
@@ -1121,25 +1056,11 @@ impl f32 {
     /// let v = f32::from_bits(0x41480000);
     /// let difference = (v - 12.5).abs();
     /// assert!(difference <= 1e-5);
-    /// // Example for a signaling NaN value:
-    /// let snan = 0x7F800001;
-    /// assert_ne!(f32::from_bits(snan).to_bits(), snan);
     /// ```
     #[stable(feature = "float_bits_conv", since = "1.20.0")]
     #[inline]
-    pub fn from_bits(mut v: u32) -> Self {
-        const EXP_MASK: u32   = 0x7F800000;
-        const FRACT_MASK: u32 = 0x007FFFFF;
-        if v & EXP_MASK == EXP_MASK && v & FRACT_MASK != 0 {
-            // While IEEE 754-2008 specifies encodings for quiet NaNs
-            // and signaling ones, certain MIPS and PA-RISC
-            // CPUs treat signaling NaNs differently.
-            // Therefore to be safe, we pass a known quiet NaN
-            // if v is any kind of NaN.
-            // The check above only assumes IEEE 754-1985 to be
-            // valid.
-            v = unsafe { ::mem::transmute(NAN) };
-        }
+    pub fn from_bits(v: u32) -> Self {
+        // It turns out the safety issues with sNaN were overblown! Hooray!
         unsafe { ::mem::transmute(v) }
     }
 }
@@ -1730,25 +1651,15 @@ mod tests {
         assert_approx_eq!(f32::from_bits(0x41480000), 12.5);
         assert_approx_eq!(f32::from_bits(0x44a72000), 1337.0);
         assert_approx_eq!(f32::from_bits(0xc1640000), -14.25);
-    }
-    #[test]
-    fn test_snan_masking() {
-        // NOTE: this test assumes that our current platform
-        // implements IEEE 754-2008 that specifies the difference
-        // in encoding of quiet and signaling NaNs.
-        // If you are porting Rust to a platform that does not
-        // implement IEEE 754-2008 (but e.g. IEEE 754-1985, which
-        // only says that "Signaling NaNs shall be reserved operands"
-        // but doesn't specify the actual setup), feel free to
-        // cfg out this test.
-        let snan: u32 = 0x7F801337;
-        const QNAN_MASK: u32  = 0x00400000;
-        let nan_masked_fl = f32::from_bits(snan);
-        let nan_masked = nan_masked_fl.to_bits();
-        // Ensure that signaling NaNs don't stay the same
-        assert_ne!(nan_masked, snan);
-        // Ensure that we have a quiet NaN
-        assert_ne!(nan_masked & QNAN_MASK, 0);
-        assert!(nan_masked_fl.is_nan());
+
+        // Check that NaNs roundtrip their bits regardless of signalingness
+        // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
+        let masked_nan1 = f32::NAN.to_bits() ^ 0x002A_AAAA;
+        let masked_nan2 = f32::NAN.to_bits() ^ 0x0055_5555;
+        assert!(f32::from_bits(masked_nan1).is_nan());
+        assert!(f32::from_bits(masked_nan2).is_nan());
+
+        assert_eq!(f32::from_bits(masked_nan1).to_bits(), masked_nan1);
+        assert_eq!(f32::from_bits(masked_nan2).to_bits(), masked_nan2);
     }
 }
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index d73d7cd2c7b..f4d804fd508 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -9,8 +9,9 @@
 // except according to those terms.
 
 //! This module provides constants which are specific to the implementation
-//! of the `f64` floating point data type. Mathematically significant
-//! numbers are provided in the `consts` sub-module.
+//! of the `f64` floating point data type.
+//!
+//! Mathematically significant numbers are provided in the `consts` sub-module.
 //!
 //! *[See also the `f64` primitive type](../primitive.f64.html).*
 
@@ -23,6 +24,8 @@ use core::num;
 use intrinsics;
 #[cfg(not(test))]
 use num::FpCategory;
+#[cfg(not(test))]
+use sys::cmath;
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON};
@@ -35,53 +38,6 @@ pub use core::f64::{MIN, MIN_POSITIVE, MAX};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::f64::consts;
 
-#[allow(dead_code)]
-mod cmath {
-    use libc::{c_double, c_int};
-
-    #[link_name = "m"]
-    extern {
-        pub fn acos(n: c_double) -> c_double;
-        pub fn asin(n: c_double) -> c_double;
-        pub fn atan(n: c_double) -> c_double;
-        pub fn atan2(a: c_double, b: c_double) -> c_double;
-        pub fn cbrt(n: c_double) -> c_double;
-        pub fn cosh(n: c_double) -> c_double;
-        pub fn erf(n: c_double) -> c_double;
-        pub fn erfc(n: c_double) -> c_double;
-        pub fn expm1(n: c_double) -> c_double;
-        pub fn fdim(a: c_double, b: c_double) -> c_double;
-        pub fn fmod(a: c_double, b: c_double) -> c_double;
-        pub fn frexp(n: c_double, value: &mut c_int) -> c_double;
-        pub fn ilogb(n: c_double) -> c_int;
-        pub fn ldexp(x: c_double, n: c_int) -> c_double;
-        pub fn logb(n: c_double) -> c_double;
-        pub fn log1p(n: c_double) -> c_double;
-        pub fn nextafter(x: c_double, y: c_double) -> c_double;
-        pub fn modf(n: c_double, iptr: &mut c_double) -> c_double;
-        pub fn sinh(n: c_double) -> c_double;
-        pub fn tan(n: c_double) -> c_double;
-        pub fn tanh(n: c_double) -> c_double;
-        pub fn tgamma(n: c_double) -> c_double;
-
-        // These are commonly only available for doubles
-
-        pub fn j0(n: c_double) -> c_double;
-        pub fn j1(n: c_double) -> c_double;
-        pub fn jn(i: c_int, n: c_double) -> c_double;
-
-        pub fn y0(n: c_double) -> c_double;
-        pub fn y1(n: c_double) -> c_double;
-        pub fn yn(i: c_int, n: c_double) -> c_double;
-
-        #[cfg_attr(all(windows, target_env = "msvc"), link_name = "__lgamma_r")]
-        pub fn lgamma_r(n: c_double, sign: &mut c_int) -> c_double;
-
-        #[cfg_attr(all(windows, target_env = "msvc"), link_name = "_hypot")]
-        pub fn hypot(x: c_double, y: c_double) -> c_double;
-    }
-}
-
 #[cfg(not(test))]
 #[lang = "f64"]
 impl f64 {
@@ -997,10 +953,13 @@ impl f64 {
 
     /// Raw transmutation to `u64`.
     ///
-    /// Converts the `f64` into its raw memory representation,
-    /// similar to the `transmute` function.
+    /// This is currently identical to `transmute::<f64, u64>(self)` on all platforms.
+    ///
+    /// See `from_bits` for some discussion of the portability of this operation
+    /// (there are almost no issues).
     ///
-    /// Note that this function is distinct from casting.
+    /// Note that this function is distinct from `as` casting, which attempts to
+    /// preserve the *numeric* value, and not the bitwise value.
     ///
     /// # Examples
     ///
@@ -1017,17 +976,33 @@ impl f64 {
 
     /// Raw transmutation from `u64`.
     ///
-    /// Converts the given `u64` containing the float's raw memory
-    /// representation into the `f64` type, similar to the
-    /// `transmute` function.
+    /// This is currently identical to `transmute::<u64, f64>(v)` on all platforms.
+    /// It turns out this is incredibly portable, for two reasons:
+    ///
+    /// * Floats and Ints have the same endianess on all supported platforms.
+    /// * IEEE-754 very precisely specifies the bit layout of floats.
     ///
-    /// There is only one difference to a bare `transmute`:
-    /// Due to the implications onto Rust's safety promises being
-    /// uncertain, if the representation of a signaling NaN "sNaN" float
-    /// is passed to the function, the implementation is allowed to
-    /// return a quiet NaN instead.
+    /// However there is one caveat: prior to the 2008 version of IEEE-754, how
+    /// to interpret the NaN signaling bit wasn't actually specified. Most platforms
+    /// (notably x86 and ARM) picked the interpretation that was ultimately
+    /// standardized in 2008, but some didn't (notably MIPS). As a result, all
+    /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
     ///
-    /// Note that this function is distinct from casting.
+    /// Rather than trying to preserve signaling-ness cross-platform, this
+    /// implementation favours preserving the exact bits. This means that
+    /// any payloads encoded in NaNs will be preserved even if the result of
+    /// this method is sent over the network from an x86 machine to a MIPS one.
+    ///
+    /// If the results of this method are only manipulated by the same
+    /// architecture that produced them, then there is no portability concern.
+    ///
+    /// If the input isn't NaN, then there is no portability concern.
+    ///
+    /// If you don't care about signalingness (very likely), then there is no
+    /// portability concern.
+    ///
+    /// Note that this function is distinct from `as` casting, which attempts to
+    /// preserve the *numeric* value, and not the bitwise value.
     ///
     /// # Examples
     ///
@@ -1036,25 +1011,11 @@ impl f64 {
     /// let v = f64::from_bits(0x4029000000000000);
     /// let difference = (v - 12.5).abs();
     /// assert!(difference <= 1e-5);
-    /// // Example for a signaling NaN value:
-    /// let snan = 0x7FF0000000000001;
-    /// assert_ne!(f64::from_bits(snan).to_bits(), snan);
     /// ```
     #[stable(feature = "float_bits_conv", since = "1.20.0")]
     #[inline]
-    pub fn from_bits(mut v: u64) -> Self {
-        const EXP_MASK: u64   = 0x7FF0000000000000;
-        const FRACT_MASK: u64 = 0x000FFFFFFFFFFFFF;
-        if v & EXP_MASK == EXP_MASK && v & FRACT_MASK != 0 {
-            // While IEEE 754-2008 specifies encodings for quiet NaNs
-            // and signaling ones, certain MIPS and PA-RISC
-            // CPUs treat signaling NaNs differently.
-            // Therefore to be safe, we pass a known quiet NaN
-            // if v is any kind of NaN.
-            // The check above only assumes IEEE 754-1985 to be
-            // valid.
-            v = unsafe { ::mem::transmute(NAN) };
-        }
+    pub fn from_bits(v: u64) -> Self {
+        // It turns out the safety issues with sNaN were overblown! Hooray!
         unsafe { ::mem::transmute(v) }
     }
 }
@@ -1641,5 +1602,15 @@ mod tests {
         assert_approx_eq!(f64::from_bits(0x4029000000000000), 12.5);
         assert_approx_eq!(f64::from_bits(0x4094e40000000000), 1337.0);
         assert_approx_eq!(f64::from_bits(0xc02c800000000000), -14.25);
+
+        // Check that NaNs roundtrip their bits regardless of signalingness
+        // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
+        let masked_nan1 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
+        let masked_nan2 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
+        assert!(f64::from_bits(masked_nan1).is_nan());
+        assert!(f64::from_bits(masked_nan2).is_nan());
+
+        assert_eq!(f64::from_bits(masked_nan1).to_bits(), masked_nan1);
+        assert_eq!(f64::from_bits(masked_nan2).to_bits(), masked_nan2);
     }
 }
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index 7992aefcb42..a2022a2eeb2 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -14,28 +14,80 @@ use cmp::Ordering;
 use error::Error;
 use fmt::{self, Write};
 use io;
-use libc;
 use mem;
 use memchr;
 use ops;
 use os::raw::c_char;
 use ptr;
+use rc::Rc;
 use slice;
 use str::{self, Utf8Error};
+use sync::Arc;
+use sys;
 
-/// A type representing an owned C-compatible string.
+/// A type representing an owned, C-compatible, nul-terminated string with no nul bytes in the
+/// middle.
 ///
-/// This type serves the primary purpose of being able to safely generate a
+/// This type serves the purpose of being able to safely generate a
 /// C-compatible string from a Rust byte slice or vector. An instance of this
 /// type is a static guarantee that the underlying bytes contain no interior 0
-/// bytes and the final byte is 0.
+/// bytes ("nul characters") and that the final byte is 0 ("nul terminator").
 ///
-/// A `CString` is created from either a byte slice or a byte vector. A [`u8`]
-/// slice can be obtained with the `as_bytes` method. Slices produced from a
-/// `CString` do *not* contain the trailing nul terminator unless otherwise
-/// specified.
+/// `CString` is to [`CStr`] as [`String`] is to [`&str`]: the former
+/// in each pair are owned strings; the latter are borrowed
+/// references.
 ///
+/// # Creating a `CString`
+///
+/// A `CString` is created from either a byte slice or a byte vector,
+/// or anything that implements [`Into`]`<`[`Vec`]`<`[`u8`]`>>` (for
+/// example, you can build a `CString` straight out of a [`String`] or
+/// a [`&str`], since both implement that trait).
+///
+/// The [`new`] method will actually check that the provided `&[u8]`
+/// does not have 0 bytes in the middle, and return an error if it
+/// finds one.
+///
+/// # Extracting a raw pointer to the whole C string
+///
+/// `CString` implements a [`as_ptr`] method through the [`Deref`]
+/// trait. This method will give you a `*const c_char` which you can
+/// feed directly to extern functions that expect a nul-terminated
+/// string, like C's `strdup()`.
+///
+/// # Extracting a slice of the whole C string
+///
+/// Alternatively, you can obtain a `&[`[`u8`]`]` slice from a
+/// `CString` with the [`as_bytes`] method. Slices produced in this
+/// way do *not* contain the trailing nul terminator. This is useful
+/// when you will be calling an extern function that takes a `*const
+/// u8` argument which is not necessarily nul-terminated, plus another
+/// argument with the length of the string — like C's `strndup()`.
+/// You can of course get the slice's length with its
+/// [`len`][slice.len] method.
+///
+/// If you need a `&[`[`u8`]`]` slice *with* the nul terminator, you
+/// can use [`as_bytes_with_nul`] instead.
+///
+/// Once you have the kind of slice you need (with or without a nul
+/// terminator), you can call the slice's own
+/// [`as_ptr`][slice.as_ptr] method to get a raw pointer to pass to
+/// extern functions. See the documentation for that function for a
+/// discussion on ensuring the lifetime of the raw pointer.
+///
+/// [`Into`]: ../convert/trait.Into.html
+/// [`Vec`]: ../vec/struct.Vec.html
+/// [`String`]: ../string/struct.String.html
+/// [`&str`]: ../primitive.str.html
 /// [`u8`]: ../primitive.u8.html
+/// [`new`]: #method.new
+/// [`as_bytes`]: #method.as_bytes
+/// [`as_bytes_with_nul`]: #method.as_bytes_with_nul
+/// [`as_ptr`]: #method.as_ptr
+/// [slice.as_ptr]: ../primitive.slice.html#method.as_ptr
+/// [slice.len]: ../primitive.slice.html#method.len
+/// [`Deref`]: ../ops/trait.Deref.html
+/// [`CStr`]: struct.CStr.html
 ///
 /// # Examples
 ///
@@ -48,6 +100,8 @@ use str::{self, Utf8Error};
 ///     fn my_printer(s: *const c_char);
 /// }
 ///
+/// // We are certain that our string doesn't have 0 bytes in the middle,
+/// // so we can .unwrap()
 /// let c_to_print = CString::new("Hello, world!").unwrap();
 /// unsafe {
 ///     my_printer(c_to_print.as_ptr());
@@ -58,7 +112,7 @@ use str::{self, Utf8Error};
 /// # Safety
 ///
 /// `CString` is intended for working with traditional C-style strings
-/// (a sequence of non-null bytes terminated by a single null byte); the
+/// (a sequence of non-nul bytes terminated by a single nul byte); the
 /// primary use case for these kinds of strings is interoperating with C-like
 /// code. Often you will need to transfer ownership to/from that external
 /// code. It is strongly recommended that you thoroughly read through the
@@ -77,17 +131,21 @@ pub struct CString {
 
 /// Representation of a borrowed C string.
 ///
-/// This dynamically sized type is only safely constructed via a borrowed
-/// version of an instance of `CString`. This type can be constructed from a raw
-/// C string as well and represents a C string borrowed from another location.
+/// This type represents a borrowed reference to a nul-terminated
+/// array of bytes. It can be constructed safely from a `&[`[`u8`]`]`
+/// slice, or unsafely from a raw `*const c_char`. It can then be
+/// converted to a Rust [`&str`] by performing UTF-8 validation, or
+/// into an owned [`CString`].
+///
+/// `CStr` is to [`CString`] as [`&str`] is to [`String`]: the former
+/// in each pair are borrowed references; the latter are owned
+/// strings.
 ///
 /// Note that this structure is **not** `repr(C)` and is not recommended to be
-/// placed in the signatures of FFI functions. Instead safe wrappers of FFI
+/// placed in the signatures of FFI functions. Instead, safe wrappers of FFI
 /// functions may leverage the unsafe [`from_ptr`] constructor to provide a safe
 /// interface to other consumers.
 ///
-/// [`from_ptr`]: #method.from_ptr
-///
 /// # Examples
 ///
 /// Inspecting a foreign C string:
@@ -100,7 +158,7 @@ pub struct CString {
 ///
 /// unsafe {
 ///     let slice = CStr::from_ptr(my_string());
-///     println!("string length: {}", slice.to_bytes().len());
+///     println!("string buffer size without nul terminator: {}", slice.to_bytes().len());
 /// }
 /// ```
 ///
@@ -122,8 +180,6 @@ pub struct CString {
 ///
 /// Converting a foreign C string into a Rust [`String`]:
 ///
-/// [`String`]: ../string/struct.String.html
-///
 /// ```no_run
 /// use std::ffi::CStr;
 /// use std::os::raw::c_char;
@@ -138,6 +194,12 @@ pub struct CString {
 ///
 /// println!("string: {}", my_string_safe());
 /// ```
+///
+/// [`u8`]: ../primitive.u8.html
+/// [`&str`]: ../primitive.str.html
+/// [`String`]: ../string/struct.String.html
+/// [`CString`]: struct.CString.html
+/// [`from_ptr`]: #method.from_ptr
 #[derive(Hash)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct CStr {
@@ -148,9 +210,15 @@ pub struct CStr {
     inner: [c_char]
 }
 
-/// An error returned from [`CString::new`] to indicate that a nul byte was found
-/// in the vector provided.
+/// An error indicating that an interior nul byte was found.
+///
+/// While Rust strings may contain nul bytes in the middle, C strings
+/// can't, as that byte would effectively truncate the string.
 ///
+/// This error is created by the [`new`][`CString::new`] method on
+/// [`CString`]. See its documentation for more.
+///
+/// [`CString`]: struct.CString.html
 /// [`CString::new`]: struct.CString.html#method.new
 ///
 /// # Examples
@@ -164,9 +232,16 @@ pub struct CStr {
 #[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.
+/// An error indicating that a nul byte was not in the expected position.
+///
+/// The slice used to create a [`CStr`] must have one and only one nul
+/// byte at the end of the slice.
 ///
+/// This error is created by the
+/// [`from_bytes_with_nul`][`CStr::from_bytes_with_nul`] method on
+/// [`CStr`]. See its documentation for more.
+///
+/// [`CStr`]: struct.CStr.html
 /// [`CStr::from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul
 ///
 /// # Examples
@@ -201,9 +276,18 @@ impl FromBytesWithNulError {
     }
 }
 
-/// An error returned from [`CString::into_string`] to indicate that a UTF-8 error
-/// was encountered during the conversion.
+/// An error indicating invalid UTF-8 when converting a [`CString`] into a [`String`].
+///
+/// `CString` is just a wrapper over a buffer of bytes with a nul
+/// terminator; [`into_string`][`CString::into_string`] performs UTF-8
+/// validation on those bytes and may return this error.
 ///
+/// This `struct` is created by the
+/// [`into_string`][`CString::into_string`] method on [`CString`]. See
+/// its documentation for more.
+///
+/// [`String`]: ../string/struct.String.html
+/// [`CString`]: struct.CString.html
 /// [`CString::into_string`]: struct.CString.html#method.into_string
 #[derive(Clone, PartialEq, Eq, Debug)]
 #[stable(feature = "cstring_into", since = "1.7.0")]
@@ -215,8 +299,11 @@ pub struct IntoStringError {
 impl CString {
     /// Creates a new C-compatible string from a container of bytes.
     ///
-    /// This method will consume the provided data and use the underlying bytes
-    /// to construct a new string, ensuring that there is a trailing 0 byte.
+    /// This function will consume the provided data and use the
+    /// underlying bytes to construct a new string, ensuring that
+    /// there is a trailing 0 byte. This trailing 0 byte will be
+    /// appended by this function; the provided data should *not*
+    /// contain any 0 bytes in it.
     ///
     /// # Examples
     ///
@@ -234,9 +321,11 @@ impl CString {
     ///
     /// # Errors
     ///
-    /// This function will return an error if the bytes yielded contain an
-    /// internal 0 byte. The error returned will contain the bytes as well as
+    /// This function will return an error if the supplied bytes contain an
+    /// internal 0 byte. The [`NulError`] returned will contain the bytes as well as
     /// the position of the nul byte.
+    ///
+    /// [`NulError`]: struct.NulError.html
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
         Self::_new(t.into())
@@ -249,8 +338,8 @@ impl CString {
         }
     }
 
-    /// Creates a C-compatible string from a byte vector without checking for
-    /// interior 0 bytes.
+    /// Creates a C-compatible string by consuming a byte vector,
+    /// without checking for interior 0 bytes.
     ///
     /// This method is equivalent to [`new`] except that no runtime assertion
     /// is made that `v` contains no 0 bytes, and it requires an actual
@@ -275,7 +364,7 @@ impl CString {
         CString { inner: v.into_boxed_slice() }
     }
 
-    /// Retakes ownership of a `CString` that was transferred to C.
+    /// Retakes ownership of a `CString` that was transferred to C via [`into_raw`].
     ///
     /// Additionally, the length of the string will be recalculated from the pointer.
     ///
@@ -286,7 +375,14 @@ impl CString {
     /// ownership of a string that was allocated by foreign code) is likely to lead
     /// to undefined behavior or allocator corruption.
     ///
+    /// > **Note:** If you need to borrow a string that was allocated by
+    /// > foreign code, use [`CStr`]. If you need to take ownership of
+    /// > a string that was allocated by foreign code, you will need to
+    /// > make your own provisions for freeing it appropriately, likely
+    /// > with the foreign code's API to do that.
+    ///
     /// [`into_raw`]: #method.into_raw
+    /// [`CStr`]: struct.CStr.html
     ///
     /// # Examples
     ///
@@ -310,16 +406,16 @@ impl CString {
     /// ```
     #[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
-        let slice = slice::from_raw_parts(ptr, len as usize);
-        CString { inner: mem::transmute(slice) }
+        let len = sys::strlen(ptr) + 1; // Including the NUL byte
+        let slice = slice::from_raw_parts_mut(ptr, len as usize);
+        CString { inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]) }
     }
 
-    /// Transfers ownership of the string to a C caller.
+    /// Consumes the `CString` and transfers ownership of the string to a C caller.
     ///
-    /// The pointer must be returned to Rust and reconstituted using
+    /// The pointer which this function returns must be returned to Rust and reconstituted using
     /// [`from_raw`] to be properly deallocated. Specifically, one
-    /// should *not* use the standard C `free` function to deallocate
+    /// should *not* use the standard C `free()` function to deallocate
     /// this string.
     ///
     /// Failure to call [`from_raw`] will lead to a memory leak.
@@ -351,11 +447,27 @@ impl CString {
         Box::into_raw(self.into_inner()) as *mut c_char
     }
 
-    /// Converts the `CString` into a [`String`] if it contains valid Unicode data.
+    /// Converts the `CString` into a [`String`] if it contains valid UTF-8 data.
     ///
     /// On failure, ownership of the original `CString` is returned.
     ///
     /// [`String`]: ../string/struct.String.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::CString;
+    ///
+    /// let valid_utf8 = vec![b'f', b'o', b'o'];
+    /// let cstring = CString::new(valid_utf8).unwrap();
+    /// assert_eq!(cstring.into_string().unwrap(), "foo");
+    ///
+    /// let invalid_utf8 = vec![b'f', 0xff, b'o', b'o'];
+    /// let cstring = CString::new(invalid_utf8).unwrap();
+    /// let err = cstring.into_string().err().unwrap();
+    /// assert_eq!(err.utf8_error().valid_up_to(), 1);
+    /// ```
+
     #[stable(feature = "cstring_into", since = "1.7.0")]
     pub fn into_string(self) -> Result<String, IntoStringError> {
         String::from_utf8(self.into_bytes())
@@ -365,10 +477,11 @@ impl CString {
             })
     }
 
-    /// Returns the underlying byte buffer.
+    /// Consumes the `CString` and returns the underlying byte buffer.
     ///
-    /// The returned buffer does **not** contain the trailing nul separator and
-    /// it is guaranteed to not have any interior nul bytes.
+    /// The returned buffer does **not** contain the trailing nul
+    /// terminator, and it is guaranteed to not have any interior nul
+    /// bytes.
     ///
     /// # Examples
     ///
@@ -388,7 +501,7 @@ impl CString {
     }
 
     /// Equivalent to the [`into_bytes`] function except that the returned vector
-    /// includes the trailing nul byte.
+    /// includes the trailing nul terminator.
     ///
     /// [`into_bytes`]: #method.into_bytes
     ///
@@ -408,8 +521,12 @@ impl CString {
 
     /// Returns the contents of this `CString` as a slice of bytes.
     ///
-    /// The returned slice does **not** contain the trailing nul separator and
-    /// it is guaranteed to not have any interior nul bytes.
+    /// The returned slice does **not** contain the trailing nul
+    /// terminator, and it is guaranteed to not have any interior nul
+    /// bytes. If you need the nul terminator, use
+    /// [`as_bytes_with_nul`] instead.
+    ///
+    /// [`as_bytes_with_nul`]: #method.as_bytes_with_nul
     ///
     /// # Examples
     ///
@@ -427,7 +544,7 @@ impl CString {
     }
 
     /// Equivalent to the [`as_bytes`] function except that the returned slice
-    /// includes the trailing nul byte.
+    /// includes the trailing nul terminator.
     ///
     /// [`as_bytes`]: #method.as_bytes
     ///
@@ -480,7 +597,7 @@ impl CString {
     /// ```
     #[stable(feature = "into_boxed_c_str", since = "1.20.0")]
     pub fn into_boxed_c_str(self) -> Box<CStr> {
-        unsafe { mem::transmute(self.into_inner()) }
+        unsafe { Box::from_raw(Box::into_raw(self.into_inner()) as *mut CStr) }
     }
 
     // Bypass "move out of struct which implements [`Drop`] trait" restriction.
@@ -569,7 +686,7 @@ impl Borrow<CStr> for CString {
 impl<'a> From<&'a CStr> for Box<CStr> {
     fn from(s: &'a CStr) -> Box<CStr> {
         let boxed: Box<[u8]> = Box::from(s.to_bytes_with_nul());
-        unsafe { mem::transmute(boxed) }
+        unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) }
     }
 }
 
@@ -589,17 +706,53 @@ impl From<CString> for Box<CStr> {
     }
 }
 
+#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+impl From<CString> for Arc<CStr> {
+    #[inline]
+    fn from(s: CString) -> Arc<CStr> {
+        let arc: Arc<[u8]> = Arc::from(s.into_inner());
+        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const CStr) }
+    }
+}
+
+#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+impl<'a> From<&'a CStr> for Arc<CStr> {
+    #[inline]
+    fn from(s: &CStr) -> Arc<CStr> {
+        let arc: Arc<[u8]> = Arc::from(s.to_bytes_with_nul());
+        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const CStr) }
+    }
+}
+
+#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+impl From<CString> for Rc<CStr> {
+    #[inline]
+    fn from(s: CString) -> Rc<CStr> {
+        let rc: Rc<[u8]> = Rc::from(s.into_inner());
+        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const CStr) }
+    }
+}
+
+#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+impl<'a> From<&'a CStr> for Rc<CStr> {
+    #[inline]
+    fn from(s: &CStr) -> Rc<CStr> {
+        let rc: Rc<[u8]> = Rc::from(s.to_bytes_with_nul());
+        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const CStr) }
+    }
+}
+
 #[stable(feature = "default_box_extra", since = "1.17.0")]
 impl Default for Box<CStr> {
     fn default() -> Box<CStr> {
         let boxed: Box<[u8]> = Box::from([0]);
-        unsafe { mem::transmute(boxed) }
+        unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) }
     }
 }
 
 impl NulError {
-    /// Returns the position of the nul byte in the slice that was provided to
-    /// [`CString::new`].
+    /// Returns the position of the nul byte in the slice that caused
+    /// [`CString::new`] to fail.
     ///
     /// [`CString::new`]: struct.CString.html#method.new
     ///
@@ -711,9 +864,9 @@ impl fmt::Display for IntoStringError {
 }
 
 impl CStr {
-    /// Casts a raw C string to a safe C string wrapper.
+    /// Wraps a raw C string with a safe C string wrapper.
     ///
-    /// This function will cast the provided `ptr` to the `CStr` wrapper which
+    /// This function will wrap the provided `ptr` with a `CStr` wrapper, which
     /// allows inspection and interoperation of non-owned C strings. This method
     /// is unsafe for a number of reasons:
     ///
@@ -746,16 +899,16 @@ impl CStr {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
-        let len = libc::strlen(ptr);
+        let len = sys::strlen(ptr);
         let ptr = ptr as *const u8;
         CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1))
     }
 
     /// Creates a C string wrapper from a byte slice.
     ///
-    /// This function will cast the provided `bytes` to a `CStr` wrapper after
-    /// ensuring that it is null terminated and does not contain any interior
-    /// nul bytes.
+    /// This function will cast the provided `bytes` to a `CStr`
+    /// wrapper after ensuring that the byte slice is nul-terminated
+    /// and does not contain any interior nul bytes.
     ///
     /// # Examples
     ///
@@ -766,7 +919,7 @@ impl CStr {
     /// assert!(cstr.is_ok());
     /// ```
     ///
-    /// Creating a `CStr` without a trailing nul byte is an error:
+    /// Creating a `CStr` without a trailing nul terminator is an error:
     ///
     /// ```
     /// use std::ffi::CStr;
@@ -800,7 +953,7 @@ impl CStr {
     /// Unsafely creates a C string wrapper from a byte slice.
     ///
     /// This function will cast the provided `bytes` to a `CStr` wrapper without
-    /// performing any sanity checks. The provided slice must be null terminated
+    /// performing any sanity checks. The provided slice **must** be nul-terminated
     /// and not contain any interior nul bytes.
     ///
     /// # Examples
@@ -817,12 +970,12 @@ impl CStr {
     #[inline]
     #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
     pub unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
-        mem::transmute(bytes)
+        &*(bytes as *const [u8] as *const CStr)
     }
 
     /// Returns the inner pointer to this C string.
     ///
-    /// The returned pointer will be valid for as long as `self` is and points
+    /// The returned pointer will be valid for as long as `self` is, and points
     /// to a contiguous region of memory terminated with a 0 byte to represent
     /// the end of the string.
     ///
@@ -843,9 +996,9 @@ impl CStr {
     /// ```
     ///
     /// This happens because the pointer returned by `as_ptr` does not carry any
-    /// lifetime information and the string is deallocated immediately after
+    /// lifetime information and the [`CString`] is deallocated immediately after
     /// the `CString::new("Hello").unwrap().as_ptr()` expression is evaluated.
-    /// To fix the problem, bind the string to a local variable:
+    /// To fix the problem, bind the `CString` to a local variable:
     ///
     /// ```no_run
     /// use std::ffi::{CString};
@@ -857,6 +1010,11 @@ impl CStr {
     ///     *ptr;
     /// }
     /// ```
+    ///
+    /// This way, the lifetime of the `CString` in `hello` encompasses
+    /// the lifetime of `ptr` and the `unsafe` block.
+    ///
+    /// [`CString`]: struct.CString.html
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn as_ptr(&self) -> *const c_char {
@@ -865,11 +1023,7 @@ impl CStr {
 
     /// Converts this C string to a byte slice.
     ///
-    /// This function will calculate the length of this string (which normally
-    /// requires a linear amount of work to be done) and then return the
-    /// resulting slice of `u8` elements.
-    ///
-    /// The returned slice will **not** contain the trailing nul that this C
+    /// The returned slice will **not** contain the trailing nul terminator that this C
     /// string has.
     ///
     /// > **Note**: This method is currently implemented as a 0-cost cast, but
@@ -894,7 +1048,7 @@ impl CStr {
     /// Converts this C string to a byte slice containing the trailing 0 byte.
     ///
     /// This function is the equivalent of [`to_bytes`] except that it will retain
-    /// the trailing nul instead of chopping it off.
+    /// the trailing nul terminator instead of chopping it off.
     ///
     /// > **Note**: This method is currently implemented as a 0-cost cast, but
     /// > it is planned to alter its definition in the future to perform the
@@ -913,13 +1067,14 @@ impl CStr {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn to_bytes_with_nul(&self) -> &[u8] {
-        unsafe { mem::transmute(&self.inner) }
+        unsafe { &*(&self.inner as *const [c_char] as *const [u8]) }
     }
 
     /// Yields a [`&str`] slice if the `CStr` contains valid UTF-8.
     ///
-    /// This function will calculate the length of this string and check for
-    /// UTF-8 validity, and then return the [`&str`] if it's valid.
+    /// If the contents of the `CStr` are valid UTF-8 data, this
+    /// function will return the corresponding [`&str`] slice. Otherwise,
+    /// it will return an error with details of where UTF-8 validation failed.
     ///
     /// > **Note**: This method is currently implemented to check for validity
     /// > after a 0-cost cast, but it is planned to alter its definition in the
@@ -947,10 +1102,12 @@ impl CStr {
 
     /// Converts a `CStr` into a [`Cow`]`<`[`str`]`>`.
     ///
-    /// This function will calculate the length of this string (which normally
-    /// requires a linear amount of work to be done) and then return the
-    /// resulting slice as a [`Cow`]`<`[`str`]`>`, replacing any invalid UTF-8 sequences
-    /// with `U+FFFD REPLACEMENT CHARACTER`.
+    /// If the contents of the `CStr` are valid UTF-8 data, this
+    /// function will return a [`Cow`]`::`[`Borrowed`]`(`[`&str`]`)`
+    /// with the the corresponding [`&str`] slice. Otherwise, it will
+    /// replace any invalid UTF-8 sequences with `U+FFFD REPLACEMENT
+    /// CHARACTER` and return a [`Cow`]`::`[`Owned`]`(`[`String`]`)`
+    /// with the result.
     ///
     /// > **Note**: This method is currently implemented to check for validity
     /// > after a 0-cost cast, but it is planned to alter its definition in the
@@ -958,7 +1115,9 @@ impl CStr {
     /// > check whenever this method is called.
     ///
     /// [`Cow`]: ../borrow/enum.Cow.html
+    /// [`Borrowed`]: ../borrow/enum.Cow.html#variant.Borrowed
     /// [`str`]: ../primitive.str.html
+    /// [`String`]: ../string/struct.String.html
     ///
     /// # Examples
     ///
@@ -1005,7 +1164,8 @@ impl CStr {
     /// ```
     #[stable(feature = "into_boxed_c_str", since = "1.20.0")]
     pub fn into_c_string(self: Box<CStr>) -> CString {
-        unsafe { mem::transmute(self) }
+        let raw = Box::into_raw(self) as *mut [u8];
+        CString { inner: unsafe { Box::from_raw(raw) } }
     }
 }
 
@@ -1079,6 +1239,8 @@ mod tests {
     use borrow::Cow::{Borrowed, Owned};
     use hash::{Hash, Hasher};
     use collections::hash_map::DefaultHasher;
+    use rc::Rc;
+    use sync::Arc;
 
     #[test]
     fn c_to_rust() {
@@ -1215,4 +1377,21 @@ mod tests {
         let boxed = <Box<CStr>>::default();
         assert_eq!(boxed.to_bytes_with_nul(), &[0]);
     }
+
+    #[test]
+    fn into_rc() {
+        let orig: &[u8] = b"Hello, world!\0";
+        let cstr = CStr::from_bytes_with_nul(orig).unwrap();
+        let rc: Rc<CStr> = Rc::from(cstr);
+        let arc: Arc<CStr> = Arc::from(cstr);
+
+        assert_eq!(&*rc, cstr);
+        assert_eq!(&*arc, cstr);
+
+        let rc2: Rc<CStr> = Rc::from(cstr.to_owned());
+        let arc2: Arc<CStr> = Arc::from(cstr.to_owned());
+
+        assert_eq!(&*rc2, cstr);
+        assert_eq!(&*arc2, cstr);
+    }
 }
diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs
index ca1ff18f1ca..a75596351e4 100644
--- a/src/libstd/ffi/mod.rs
+++ b/src/libstd/ffi/mod.rs
@@ -9,6 +9,157 @@
 // except according to those terms.
 
 //! Utilities related to FFI bindings.
+//!
+//! This module provides utilities to handle data across non-Rust
+//! interfaces, like other programming languages and the underlying
+//! operating system. It is mainly of use for FFI (Foreign Function
+//! Interface) bindings and code that needs to exchange C-like strings
+//! with other languages.
+//!
+//! # Overview
+//!
+//! Rust represents owned strings with the [`String`] type, and
+//! borrowed slices of strings with the [`str`] primitive. Both are
+//! always in UTF-8 encoding, and may contain nul bytes in the middle,
+//! i.e. if you look at the bytes that make up the string, there may
+//! be a `\0` among them. Both `String` and `str` store their length
+//! explicitly; there are no nul terminators at the end of strings
+//! like in C.
+//!
+//! C strings are different from Rust strings:
+//!
+//! * **Encodings** - Rust strings are UTF-8, but C strings may use
+//! other encodings. If you are using a string from C, you should
+//! check its encoding explicitly, rather than just assuming that it
+//! is UTF-8 like you can do in Rust.
+//!
+//! * **Character size** - C strings may use `char` or `wchar_t`-sized
+//! characters; please **note** that C's `char` is different from Rust's.
+//! The C standard leaves the actual sizes of those types open to
+//! interpretation, but defines different APIs for strings made up of
+//! each character type. Rust strings are always UTF-8, so different
+//! Unicode characters will be encoded in a variable number of bytes
+//! each. The Rust type [`char`] represents a '[Unicode scalar
+//! value]', which is similar to, but not the same as, a '[Unicode
+//! code point]'.
+//!
+//! * **Nul terminators and implicit string lengths** - Often, C
+//! strings are nul-terminated, i.e. they have a `\0` character at the
+//! end. The length of a string buffer is not stored, but has to be
+//! calculated; to compute the length of a string, C code must
+//! manually call a function like `strlen()` for `char`-based strings,
+//! or `wcslen()` for `wchar_t`-based ones. Those functions return
+//! the number of characters in the string excluding the nul
+//! terminator, so the buffer length is really `len+1` characters.
+//! Rust strings don't have a nul terminator; their length is always
+//! stored and does not need to be calculated. While in Rust
+//! accessing a string's length is a O(1) operation (becasue the
+//! length is stored); in C it is an O(length) operation because the
+//! length needs to be computed by scanning the string for the nul
+//! terminator.
+//!
+//! * **Internal nul characters** - When C strings have a nul
+//! terminator character, this usually means that they cannot have nul
+//! characters in the middle — a nul character would essentially
+//! truncate the string. Rust strings *can* have nul characters in
+//! the middle, because nul does not have to mark the end of the
+//! string in Rust.
+//!
+//! # Representations of non-Rust strings
+//!
+//! [`CString`] and [`CStr`] are useful when you need to transfer
+//! UTF-8 strings to and from languages with a C ABI, like Python.
+//!
+//! * **From Rust to C:** [`CString`] represents an owned, C-friendly
+//! string: it is nul-terminated, and has no internal nul characters.
+//! Rust code can create a `CString` out of a normal string (provided
+//! that the string doesn't have nul characters in the middle), and
+//! then use a variety of methods to obtain a raw `*mut u8` that can
+//! then be passed as an argument to functions which use the C
+//! conventions for strings.
+//!
+//! * **From C to Rust:** [`CStr`] represents a borrowed C string; it
+//! is what you would use to wrap a raw `*const u8` that you got from
+//! a C function. A `CStr` is guaranteed to be a nul-terminated array
+//! of bytes. Once you have a `CStr`, you can convert it to a Rust
+//! `&str` if it's valid UTF-8, or lossily convert it by adding
+//! replacement characters.
+//!
+//! [`OsString`] and [`OsStr`] are useful when you need to transfer
+//! strings to and from the operating system itself, or when capturing
+//! the output of external commands. Conversions between `OsString`,
+//! `OsStr` and Rust strings work similarly to those for [`CString`]
+//! and [`CStr`].
+//!
+//! * [`OsString`] represents an owned string in whatever
+//! representation the operating system prefers. In the Rust standard
+//! library, various APIs that transfer strings to/from the operating
+//! system use `OsString` instead of plain strings. For example,
+//! [`env::var_os()`] is used to query environment variables; it
+//! returns an `Option<OsString>`. If the environment variable exists
+//! you will get a `Some(os_string)`, which you can *then* try to
+//! convert to a Rust string. This yields a [`Result<>`], so that
+//! your code can detect errors in case the environment variable did
+//! not in fact contain valid Unicode data.
+//!
+//! * [`OsStr`] represents a borrowed reference to a string in a
+//! format that can be passed to the operating system. It can be
+//! converted into an UTF-8 Rust string slice in a similar way to
+//! `OsString`.
+//!
+//! # Conversions
+//!
+//! ## On Unix
+//!
+//! On Unix, [`OsStr`] implements the
+//! `std::os::unix:ffi::`[`OsStrExt`][unix.OsStrExt] trait, which
+//! augments it with two methods, [`from_bytes`] and [`as_bytes`].
+//! These do inexpensive conversions from and to UTF-8 byte slices.
+//!
+//! Additionally, on Unix [`OsString`] implements the
+//! `std::os::unix:ffi::`[`OsStringExt`][unix.OsStringExt] trait,
+//! which provides [`from_vec`] and [`into_vec`] methods that consume
+//! their arguments, and take or produce vectors of [`u8`].
+//!
+//! ## On Windows
+//!
+//! On Windows, [`OsStr`] implements the
+//! `std::os::windows::ffi::`[`OsStrExt`][windows.OsStrExt] trait,
+//! which provides an [`encode_wide`] method. This provides an
+//! iterator that can be [`collect`]ed into a vector of [`u16`].
+//!
+//! Additionally, on Windows [`OsString`] implements the
+//! `std::os::windows:ffi::`[`OsStringExt`][windows.OsStringExt]
+//! trait, which provides a [`from_wide`] method. The result of this
+//! method is an `OsString` which can be round-tripped to a Windows
+//! string losslessly.
+//!
+//! [`String`]: ../string/struct.String.html
+//! [`str`]: ../primitive.str.html
+//! [`char`]: ../primitive.char.html
+//! [`u8`]: ../primitive.u8.html
+//! [`u16`]: ../primitive.u16.html
+//! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value
+//! [Unicode code point]: http://www.unicode.org/glossary/#code_point
+//! [`CString`]: struct.CString.html
+//! [`CStr`]: struct.CStr.html
+//! [`OsString`]: struct.OsString.html
+//! [`OsStr`]: struct.OsStr.html
+//! [`env::set_var()`]: ../env/fn.set_var.html
+//! [`env::var_os()`]: ../env/fn.var_os.html
+//! [`Result<>`]: ../result/enum.Result.html
+//! [unix.OsStringExt]: ../os/unix/ffi/trait.OsStringExt.html
+//! [`from_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.from_vec
+//! [`into_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.into_vec
+//! [unix.OsStrExt]: ../os/unix/ffi/trait.OsStrExt.html
+//! [`from_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.from_bytes
+//! [`as_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.as_bytes
+//! [`OsStrExt`]: ../os/unix/ffi/trait.OsStrExt.html
+//! [windows.OsStrExt]: ../os/windows/ffi/trait.OsStrExt.html
+//! [`encode_wide`]: ../os/windows/ffi/trait.OsStrExt.html#tymethod.encode_wide
+//! [`collect`]: ../iter/trait.Iterator.html#method.collect
+//! [windows.OsStringExt]: ../os/windows/ffi/trait.OsStringExt.html
+//! [`from_wide`]: ../os/windows/ffi/trait.OsStringExt.html#tymethod.from_wide
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs
index a40a9329ed9..cb902461f39 100644
--- a/src/libstd/ffi/os_str.rs
+++ b/src/libstd/ffi/os_str.rs
@@ -10,10 +10,11 @@
 
 use borrow::{Borrow, Cow};
 use fmt;
-use mem;
 use ops;
 use cmp;
 use hash::{Hash, Hasher};
+use rc::Rc;
+use sync::Arc;
 
 use sys::os_str::{Buf, Slice};
 use sys_common::{AsInner, IntoInner, FromInner};
@@ -33,18 +34,64 @@ use sys_common::{AsInner, IntoInner, FromInner};
 ///
 /// `OsString` and [`OsStr`] bridge this gap by simultaneously representing Rust
 /// and platform-native string values, and in particular allowing a Rust string
-/// to be converted into an "OS" string with no cost.
+/// to be converted into an "OS" string with no cost if possible.
+///
+/// `OsString` is to [`OsStr`] as [`String`] is to [`&str`]: the former
+/// in each pair are owned strings; the latter are borrowed
+/// references.
+///
+/// # Creating an `OsString`
+///
+/// **From a Rust string**: `OsString` implements
+/// [`From`]`<`[`String`]`>`, so you can use `my_string.from` to
+/// create an `OsString` from a normal Rust string.
+///
+/// **From slices:** Just like you can start with an empty Rust
+/// [`String`] and then [`push_str`][String.push_str] `&str`
+/// sub-string slices into it, you can create an empty `OsString` with
+/// the [`new`] method and then push string slices into it with the
+/// [`push`] method.
+///
+/// # Extracting a borrowed reference to the whole OS string
+///
+/// You can use the [`as_os_str`] method to get an `&`[`OsStr`] from
+/// an `OsString`; this is effectively a borrowed reference to the
+/// whole string.
+///
+/// # Conversions
+///
+/// See the [module's toplevel documentation about conversions][conversions] for a discussion on
+/// the traits which `OsString` implements for conversions from/to native representations.
 ///
 /// [`OsStr`]: struct.OsStr.html
+/// [`From`]: ../convert/trait.From.html
+/// [`String`]: ../string/struct.String.html
+/// [`&str`]: ../primitive.str.html
+/// [`u8`]: ../primitive.u8.html
+/// [`u16`]: ../primitive.u16.html
+/// [String.push_str]: ../string/struct.String.html#method.push_str
+/// [`new`]: #method.new
+/// [`push`]: #method.push
+/// [`as_os_str`]: #method.as_os_str
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct OsString {
     inner: Buf
 }
 
-/// Slices into OS strings (see [`OsString`]).
+/// Borrowed reference to an OS string (see [`OsString`]).
+///
+/// This type represents a borrowed reference to a string in the operating system's preferred
+/// representation.
+///
+/// `OsStr` is to [`OsString`] as [`String`] is to [`&str`]: the former in each pair are borrowed
+/// references; the latter are owned strings.
+///
+/// See the [module's toplevel documentation about conversions][conversions] for a discussion on
+/// the traits which `OsStr` implements for conversions from/to native representations.
 ///
 /// [`OsString`]: struct.OsString.html
+/// [conversions]: index.html#conversions
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct OsStr {
     inner: Slice
@@ -260,7 +307,8 @@ impl OsString {
     /// ```
     #[stable(feature = "into_boxed_os_str", since = "1.20.0")]
     pub fn into_boxed_os_str(self) -> Box<OsStr> {
-        unsafe { mem::transmute(self.inner.into_box()) }
+        let rw = Box::into_raw(self.inner.into_box()) as *mut OsStr;
+        unsafe { Box::from_raw(rw) }
     }
 }
 
@@ -394,7 +442,7 @@ impl OsStr {
     }
 
     fn from_inner(inner: &Slice) -> &OsStr {
-        unsafe { mem::transmute(inner) }
+        unsafe { &*(inner as *const Slice as *const OsStr) }
     }
 
     /// Yields a [`&str`] slice if the `OsStr` is valid Unicode.
@@ -511,8 +559,8 @@ impl OsStr {
     /// [`OsString`]: struct.OsString.html
     #[stable(feature = "into_boxed_os_str", since = "1.20.0")]
     pub fn into_os_string(self: Box<OsStr>) -> OsString {
-        let inner: Box<Slice> = unsafe { mem::transmute(self) };
-        OsString { inner: Buf::from_box(inner) }
+        let boxed = unsafe { Box::from_raw(Box::into_raw(self) as *mut Slice) };
+        OsString { inner: Buf::from_box(boxed) }
     }
 
     /// Gets the underlying byte representation.
@@ -520,14 +568,15 @@ impl OsStr {
     /// Note: it is *crucial* that this API is private, to avoid
     /// revealing the internal, platform-specific encodings.
     fn bytes(&self) -> &[u8] {
-        unsafe { mem::transmute(&self.inner) }
+        unsafe { &*(&self.inner as *const _ as *const [u8]) }
     }
 }
 
 #[stable(feature = "box_from_os_str", since = "1.17.0")]
 impl<'a> From<&'a OsStr> for Box<OsStr> {
     fn from(s: &'a OsStr) -> Box<OsStr> {
-        unsafe { mem::transmute(s.inner.into_box()) }
+        let rw = Box::into_raw(s.inner.into_box()) as *mut OsStr;
+        unsafe { Box::from_raw(rw) }
     }
 }
 
@@ -545,10 +594,47 @@ impl From<OsString> for Box<OsStr> {
     }
 }
 
+#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+impl From<OsString> for Arc<OsStr> {
+    #[inline]
+    fn from(s: OsString) -> Arc<OsStr> {
+        let arc = s.inner.into_arc();
+        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const OsStr) }
+    }
+}
+
+#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+impl<'a> From<&'a OsStr> for Arc<OsStr> {
+    #[inline]
+    fn from(s: &OsStr) -> Arc<OsStr> {
+        let arc = s.inner.into_arc();
+        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const OsStr) }
+    }
+}
+
+#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+impl From<OsString> for Rc<OsStr> {
+    #[inline]
+    fn from(s: OsString) -> Rc<OsStr> {
+        let rc = s.inner.into_rc();
+        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const OsStr) }
+    }
+}
+
+#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+impl<'a> From<&'a OsStr> for Rc<OsStr> {
+    #[inline]
+    fn from(s: &OsStr) -> Rc<OsStr> {
+        let rc = s.inner.into_rc();
+        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const OsStr) }
+    }
+}
+
 #[stable(feature = "box_default_extra", since = "1.17.0")]
 impl Default for Box<OsStr> {
     fn default() -> Box<OsStr> {
-        unsafe { mem::transmute(Slice::empty_box()) }
+        let rw = Box::into_raw(Slice::empty_box()) as *mut OsStr;
+        unsafe { Box::from_raw(rw) }
     }
 }
 
@@ -745,6 +831,9 @@ mod tests {
     use super::*;
     use sys_common::{AsInner, IntoInner};
 
+    use rc::Rc;
+    use sync::Arc;
+
     #[test]
     fn test_os_string_with_capacity() {
         let os_string = OsString::with_capacity(0);
@@ -887,4 +976,21 @@ mod tests {
         assert_eq!(os_str, os_string);
         assert!(os_string.capacity() >= 123);
     }
+
+    #[test]
+    fn into_rc() {
+        let orig = "Hello, world!";
+        let os_str = OsStr::new(orig);
+        let rc: Rc<OsStr> = Rc::from(os_str);
+        let arc: Arc<OsStr> = Arc::from(os_str);
+
+        assert_eq!(&*rc, os_str);
+        assert_eq!(&*arc, os_str);
+
+        let rc2: Rc<OsStr> = Rc::from(os_str.to_owned());
+        let arc2: Arc<OsStr> = Arc::from(os_str.to_owned());
+
+        assert_eq!(&*rc2, os_str);
+        assert_eq!(&*arc2, os_str);
+    }
 }
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index 91600b01298..b07733d3c80 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -1374,14 +1374,17 @@ pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()>
 /// Note that if `from` and `to` both point to the same file, then the file
 /// will likely get truncated by this operation.
 ///
-/// On success, the total number of bytes copied is returned.
+/// On success, the total number of bytes copied is returned and it is equal to
+/// the length of the `to` file as reported by `metadata`.
 ///
 /// # Platform-specific behavior
 ///
 /// This function currently corresponds to the `open` function in Unix
 /// with `O_RDONLY` for `from` and `O_WRONLY`, `O_CREAT`, and `O_TRUNC` for `to`.
 /// `O_CLOEXEC` is set for returned file descriptors.
-/// On Windows, this function currently corresponds to `CopyFileEx`.
+/// On Windows, this function currently corresponds to `CopyFileEx`. Alternate
+/// NTFS streams are copied but only the size of the main stream is returned by
+/// this function.
 /// Note that, this [may change in the future][changes].
 ///
 /// [changes]: ../io/index.html#platform-specific-behavior
@@ -2589,7 +2592,7 @@ mod tests {
     fn copy_file_preserves_streams() {
         let tmp = tmpdir();
         check!(check!(File::create(tmp.join("in.txt:bunny"))).write("carrot".as_bytes()));
-        assert_eq!(check!(fs::copy(tmp.join("in.txt"), tmp.join("out.txt"))), 6);
+        assert_eq!(check!(fs::copy(tmp.join("in.txt"), tmp.join("out.txt"))), 0);
         assert_eq!(check!(tmp.join("out.txt").metadata()).len(), 0);
         let mut v = Vec::new();
         check!(check!(File::open(tmp.join("out.txt:bunny"))).read_to_end(&mut v));
@@ -2597,6 +2600,18 @@ mod tests {
     }
 
     #[test]
+    fn copy_file_returns_metadata_len() {
+        let tmp = tmpdir();
+        let in_path = tmp.join("in.txt");
+        let out_path = tmp.join("out.txt");
+        check!(check!(File::create(&in_path)).write(b"lettuce"));
+        #[cfg(windows)]
+        check!(check!(File::create(tmp.join("in.txt:bunny"))).write(b"carrot"));
+        let copied_len = check!(fs::copy(&in_path, &out_path));
+        assert_eq!(check!(out_path.metadata()).len(), copied_len);
+    }
+
+    #[test]
     fn symlinks_work() {
         let tmpdir = tmpdir();
         if !got_symlink_permission(&tmpdir) { return };
diff --git a/src/libstd/heap.rs b/src/libstd/heap.rs
index d76ab31862b..4d5e4df6f95 100644
--- a/src/libstd/heap.rs
+++ b/src/libstd/heap.rs
@@ -17,6 +17,7 @@ pub use alloc_system::System;
 
 #[cfg(not(test))]
 #[doc(hidden)]
+#[allow(unused_attributes)]
 pub mod __default_lib_allocator {
     use super::{System, Layout, Alloc, AllocErr};
     use ptr;
@@ -28,6 +29,7 @@ pub mod __default_lib_allocator {
     // ABI
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_alloc(size: usize,
                                      align: usize,
                                      err: *mut u8) -> *mut u8 {
@@ -42,11 +44,13 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_oom(err: *const u8) -> ! {
         System.oom((*(err as *const AllocErr)).clone())
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_dealloc(ptr: *mut u8,
                                        size: usize,
                                        align: usize) {
@@ -54,6 +58,7 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_usable_size(layout: *const u8,
                                            min: *mut usize,
                                            max: *mut usize) {
@@ -63,6 +68,7 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_realloc(ptr: *mut u8,
                                        old_size: usize,
                                        old_align: usize,
@@ -81,6 +87,7 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_alloc_zeroed(size: usize,
                                             align: usize,
                                             err: *mut u8) -> *mut u8 {
@@ -95,6 +102,7 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_alloc_excess(size: usize,
                                             align: usize,
                                             excess: *mut usize,
@@ -113,6 +121,7 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_realloc_excess(ptr: *mut u8,
                                               old_size: usize,
                                               old_align: usize,
@@ -135,6 +144,7 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_grow_in_place(ptr: *mut u8,
                                              old_size: usize,
                                              old_align: usize,
@@ -149,6 +159,7 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_shrink_in_place(ptr: *mut u8,
                                                old_size: usize,
                                                old_align: usize,
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index 4ebd3554fd1..6d3fbc9d268 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -147,6 +147,31 @@ impl<R: Read> BufReader<R> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_mut(&mut self) -> &mut R { &mut self.inner }
 
+    /// Returns `true` if there are no bytes in the internal buffer.
+    ///
+    /// # Examples
+    /// ```
+    /// # #![feature(bufreader_is_empty)]
+    /// use std::io::BufReader;
+    /// use std::io::BufRead;
+    /// use std::fs::File;
+    ///
+    /// # fn foo() -> std::io::Result<()> {
+    /// let f1 = File::open("log.txt")?;
+    /// let mut reader = BufReader::new(f1);
+    /// assert!(reader.is_empty());
+    ///
+    /// if reader.fill_buf()?.len() > 0 {
+    ///     assert!(!reader.is_empty());
+    /// }
+    /// # Ok(())
+    /// # }
+    /// ```
+    #[unstable(feature = "bufreader_is_empty", issue = "45323", reason = "recently added")]
+    pub fn is_empty(&self) -> bool {
+        self.pos == self.cap
+    }
+
     /// Unwraps this `BufReader`, returning the underlying reader.
     ///
     /// Note that any leftover data in the internal buffer is lost.
diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs
index 32a92145aaf..b5ea5531b65 100644
--- a/src/libstd/io/cursor.rs
+++ b/src/libstd/io/cursor.rs
@@ -230,6 +230,13 @@ impl<T> Read for Cursor<T> where T: AsRef<[u8]> {
         Ok(n)
     }
 
+    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
+        let n = buf.len();
+        Read::read_exact(&mut self.fill_buf()?, buf)?;
+        self.pos += n as u64;
+        Ok(())
+    }
+
     #[inline]
     unsafe fn initializer(&self) -> Initializer {
         Initializer::nop()
@@ -476,6 +483,24 @@ mod tests {
     }
 
     #[test]
+    fn test_read_exact() {
+        let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
+        let reader = &mut &in_buf[..];
+        let mut buf = [];
+        assert!(reader.read_exact(&mut buf).is_ok());
+        let mut buf = [8];
+        assert!(reader.read_exact(&mut buf).is_ok());
+        assert_eq!(buf[0], 0);
+        assert_eq!(reader.len(), 7);
+        let mut buf = [0, 0, 0, 0, 0, 0, 0];
+        assert!(reader.read_exact(&mut buf).is_ok());
+        assert_eq!(buf, [1, 2, 3, 4, 5, 6, 7]);
+        assert_eq!(reader.len(), 0);
+        let mut buf = [0];
+        assert!(reader.read_exact(&mut buf).is_err());
+    }
+
+    #[test]
     fn test_buf_reader() {
         let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
         let mut reader = Cursor::new(&in_buf[..]);
diff --git a/src/libstd/io/impls.rs b/src/libstd/io/impls.rs
index d6b41ceda43..fe1179a3b4a 100644
--- a/src/libstd/io/impls.rs
+++ b/src/libstd/io/impls.rs
@@ -206,6 +206,14 @@ impl<'a> Read for &'a [u8] {
         *self = b;
         Ok(())
     }
+
+    #[inline]
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        buf.extend_from_slice(*self);
+        let len = self.len();
+        *self = &self[len..];
+        Ok(len)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 074ab3ebd8f..b7a3695b470 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -366,16 +366,13 @@ fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize>
 fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> {
     let start_len = buf.len();
     let mut g = Guard { len: buf.len(), buf: buf };
-    let mut new_write_size = 16;
     let ret;
     loop {
         if g.len == g.buf.len() {
-            if new_write_size < DEFAULT_BUF_SIZE {
-                new_write_size *= 2;
-            }
             unsafe {
-                g.buf.reserve(new_write_size);
-                g.buf.set_len(g.len + new_write_size);
+                g.buf.reserve(32);
+                let capacity = g.buf.capacity();
+                g.buf.set_len(capacity);
                 r.initializer().initialize(&mut g.buf[g.len..]);
             }
         }
@@ -419,14 +416,8 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize>
 ///
 /// [`File`]s implement `Read`:
 ///
-/// [`read()`]: trait.Read.html#tymethod.read
-/// [`std::io`]: ../../std/io/index.html
-/// [`File`]: ../fs/struct.File.html
-/// [`BufRead`]: trait.BufRead.html
-/// [`BufReader`]: struct.BufReader.html
-///
 /// ```
-/// use std::io;
+/// # use std::io;
 /// use std::io::prelude::*;
 /// use std::fs::File;
 ///
@@ -449,7 +440,33 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize>
 /// # Ok(())
 /// # }
 /// ```
+///
+/// Read from `&str` because [`&[u8]`] implements `Read`:
+///
+/// ```
+/// # use std::io;
+/// use std::io::prelude::*;
+///
+/// # fn foo() -> io::Result<()> {
+/// let mut b = "This string will be read".as_bytes();
+/// let mut buffer = [0; 10];
+///
+/// // read up to 10 bytes
+/// b.read(&mut buffer)?;
+///
+/// // etc... it works exactly as a File does!
+/// # Ok(())
+/// # }
+/// ```
+///
+/// [`read()`]: trait.Read.html#tymethod.read
+/// [`std::io`]: ../../std/io/index.html
+/// [`File`]: ../fs/struct.File.html
+/// [`BufRead`]: trait.BufRead.html
+/// [`BufReader`]: struct.BufReader.html
+/// [`&[u8]`]: primitive.slice.html
 #[stable(feature = "rust1", since = "1.0.0")]
+#[doc(spotlight)]
 pub trait Read {
     /// Pull some bytes from this source into the specified buffer, returning
     /// how many bytes were read.
@@ -736,10 +753,10 @@ pub trait Read {
 
     /// Transforms this `Read` instance to an [`Iterator`] over its bytes.
     ///
-    /// The returned type implements [`Iterator`] where the `Item` is [`Result`]`<`[`u8`]`,
-    /// R::Err>`. The yielded item is [`Ok`] if a byte was successfully read and
-    /// [`Err`] otherwise for I/O errors. EOF is mapped to returning [`None`] from
-    /// this iterator.
+    /// The returned type implements [`Iterator`] where the `Item` is
+    /// [`Result`]`<`[`u8`]`, `[`io::Error`]`>`.
+    /// The yielded item is [`Ok`] if a byte was successfully read and [`Err`]
+    /// otherwise. EOF is mapped to returning [`None`] from this iterator.
     ///
     /// # Examples
     ///
@@ -748,6 +765,7 @@ pub trait Read {
     /// [file]: ../fs/struct.File.html
     /// [`Iterator`]: ../../std/iter/trait.Iterator.html
     /// [`Result`]: ../../std/result/enum.Result.html
+    /// [`io::Error`]: ../../std/io/struct.Error.html
     /// [`u8`]: ../../std/primitive.u8.html
     /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
     /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
@@ -967,6 +985,7 @@ impl Initializer {
 /// # }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
+#[doc(spotlight)]
 pub trait Write {
     /// Write a buffer into this object, returning how many bytes were written.
     ///
@@ -1410,6 +1429,8 @@ pub trait BufRead: Read {
     ///
     /// If successful, this function will return the total number of bytes read.
     ///
+    /// An empty buffer returned indicates that the stream has reached EOF.
+    ///
     /// # Errors
     ///
     /// This function will ignore all instances of [`ErrorKind::Interrupted`] and
@@ -1470,6 +1491,8 @@ pub trait BufRead: Read {
     ///
     /// If successful, this function will return the total number of bytes read.
     ///
+    /// An empty buffer returned indicates that the stream has reached EOF.
+    ///
     /// # Errors
     ///
     /// This function has the same error semantics as [`read_until`] and will
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index fb489bf487b..831688bb73d 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -121,10 +121,8 @@ impl<R: io::Read> io::Read for Maybe<R> {
 }
 
 fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
-    use sys::stdio::EBADF_ERR;
-
     match r {
-        Err(ref e) if e.raw_os_error() == Some(EBADF_ERR) => Ok(default),
+        Err(ref e) if stdio::is_ebadf(e) => Ok(default),
         r => r
     }
 }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 9fc7e2c01aa..bf177ac7f2c 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -243,7 +243,10 @@
 #![feature(allow_internal_unsafe)]
 #![feature(allow_internal_unstable)]
 #![feature(align_offset)]
+#![feature(array_error_internals)]
+#![feature(ascii_ctype)]
 #![feature(asm)]
+#![feature(attr_literals)]
 #![feature(box_syntax)]
 #![feature(cfg_target_has_atomic)]
 #![feature(cfg_target_thread_local)]
@@ -257,6 +260,7 @@
 #![feature(core_intrinsics)]
 #![feature(dropck_eyepatch)]
 #![feature(exact_size_is_empty)]
+#![feature(fixed_size_array)]
 #![feature(float_from_str_radix)]
 #![feature(fn_traits)]
 #![feature(fnbox)]
@@ -290,9 +294,9 @@
 #![feature(prelude_import)]
 #![feature(rand)]
 #![feature(raw)]
+#![feature(repr_align)]
 #![feature(repr_simd)]
 #![feature(rustc_attrs)]
-#![cfg_attr(not(stage0), feature(rustc_const_unstable))]
 #![feature(shared)]
 #![feature(sip_hash_13)]
 #![feature(slice_bytes)]
@@ -315,18 +319,9 @@
 #![feature(vec_push_all)]
 #![feature(doc_cfg)]
 #![feature(doc_masked)]
+#![feature(doc_spotlight)]
 #![cfg_attr(test, feature(update_panic_count))]
-
-#![cfg_attr(not(stage0), feature(const_max_value))]
-#![cfg_attr(not(stage0), feature(const_atomic_bool_new))]
-#![cfg_attr(not(stage0), feature(const_atomic_isize_new))]
-#![cfg_attr(not(stage0), feature(const_atomic_usize_new))]
-#![cfg_attr(all(not(stage0), windows), feature(const_atomic_ptr_new))]
-#![cfg_attr(not(stage0), feature(const_unsafe_cell_new))]
-#![cfg_attr(not(stage0), feature(const_cell_new))]
-#![cfg_attr(not(stage0), feature(const_once_new))]
-#![cfg_attr(not(stage0), feature(const_ptr_null))]
-#![cfg_attr(not(stage0), feature(const_ptr_null_mut))]
+#![cfg_attr(windows, feature(used))]
 
 #![default_lib_allocator]
 
@@ -352,6 +347,7 @@ use prelude::v1::*;
 
 // Access to Bencher, etc.
 #[cfg(test)] extern crate test;
+#[cfg(test)] extern crate rand;
 
 // 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
@@ -360,9 +356,6 @@ use prelude::v1::*;
                  debug_assert_ne, unreachable, unimplemented, write, writeln, try)]
 extern crate core as __core;
 
-#[doc(masked)]
-#[allow(deprecated)]
-extern crate rand as core_rand;
 #[macro_use]
 #[macro_reexport(vec, format)]
 extern crate alloc;
@@ -500,24 +493,12 @@ mod sys;
 
 // Private support modules
 mod panicking;
-mod rand;
 mod memchr;
 
 // The runtime entry point and a few unstable public functions used by the
 // compiler
 pub mod rt;
 
-// Some external utilities of the standard library rely on randomness (aka
-// rustc_back::TempDir and tests) and need a way to get at the OS rng we've got
-// here. This module is not at all intended for stabilization as-is, however,
-// but it may be stabilized long-term. As a result we're exposing a hidden,
-// unstable module so we can get our build working.
-#[doc(hidden)]
-#[unstable(feature = "rand", issue = "27703")]
-pub mod __rand {
-    pub use rand::{thread_rng, ThreadRng, Rng};
-}
-
 // Include a number of private modules that exist solely to provide
 // the rustdoc documentation for primitive types. Using `include!`
 // because rustdoc only looks for these modules at the crate level.
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index 8089671f309..7d62f94056f 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -325,9 +325,10 @@ pub mod builtin {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[macro_export]
-    macro_rules! format_args { ($fmt:expr, $($args:tt)*) => ({
-        /* compiler built-in */
-    }) }
+    macro_rules! format_args {
+        ($fmt:expr) => ({ /* compiler built-in */ });
+        ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ });
+    }
 
     /// Inspect an environment variable at compile time.
     ///
@@ -348,7 +349,10 @@ pub mod builtin {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[macro_export]
-    macro_rules! env { ($name:expr) => ({ /* compiler built-in */ }) }
+    macro_rules! env {
+        ($name:expr) => ({ /* compiler built-in */ });
+        ($name:expr,) => ({ /* compiler built-in */ });
+    }
 
     /// Optionally inspect an environment variable at compile time.
     ///
@@ -400,7 +404,8 @@ pub mod builtin {
     #[unstable(feature = "concat_idents_macro", issue = "29599")]
     #[macro_export]
     macro_rules! concat_idents {
-        ($($e:ident),*) => ({ /* compiler built-in */ })
+        ($($e:ident),*) => ({ /* compiler built-in */ });
+        ($($e:ident,)*) => ({ /* compiler built-in */ });
     }
 
     /// Concatenates literals into a static string slice.
@@ -420,7 +425,10 @@ pub mod builtin {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[macro_export]
-    macro_rules! concat { ($($e:expr),*) => ({ /* compiler built-in */ }) }
+    macro_rules! concat {
+        ($($e:expr),*) => ({ /* compiler built-in */ });
+        ($($e:expr,)*) => ({ /* compiler built-in */ });
+    }
 
     /// A macro which expands to the line number on which it was invoked.
     ///
@@ -490,7 +498,7 @@ pub mod builtin {
     #[macro_export]
     macro_rules! file { () => ({ /* compiler built-in */ }) }
 
-    /// A macro which stringifies its argument.
+    /// A macro which stringifies its arguments.
     ///
     /// This macro will yield an expression of type `&'static str` which is the
     /// stringification of all the tokens passed to the macro. No restrictions
@@ -507,7 +515,7 @@ pub mod builtin {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[macro_export]
-    macro_rules! stringify { ($t:tt) => ({ /* compiler built-in */ }) }
+    macro_rules! stringify { ($($t:tt)*) => ({ /* compiler built-in */ }) }
 
     /// Includes a utf8-encoded file as a string.
     ///
@@ -663,3 +671,39 @@ pub mod builtin {
     #[macro_export]
     macro_rules! include { ($file:expr) => ({ /* compiler built-in */ }) }
 }
+
+/// A macro for defining #[cfg] if-else statements.
+///
+/// This is similar to the `if/elif` C preprocessor macro by allowing definition
+/// of a cascade of `#[cfg]` cases, emitting the implementation which matches
+/// first.
+///
+/// This allows you to conveniently provide a long list #[cfg]'d blocks of code
+/// without having to rewrite each clause multiple times.
+macro_rules! cfg_if {
+    ($(
+        if #[cfg($($meta:meta),*)] { $($it:item)* }
+    ) else * else {
+        $($it2:item)*
+    }) => {
+        __cfg_if_items! {
+            () ;
+            $( ( ($($meta),*) ($($it)*) ), )*
+            ( () ($($it2)*) ),
+        }
+    }
+}
+
+macro_rules! __cfg_if_items {
+    (($($not:meta,)*) ; ) => {};
+    (($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => {
+        __cfg_if_apply! { cfg(all(not(any($($not),*)), $($m,)*)), $($it)* }
+        __cfg_if_items! { ($($not,)* $($m,)*) ; $($rest)* }
+    }
+}
+
+macro_rules! __cfg_if_apply {
+    ($m:meta, $($it:item)*) => {
+        $(#[$m] $it)*
+    }
+}
diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs
index e1d7a2531b6..1ca7e66ed9c 100644
--- a/src/libstd/net/addr.rs
+++ b/src/libstd/net/addr.rs
@@ -759,7 +759,7 @@ impl hash::Hash for SocketAddrV6 {
 /// ```
 ///
 /// [`TcpStream::connect`] is an example of an function that utilizes
-/// `ToSocketsAddr` as a trait bound on its parameter in order to accept
+/// `ToSocketAddrs` as a trait bound on its parameter in order to accept
 /// different types:
 ///
 /// ```no_run
diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs
index eea604943af..c832f8a934d 100644
--- a/src/libstd/net/ip.rs
+++ b/src/libstd/net/ip.rs
@@ -719,7 +719,8 @@ impl Eq for Ipv4Addr {}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl hash::Hash for Ipv4Addr {
     fn hash<H: hash::Hasher>(&self, s: &mut H) {
-        self.inner.s_addr.hash(s)
+        // `inner` is #[repr(packed)], so we need to copy `s_addr`.
+        {self.inner.s_addr}.hash(s)
     }
 }
 
diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs
index aff9af66444..539ff1df187 100644
--- a/src/libstd/net/tcp.rs
+++ b/src/libstd/net/tcp.rs
@@ -167,7 +167,7 @@ impl TcpStream {
     /// connection request.
     ///
     /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
-    #[stable(feature = "tcpstream_connect_timeout", since = "1.22.0")]
+    #[stable(feature = "tcpstream_connect_timeout", since = "1.21.0")]
     pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
         net_imp::TcpStream::connect_timeout(addr, timeout).map(TcpStream)
     }
@@ -194,12 +194,12 @@ impl TcpStream {
     /// # Examples
     ///
     /// ```no_run
-    /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpStream};
+    /// use std::net::{IpAddr, Ipv4Addr, TcpStream};
     ///
     /// let stream = TcpStream::connect("127.0.0.1:8080")
     ///                        .expect("Couldn't connect to the server...");
-    /// assert_eq!(stream.local_addr().unwrap(),
-    ///            SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080)));
+    /// assert_eq!(stream.local_addr().unwrap().ip(),
+    ///            IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn local_addr(&self) -> io::Result<SocketAddr> {
@@ -498,18 +498,46 @@ impl TcpStream {
 
     /// Moves this TCP stream into or out of nonblocking mode.
     ///
-    /// On Unix this corresponds to calling fcntl, and on Windows this
-    /// corresponds to calling ioctlsocket.
+    /// This will result in `read`, `write`, `recv` and `send` operations
+    /// becoming nonblocking, i.e. immediately returning from their calls.
+    /// If the IO operation is successful, `Ok` is returned and no further
+    /// action is required. If the IO operation could not be completed and needs
+    /// to be retried, an error with kind [`io::ErrorKind::WouldBlock`] is
+    /// returned.
+    ///
+    /// On Unix platforms, calling this method corresponds to calling `fcntl`
+    /// `FIONBIO`. On Windows calling this method corresponds to calling
+    /// `ioctlsocket` `FIONBIO`.
     ///
     /// # Examples
     ///
+    /// Reading bytes from a TCP stream in non-blocking mode:
+    ///
     /// ```no_run
+    /// use std::io::{self, Read};
     /// use std::net::TcpStream;
     ///
-    /// let stream = TcpStream::connect("127.0.0.1:8080")
-    ///                        .expect("Couldn't connect to the server...");
+    /// let mut stream = TcpStream::connect("127.0.0.1:7878")
+    ///     .expect("Couldn't connect to the server...");
     /// stream.set_nonblocking(true).expect("set_nonblocking call failed");
+    ///
+    /// # fn wait_for_fd() { unimplemented!() }
+    /// let mut buf = vec![];
+    /// loop {
+    ///     match stream.read_to_end(&mut buf) {
+    ///         Ok(_) => break,
+    ///         Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+    ///             // wait until network socket is ready, typically implemented
+    ///             // via platform-specific APIs such as epoll or IOCP
+    ///             wait_for_fd();
+    ///         }
+    ///         Err(e) => panic!("encountered IO error: {}", e),
+    ///     };
+    /// };
+    /// println!("bytes: {:?}", buf);
     /// ```
+    ///
+    /// [`io::ErrorKind::WouldBlock`]: ../io/enum.ErrorKind.html#variant.WouldBlock
     #[stable(feature = "net2_mutators", since = "1.9.0")]
     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
         self.0.set_nonblocking(nonblocking)
@@ -780,17 +808,48 @@ impl TcpListener {
 
     /// Moves this TCP stream into or out of nonblocking mode.
     ///
-    /// On Unix this corresponds to calling fcntl, and on Windows this
-    /// corresponds to calling ioctlsocket.
+    /// This will result in the `accept` operation becoming nonblocking,
+    /// i.e. immediately returning from their calls. If the IO operation is
+    /// successful, `Ok` is returned and no further action is required. If the
+    /// IO operation could not be completed and needs to be retried, an error
+    /// with kind [`io::ErrorKind::WouldBlock`] is returned.
+    ///
+    /// On Unix platforms, calling this method corresponds to calling `fcntl`
+    /// `FIONBIO`. On Windows calling this method corresponds to calling
+    /// `ioctlsocket` `FIONBIO`.
     ///
     /// # Examples
     ///
+    /// Bind a TCP listener to an address, listen for connections, and read
+    /// bytes in nonblocking mode:
+    ///
     /// ```no_run
+    /// use std::io;
     /// use std::net::TcpListener;
     ///
-    /// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
+    /// let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
     /// listener.set_nonblocking(true).expect("Cannot set non-blocking");
+    ///
+    /// # fn wait_for_fd() { unimplemented!() }
+    /// # fn handle_connection(stream: std::net::TcpStream) { unimplemented!() }
+    /// for stream in listener.incoming() {
+    ///     match stream {
+    ///         Ok(s) => {
+    ///             // do something with the TcpStream
+    ///             handle_connection(s);
+    ///         }
+    ///         Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+    ///             // wait until network socket is ready, typically implemented
+    ///             // via platform-specific APIs such as epoll or IOCP
+    ///             wait_for_fd();
+    ///             continue;
+    ///         }
+    ///         Err(e) => panic!("encountered IO error: {}", e),
+    ///     }
+    /// }
     /// ```
+    ///
+    /// [`io::ErrorKind::WouldBlock`]: ../io/enum.ErrorKind.html#variant.WouldBlock
     #[stable(feature = "net2_mutators", since = "1.9.0")]
     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
         self.0.set_nonblocking(nonblocking)
@@ -1580,6 +1639,21 @@ mod tests {
     }
 
     #[test]
+    fn connect_timeout_unbound() {
+        // bind and drop a socket to track down a "probably unassigned" port
+        let socket = TcpListener::bind("127.0.0.1:0").unwrap();
+        let addr = socket.local_addr().unwrap();
+        drop(socket);
+
+        let timeout = Duration::from_secs(1);
+        let e = TcpStream::connect_timeout(&addr, timeout).unwrap_err();
+        assert!(e.kind() == io::ErrorKind::ConnectionRefused ||
+                e.kind() == io::ErrorKind::TimedOut ||
+                e.kind() == io::ErrorKind::Other,
+                "bad error: {} {:?}", e, e.kind());
+    }
+
+    #[test]
     fn connect_timeout_valid() {
         let listener = TcpListener::bind("127.0.0.1:0").unwrap();
         let addr = listener.local_addr().unwrap();
diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs
index a8a242846d7..84ceaa65951 100644
--- a/src/libstd/net/udp.rs
+++ b/src/libstd/net/udp.rs
@@ -168,7 +168,7 @@ impl UdpSocket {
     /// This will return an error when the IP version of the local socket
     /// does not match that returned from [`ToSocketAddrs`].
     ///
-    /// See https://github.com/rust-lang/rust/issues/34202 for more details.
+    /// See <https://github.com/rust-lang/rust/issues/34202> for more details.
     ///
     /// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
     ///
@@ -721,16 +721,45 @@ impl UdpSocket {
 
     /// Moves this UDP socket into or out of nonblocking mode.
     ///
-    /// On Unix this corresponds to calling fcntl, and on Windows this
-    /// corresponds to calling ioctlsocket.
+    /// This will result in `recv`, `recv_from`, `send`, and `send_to`
+    /// operations becoming nonblocking, i.e. immediately returning from their
+    /// calls. If the IO operation is successful, `Ok` is returned and no
+    /// further action is required. If the IO operation could not be completed
+    /// and needs to be retried, an error with kind
+    /// [`io::ErrorKind::WouldBlock`] is returned.
+    ///
+    /// On Unix platforms, calling this method corresponds to calling `fcntl`
+    /// `FIONBIO`. On Windows calling this method corresponds to calling
+    /// `ioctlsocket` `FIONBIO`.
+    ///
+    /// [`io::ErrorKind::WouldBlock`]: ../io/enum.ErrorKind.html#variant.WouldBlock
     ///
     /// # Examples
     ///
+    /// Create a UDP socket bound to `127.0.0.1:7878` and read bytes in
+    /// nonblocking mode:
+    ///
     /// ```no_run
+    /// use std::io;
     /// use std::net::UdpSocket;
     ///
-    /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
-    /// socket.set_nonblocking(true).expect("set_nonblocking call failed");
+    /// let socket = UdpSocket::bind("127.0.0.1:7878").unwrap();
+    /// socket.set_nonblocking(true).unwrap();
+    ///
+    /// # fn wait_for_fd() { unimplemented!() }
+    /// let mut buf = [0; 10];
+    /// let (num_bytes_read, _) = loop {
+    ///     match socket.recv_from(&mut buf) {
+    ///         Ok(n) => break n,
+    ///         Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+    ///             // wait until network socket is ready, typically implemented
+    ///             // via platform-specific APIs such as epoll or IOCP
+    ///             wait_for_fd();
+    ///         }
+    ///         Err(e) => panic!("encountered IO error: {}", e),
+    ///     }
+    /// };
+    /// println!("bytes: {:?}", &buf[..num_bytes_read]);
     /// ```
     #[stable(feature = "net2_mutators", since = "1.9.0")]
     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
diff --git a/src/libstd/os/linux/fs.rs b/src/libstd/os/linux/fs.rs
index 7ebda5ed744..5d37d970e89 100644
--- a/src/libstd/os/linux/fs.rs
+++ b/src/libstd/os/linux/fs.rs
@@ -24,9 +24,25 @@ 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
+    /// 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.
+    ///
+    /// [`stat`]: ../../../../std/os/linux/raw/struct.stat.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let stat = meta.as_raw_stat();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     #[rustc_deprecated(since = "1.8.0",
                        reason = "deprecated in favor of the accessor \
@@ -35,54 +51,278 @@ pub trait MetadataExt {
     fn as_raw_stat(&self) -> &raw::stat;
 
     /// Returns the device ID on which this file resides.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// println!("{}", meta.st_dev());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_dev(&self) -> u64;
     /// Returns the inode number.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// println!("{}", meta.st_ino());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_ino(&self) -> u64;
     /// Returns the file type and mode.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// println!("{}", meta.st_mode());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_mode(&self) -> u32;
     /// Returns the number of hard links to file.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// println!("{}", meta.st_nlink());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_nlink(&self) -> u64;
     /// Returns the user ID of the file owner.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// println!("{}", meta.st_uid());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_uid(&self) -> u32;
     /// Returns the group ID of the file owner.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// println!("{}", meta.st_gid());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_gid(&self) -> u32;
     /// Returns the device ID that this file represents. Only relevant for special file.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// println!("{}", meta.st_rdev());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_rdev(&self) -> u64;
     /// Returns the size of the file (if it is a regular file or a symbolic link) in bytes.
     ///
     /// The size of a symbolic link is the length of the pathname it contains,
     /// without a terminating null byte.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// println!("{}", meta.st_size());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_size(&self) -> u64;
     /// Returns the last access time.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// println!("{}", meta.st_atime());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_atime(&self) -> i64;
     /// Returns the last access time, nano seconds part.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// println!("{}", meta.st_atime_nsec());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_atime_nsec(&self) -> i64;
     /// Returns the last modification time.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// println!("{}", meta.st_mtime());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_mtime(&self) -> i64;
     /// Returns the last modification time, nano seconds part.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// println!("{}", meta.st_mtime_nsec());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_mtime_nsec(&self) -> i64;
     /// Returns the last status change time.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// println!("{}", meta.st_ctime());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_ctime(&self) -> i64;
     /// Returns the last status change time, nano seconds part.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// println!("{}", meta.st_ctime_nsec());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_ctime_nsec(&self) -> i64;
     /// Returns the "preferred" blocksize for efficient filesystem I/O.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// println!("{}", meta.st_blksize());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_blksize(&self) -> u64;
     /// Returns the number of blocks allocated to the file, 512-byte units.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// println!("{}", meta.st_blocks());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_blocks(&self) -> u64;
 }
diff --git a/src/libstd/os/mod.rs b/src/libstd/os/mod.rs
index b460bd90f17..ac7809451d1 100644
--- a/src/libstd/os/mod.rs
+++ b/src/libstd/os/mod.rs
@@ -13,36 +13,53 @@
 #![stable(feature = "os", since = "1.0.0")]
 #![allow(missing_docs, bad_style, missing_debug_implementations)]
 
-#[cfg(all(not(dox), any(target_os = "redox", unix)))]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use sys::ext as unix;
-#[cfg(all(not(dox), windows))]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use sys::ext as windows;
-
-#[cfg(dox)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use sys::unix_ext as unix;
-#[cfg(dox)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use sys::windows_ext as windows;
-
-#[cfg(any(dox, target_os = "linux", target_os = "l4re"))]
-#[doc(cfg(target_os = "linux"))]
-pub mod linux;
-
-#[cfg(all(not(dox), target_os = "android"))]    pub mod android;
-#[cfg(all(not(dox), target_os = "bitrig"))]     pub mod bitrig;
-#[cfg(all(not(dox), target_os = "dragonfly"))]  pub mod dragonfly;
-#[cfg(all(not(dox), target_os = "freebsd"))]    pub mod freebsd;
-#[cfg(all(not(dox), target_os = "haiku"))]      pub mod haiku;
-#[cfg(all(not(dox), target_os = "ios"))]        pub mod ios;
-#[cfg(all(not(dox), target_os = "macos"))]      pub mod macos;
-#[cfg(all(not(dox), target_os = "nacl"))]       pub mod nacl;
-#[cfg(all(not(dox), target_os = "netbsd"))]     pub mod netbsd;
-#[cfg(all(not(dox), target_os = "openbsd"))]    pub mod openbsd;
-#[cfg(all(not(dox), target_os = "solaris"))]    pub mod solaris;
-#[cfg(all(not(dox), target_os = "emscripten"))] pub mod emscripten;
-#[cfg(all(not(dox), target_os = "fuchsia"))]    pub mod fuchsia;
+cfg_if! {
+    if #[cfg(dox)] {
+
+        // When documenting libstd we want to show unix/windows/linux modules as
+        // these are the "main modules" that are used across platforms. This
+        // should help show platform-specific functionality in a hopefully
+        // cross-platform way in the documentation
+
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub use sys::unix_ext as unix;
+
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub use sys::windows_ext as windows;
+
+        #[doc(cfg(target_os = "linux"))]
+        pub mod linux;
+
+    } else {
+
+        // If we're not documenting libstd then we just expose everything as we
+        // otherwise would.
+
+        #[cfg(target_os = "android")]    pub mod android;
+        #[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 = "macos")]      pub mod macos;
+        #[cfg(target_os = "netbsd")]     pub mod netbsd;
+        #[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;
+
+        #[cfg(any(target_os = "redox", unix))]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub use sys::ext as unix;
+
+        #[cfg(windows)]
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub use sys::ext as windows;
+
+        #[cfg(any(target_os = "linux", target_os = "l4re"))]
+        pub mod linux;
+
+    }
+}
 
 pub mod raw;
diff --git a/src/libstd/os/nacl/fs.rs b/src/libstd/os/nacl/fs.rs
deleted file mode 100644
index 3e0fb44b01e..00000000000
--- a/src/libstd/os/nacl/fs.rs
+++ /dev/null
@@ -1,128 +0,0 @@
-// 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::nacl::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_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::stat64
-                                          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_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/nacl/raw.rs b/src/libstd/os/nacl/raw.rs
deleted file mode 100644
index 3c3d4410a2a..00000000000
--- a/src/libstd/os/nacl/raw.rs
+++ /dev/null
@@ -1,56 +0,0 @@
-// 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.
-
-//! Nacl-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)]
-
-#[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64;
-#[stable(feature = "raw_ext", since = "1.1.0")] pub type off_t = u64;
-#[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_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 pid_t = i32;
-#[stable(feature = "raw_ext", since = "1.1.0")] pub type uid_t = u32;
-#[stable(feature = "raw_ext", since = "1.1.0")] pub type gid_t = u32;
-#[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 = u64;
-#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
-#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
-
-#[stable(feature = "pthread_t", since = "1.8.0")]
-pub type pthread_t = usize;
-
-#[repr(C)]
-#[derive(Copy, 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_rdev: dev_t,
-    #[stable(feature = "raw_ext", since = "1.1.0")] pub st_size: off_t,
-    #[stable(feature = "raw_ext", since = "1.1.0")] pub st_blksize: blksize_t,
-    #[stable(feature = "raw_ext", since = "1.1.0")] pub st_blocks: blkcnt_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: i64,
-    #[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: i64,
-    #[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: i64,
-}
diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs
index 97b09b7e2ad..219e55d6c12 100644
--- a/src/libstd/panic.rs
+++ b/src/libstd/panic.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Panic support in the standard library
+//! Panic support in the standard library.
 
 #![stable(feature = "std_panic", since = "1.9.0")]
 
@@ -188,6 +188,8 @@ pub struct AssertUnwindSafe<T>(
 // * Types like Mutex/RwLock which are explicilty poisoned are unwind safe
 // * Our custom AssertUnwindSafe wrapper is indeed unwind safe
 #[stable(feature = "catch_unwind", since = "1.9.0")]
+#[allow(unknown_lints)]
+#[allow(auto_impl)]
 impl UnwindSafe for .. {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<'a, T: ?Sized> !UnwindSafe for &'a mut T {}
@@ -221,6 +223,8 @@ impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Arc<T> {}
 // only thing which doesn't implement it (which then transitively applies to
 // everything else).
 #[stable(feature = "catch_unwind", since = "1.9.0")]
+#[allow(unknown_lints)]
+#[allow(auto_impl)]
 impl RefUnwindSafe for .. {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T: ?Sized> !RefUnwindSafe for UnsafeCell<T> {}
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index 830b9dc475d..eb125a4737a 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -77,7 +77,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use ascii::*;
 use borrow::{Borrow, Cow};
 use cmp;
 use error::Error;
@@ -86,8 +85,9 @@ use fs;
 use hash::{Hash, Hasher};
 use io;
 use iter::{self, FusedIterator};
-use mem;
 use ops::{self, Deref};
+use rc::Rc;
+use sync::Arc;
 
 use ffi::{OsStr, OsString};
 
@@ -317,10 +317,10 @@ fn iter_after<A, I, J>(mut iter: I, mut prefix: J) -> Option<I>
 
 // See note at the top of this module to understand why these are used:
 fn os_str_as_u8_slice(s: &OsStr) -> &[u8] {
-    unsafe { mem::transmute(s) }
+    unsafe { &*(s as *const OsStr as *const [u8]) }
 }
 unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr {
-    mem::transmute(s)
+    &*(s as *const [u8] as *const OsStr)
 }
 
 // Detect scheme on Redox
@@ -1334,7 +1334,8 @@ impl PathBuf {
     /// [`Path`]: struct.Path.html
     #[stable(feature = "into_boxed_path", since = "1.20.0")]
     pub fn into_boxed_path(self) -> Box<Path> {
-        unsafe { mem::transmute(self.inner.into_boxed_os_str()) }
+        let rw = Box::into_raw(self.inner.into_boxed_os_str()) as *mut Path;
+        unsafe { Box::from_raw(rw) }
     }
 }
 
@@ -1342,7 +1343,8 @@ impl PathBuf {
 impl<'a> From<&'a Path> for Box<Path> {
     fn from(path: &'a Path) -> Box<Path> {
         let boxed: Box<OsStr> = path.inner.into();
-        unsafe { mem::transmute(boxed) }
+        let rw = Box::into_raw(boxed) as *mut Path;
+        unsafe { Box::from_raw(rw) }
     }
 }
 
@@ -1452,6 +1454,42 @@ impl<'a> From<PathBuf> for Cow<'a, Path> {
     }
 }
 
+#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+impl From<PathBuf> for Arc<Path> {
+    #[inline]
+    fn from(s: PathBuf) -> Arc<Path> {
+        let arc: Arc<OsStr> = Arc::from(s.into_os_string());
+        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) }
+    }
+}
+
+#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+impl<'a> From<&'a Path> for Arc<Path> {
+    #[inline]
+    fn from(s: &Path) -> Arc<Path> {
+        let arc: Arc<OsStr> = Arc::from(s.as_os_str());
+        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) }
+    }
+}
+
+#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+impl From<PathBuf> for Rc<Path> {
+    #[inline]
+    fn from(s: PathBuf) -> Rc<Path> {
+        let rc: Rc<OsStr> = Rc::from(s.into_os_string());
+        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) }
+    }
+}
+
+#[stable(feature = "shared_from_slice2", since = "1.23.0")]
+impl<'a> From<&'a Path> for Rc<Path> {
+    #[inline]
+    fn from(s: &Path) -> Rc<Path> {
+        let rc: Rc<OsStr> = Rc::from(s.as_os_str());
+        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) }
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl ToOwned for Path {
     type Owned = PathBuf;
@@ -1589,7 +1627,7 @@ impl Path {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &Path {
-        unsafe { mem::transmute(s.as_ref()) }
+        unsafe { &*(s.as_ref() as *const OsStr as *const Path) }
     }
 
     /// Yields the underlying [`OsStr`] slice.
@@ -1690,11 +1728,11 @@ impl Path {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[allow(deprecated)]
     pub fn is_absolute(&self) -> bool {
-        if !cfg!(target_os = "redox") {
-            self.has_root() && (cfg!(unix) || self.prefix().is_some())
-        } else {
+        if cfg!(target_os = "redox") {
             // FIXME: Allow Redox prefixes
-            has_redox_scheme(self.as_u8_slice())
+            self.has_root() || has_redox_scheme(self.as_u8_slice())
+        } else {
+            self.has_root() && (cfg!(unix) || self.prefix().is_some())
         }
     }
 
@@ -2312,7 +2350,8 @@ impl Path {
     /// [`PathBuf`]: struct.PathBuf.html
     #[stable(feature = "into_boxed_path", since = "1.20.0")]
     pub fn into_path_buf(self: Box<Path>) -> PathBuf {
-        let inner: Box<OsStr> = unsafe { mem::transmute(self) };
+        let rw = Box::into_raw(self) as *mut OsStr;
+        let inner = unsafe { Box::from_raw(rw) };
         PathBuf { inner: OsString::from(inner) }
     }
 }
@@ -2567,6 +2606,9 @@ impl Error for StripPrefixError {
 mod tests {
     use super::*;
 
+    use rc::Rc;
+    use sync::Arc;
+
     macro_rules! t(
         ($path:expr, iter: $iter:expr) => (
             {
@@ -3751,7 +3793,7 @@ mod tests {
     }
 
     #[test]
-    fn test_eq_recievers() {
+    fn test_eq_receivers() {
         use borrow::Cow;
 
         let borrowed: &Path = Path::new("foo/bar");
@@ -3969,4 +4011,21 @@ mod tests {
         assert_eq!(format!("a{:#<5}b", Path::new("").display()), "a#####b");
         assert_eq!(format!("a{:#<5}b", Path::new("a").display()), "aa####b");
     }
+
+    #[test]
+    fn into_rc() {
+        let orig = "hello/world";
+        let path = Path::new(orig);
+        let rc: Rc<Path> = Rc::from(path);
+        let arc: Arc<Path> = Arc::from(path);
+
+        assert_eq!(&*rc, path);
+        assert_eq!(&*arc, path);
+
+        let rc2: Rc<Path> = Rc::from(path.to_owned());
+        let arc2: Arc<Path> = Arc::from(path.to_owned());
+
+        assert_eq!(&*rc2, path);
+        assert_eq!(&*arc2, path);
+    }
 }
diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs
index 1edb35d8fe7..9e1da318242 100644
--- a/src/libstd/primitive_docs.rs
+++ b/src/libstd/primitive_docs.rs
@@ -284,7 +284,6 @@ mod prim_pointer { }
 /// Arrays of sizes from 0 to 32 (inclusive) implement the following traits if
 /// the element type allows it:
 ///
-/// - [`Clone`][clone] (only if `T: `[`Copy`][copy])
 /// - [`Debug`][debug]
 /// - [`IntoIterator`][intoiterator] (implemented for `&[T; N]` and `&mut [T; N]`)
 /// - [`PartialEq`][partialeq], [`PartialOrd`][partialord], [`Eq`][eq], [`Ord`][ord]
@@ -299,8 +298,10 @@ mod prim_pointer { }
 /// entirely different types. As a stopgap, trait implementations are
 /// statically generated up to size 32.
 ///
-/// Arrays of *any* size are [`Copy`][copy] if the element type is [`Copy`][copy]. This
-/// works because the [`Copy`][copy] trait is specially known to the compiler.
+/// Arrays of *any* size are [`Copy`][copy] if the element type is [`Copy`][copy]
+/// and [`Clone`][clone] if the element type is [`Clone`][clone]. This works
+/// because [`Copy`][copy] and [`Clone`][clone] traits are specially known
+/// to the compiler.
 ///
 /// Arrays coerce to [slices (`[T]`)][slice], so a slice method may be called on
 /// an array. Indeed, this provides most of the API for working with arrays.
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index 1869ad3ed70..2335695ae42 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -10,25 +10,66 @@
 
 //! A module for working with processes.
 //!
-//! # Examples
+//! This module is mostly concerned with spawning and interacting with child
+//! processes, but it also provides [`abort`] and [`exit`] for terminating the
+//! current process.
 //!
-//! Basic usage where we try to execute the `cat` shell command:
+//! # Spawning a process
 //!
-//! ```should_panic
+//! The [`Command`] struct is used to configure and spawn processes:
+//!
+//! ```
 //! use std::process::Command;
 //!
-//! let mut child = Command::new("/bin/cat")
-//!                         .arg("file.txt")
-//!                         .spawn()
-//!                         .expect("failed to execute child");
+//! let output = Command::new("echo")
+//!                      .arg("Hello world")
+//!                      .output()
+//!                      .expect("Failed to execute command");
+//!
+//! assert_eq!(b"Hello world\n", output.stdout.as_slice());
+//! ```
+//!
+//! Several methods on [`Command`], such as [`spawn`] or [`output`], can be used
+//! to spawn a process. In particular, [`output`] spawns the child process and
+//! waits until the process terminates, while [`spawn`] will return a [`Child`]
+//! that represents the spawned child process.
+//!
+//! # Handling I/O
+//!
+//! The [`stdout`], [`stdin`], and [`stderr`] of a child process can be
+//! configured by passing an [`Stdio`] to the corresponding method on
+//! [`Command`]. Once spawned, they can be accessed from the [`Child`]. For
+//! example, piping output from one command into another command can be done
+//! like so:
+//!
+//! ```no_run
+//! use std::process::{Command, Stdio};
+//!
+//! // stdout must be configured with `Stdio::piped` in order to use
+//! // `echo_child.stdout`
+//! let echo_child = Command::new("echo")
+//!     .arg("Oh no, a tpyo!")
+//!     .stdout(Stdio::piped())
+//!     .spawn()
+//!     .expect("Failed to start echo process");
 //!
-//! let ecode = child.wait()
-//!                  .expect("failed to wait on child");
+//! // Note that `echo_child` is moved here, but we won't be needing
+//! // `echo_child` anymore
+//! let echo_out = echo_child.stdout.expect("Failed to open echo stdout");
 //!
-//! assert!(ecode.success());
+//! let mut sed_child = Command::new("sed")
+//!     .arg("s/tpyo/typo/")
+//!     .stdin(Stdio::from(echo_out))
+//!     .stdout(Stdio::piped())
+//!     .spawn()
+//!     .expect("Failed to start sed process");
+//!
+//! let output = sed_child.wait_with_output().expect("Failed to wait on sed");
+//! assert_eq!(b"Oh no, a typo!\n", output.stdout.as_slice());
 //! ```
 //!
-//! Calling a command with input and reading its output:
+//! Note that [`ChildStderr`] and [`ChildStdout`] implement [`Write`] and
+//! [`ChildStdin`] implements [`Read`]:
 //!
 //! ```no_run
 //! use std::process::{Command, Stdio};
@@ -52,6 +93,26 @@
 //!
 //! assert_eq!(b"test", output.stdout.as_slice());
 //! ```
+//!
+//! [`abort`]: fn.abort.html
+//! [`exit`]: fn.exit.html
+//!
+//! [`Command`]: struct.Command.html
+//! [`spawn`]: struct.Command.html#method.spawn
+//! [`output`]: struct.Command.html#method.output
+//!
+//! [`Child`]: struct.Child.html
+//! [`ChildStdin`]: struct.ChildStdin.html
+//! [`ChildStdout`]: struct.ChildStdout.html
+//! [`ChildStderr`]: struct.ChildStderr.html
+//! [`Stdio`]: struct.Stdio.html
+//!
+//! [`stdout`]: struct.Command.html#method.stdout
+//! [`stdin`]: struct.Command.html#method.stdin
+//! [`stderr`]: struct.Command.html#method.stderr
+//!
+//! [`Write`]: ../io/trait.Write.html
+//! [`Read`]: ../io/trait.Read.html
 
 #![stable(feature = "process", since = "1.0.0")]
 
@@ -343,7 +404,7 @@ impl Command {
     /// The search path to be used may be controlled by setting the
     /// `PATH` environment variable on the Command,
     /// but this has some implementation limitations on Windows
-    /// (see https://github.com/rust-lang/rust/issues/37519).
+    /// (see <https://github.com/rust-lang/rust/issues/37519>).
     ///
     /// # Examples
     ///
@@ -552,6 +613,12 @@ impl Command {
 
     /// Configuration for the child process's standard input (stdin) handle.
     ///
+    /// Defaults to [`inherit`] when used with `spawn` or `status`, and
+    /// defaults to [`piped`] when used with `output`.
+    ///
+    /// [`inherit`]: struct.Stdio.html#method.inherit
+    /// [`piped`]: struct.Stdio.html#method.piped
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -572,6 +639,12 @@ impl Command {
 
     /// Configuration for the child process's standard output (stdout) handle.
     ///
+    /// Defaults to [`inherit`] when used with `spawn` or `status`, and
+    /// defaults to [`piped`] when used with `output`.
+    ///
+    /// [`inherit`]: struct.Stdio.html#method.inherit
+    /// [`piped`]: struct.Stdio.html#method.piped
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -592,6 +665,12 @@ impl Command {
 
     /// Configuration for the child process's standard error (stderr) handle.
     ///
+    /// Defaults to [`inherit`] when used with `spawn` or `status`, and
+    /// defaults to [`piped`] when used with `output`.
+    ///
+    /// [`inherit`]: struct.Stdio.html#method.inherit
+    /// [`piped`]: struct.Stdio.html#method.piped
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -633,8 +712,10 @@ impl Command {
     /// Executes the command as a child process, waiting for it to finish and
     /// collecting all of its output.
     ///
-    /// By default, stdin, stdout and stderr are captured (and used to
-    /// provide the resulting output).
+    /// By default, stdout and stderr are captured (and used to provide the
+    /// resulting output). Stdin is not inherited from the parent and any
+    /// attempt by the child process to read from the stdin stream will result
+    /// in the stream immediately closing.
     ///
     /// # Examples
     ///
@@ -702,6 +783,15 @@ impl AsInnerMut<imp::Command> for Command {
 }
 
 /// The output of a finished process.
+///
+/// This is returned in a Result by either the [`output`] method of a
+/// [`Command`], or the [`wait_with_output`] method of a [`Child`]
+/// process.
+///
+/// [`Command`]: struct.Command.html
+/// [`Child`]: struct.Child.html
+/// [`output`]: struct.Command.html#method.output
+/// [`wait_with_output`]: struct.Child.html#method.wait_with_output
 #[derive(PartialEq, Eq, Clone)]
 #[stable(feature = "process", since = "1.0.0")]
 pub struct Output {
@@ -742,21 +832,128 @@ impl fmt::Debug for Output {
     }
 }
 
-/// Describes what to do with a standard I/O stream for a child process.
+/// Describes what to do with a standard I/O stream for a child process when
+/// passed to the [`stdin`], [`stdout`], and [`stderr`] methods of [`Command`].
+///
+/// [`stdin`]: struct.Command.html#method.stdin
+/// [`stdout`]: struct.Command.html#method.stdout
+/// [`stderr`]: struct.Command.html#method.stderr
+/// [`Command`]: struct.Command.html
 #[stable(feature = "process", since = "1.0.0")]
 pub struct Stdio(imp::Stdio);
 
 impl Stdio {
     /// A new pipe should be arranged to connect the parent and child processes.
+    ///
+    /// # Examples
+    ///
+    /// With stdout:
+    ///
+    /// ```no_run
+    /// use std::process::{Command, Stdio};
+    ///
+    /// let output = Command::new("echo")
+    ///     .arg("Hello, world!")
+    ///     .stdout(Stdio::piped())
+    ///     .output()
+    ///     .expect("Failed to execute command");
+    ///
+    /// assert_eq!(String::from_utf8_lossy(&output.stdout), "Hello, world!\n");
+    /// // Nothing echoed to console
+    /// ```
+    ///
+    /// With stdin:
+    ///
+    /// ```no_run
+    /// use std::io::Write;
+    /// use std::process::{Command, Stdio};
+    ///
+    /// let mut child = Command::new("rev")
+    ///     .stdin(Stdio::piped())
+    ///     .stdout(Stdio::piped())
+    ///     .spawn()
+    ///     .expect("Failed to spawn child process");
+    ///
+    /// {
+    ///     let mut stdin = child.stdin.as_mut().expect("Failed to open stdin");
+    ///     stdin.write_all("Hello, world!".as_bytes()).expect("Failed to write to stdin");
+    /// }
+    ///
+    /// let output = child.wait_with_output().expect("Failed to read stdout");
+    /// assert_eq!(String::from_utf8_lossy(&output.stdout), "!dlrow ,olleH\n");
+    /// ```
     #[stable(feature = "process", since = "1.0.0")]
     pub fn piped() -> Stdio { Stdio(imp::Stdio::MakePipe) }
 
     /// The child inherits from the corresponding parent descriptor.
+    ///
+    /// # Examples
+    ///
+    /// With stdout:
+    ///
+    /// ```no_run
+    /// use std::process::{Command, Stdio};
+    ///
+    /// let output = Command::new("echo")
+    ///     .arg("Hello, world!")
+    ///     .stdout(Stdio::inherit())
+    ///     .output()
+    ///     .expect("Failed to execute command");
+    ///
+    /// assert_eq!(String::from_utf8_lossy(&output.stdout), "");
+    /// // "Hello, world!" echoed to console
+    /// ```
+    ///
+    /// With stdin:
+    ///
+    /// ```no_run
+    /// use std::process::{Command, Stdio};
+    ///
+    /// let output = Command::new("rev")
+    ///     .stdin(Stdio::inherit())
+    ///     .stdout(Stdio::piped())
+    ///     .output()
+    ///     .expect("Failed to execute command");
+    ///
+    /// println!("You piped in the reverse of: {}", String::from_utf8_lossy(&output.stdout));
+    /// ```
     #[stable(feature = "process", since = "1.0.0")]
     pub fn inherit() -> Stdio { Stdio(imp::Stdio::Inherit) }
 
     /// This stream will be ignored. This is the equivalent of attaching the
     /// stream to `/dev/null`
+    ///
+    /// # Examples
+    ///
+    /// With stdout:
+    ///
+    /// ```no_run
+    /// use std::process::{Command, Stdio};
+    ///
+    /// let output = Command::new("echo")
+    ///     .arg("Hello, world!")
+    ///     .stdout(Stdio::null())
+    ///     .output()
+    ///     .expect("Failed to execute command");
+    ///
+    /// assert_eq!(String::from_utf8_lossy(&output.stdout), "");
+    /// // Nothing echoed to console
+    /// ```
+    ///
+    /// With stdin:
+    ///
+    /// ```no_run
+    /// use std::process::{Command, Stdio};
+    ///
+    /// let output = Command::new("rev")
+    ///     .stdin(Stdio::null())
+    ///     .stdout(Stdio::piped())
+    ///     .output()
+    ///     .expect("Failed to execute command");
+    ///
+    /// assert_eq!(String::from_utf8_lossy(&output.stdout), "");
+    /// // Ignores any piped-in input
+    /// ```
     #[stable(feature = "process", since = "1.0.0")]
     pub fn null() -> Stdio { Stdio(imp::Stdio::Null) }
 }
@@ -1083,8 +1280,6 @@ impl Child {
 /// function and compute the exit code from its return value:
 ///
 /// ```
-/// use std::io::{self, Write};
-///
 /// fn run_app() -> Result<(), ()> {
 ///     // Application logic here
 ///     Ok(())
@@ -1094,7 +1289,7 @@ impl Child {
 ///     ::std::process::exit(match run_app() {
 ///        Ok(_) => 0,
 ///        Err(err) => {
-///            writeln!(io::stderr(), "error: {:?}", err).unwrap();
+///            eprintln!("error: {:?}", err);
 ///            1
 ///        }
 ///     });
@@ -1124,7 +1319,15 @@ pub fn exit(code: i32) -> ! {
 ///
 /// Note that because this function never returns, and that it terminates the
 /// process, no destructors on the current stack or any other thread's stack
-/// will be run. If a clean shutdown is needed it is recommended to only call
+/// will be run.
+///
+/// This is in contrast to the default behaviour of [`panic!`] which unwinds
+/// the current thread's stack and calls all destructors.
+/// When `panic="abort"` is set, either as an argument to `rustc` or in a
+/// crate's Cargo.toml, [`panic!`] and `abort` are similar. However,
+/// [`panic!`] will still call the [panic hook] while `abort` will not.
+///
+/// If a clean shutdown is needed it is recommended to only call
 /// this function at a known point where there are no more destructors left
 /// to run.
 ///
@@ -1142,7 +1345,7 @@ pub fn exit(code: i32) -> ! {
 /// }
 /// ```
 ///
-/// The [`abort`] function terminates the process, so the destructor will not
+/// The `abort` function terminates the process, so the destructor will not
 /// get run on the example below:
 ///
 /// ```no_run
@@ -1162,11 +1365,33 @@ pub fn exit(code: i32) -> ! {
 ///     // the destructor implemented for HasDrop will never get run
 /// }
 /// ```
+///
+/// [`panic!`]: ../../std/macro.panic.html
+/// [panic hook]: ../../std/panic/fn.set_hook.html
 #[stable(feature = "process_abort", since = "1.17.0")]
 pub fn abort() -> ! {
     unsafe { ::sys::abort_internal() };
 }
 
+/// Returns the OS-assigned process identifier associated with this process.
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```no_run
+/// #![feature(getpid)]
+/// use std::process;
+///
+/// println!("My pid is {}", process::id());
+/// ```
+///
+///
+#[unstable(feature = "getpid", issue = "44971", reason = "recently added")]
+pub fn id() -> u32 {
+    ::sys::os::getpid()
+}
+
 #[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
deleted file mode 100644
index 8da070e7a49..00000000000
--- a/src/libstd/rand/mod.rs
+++ /dev/null
@@ -1,286 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Utilities for random number generation
-//!
-//! The key functions are `random()` and `Rng::gen()`. These are polymorphic
-//! and so can be used to generate any type that implements `Rand`. Type inference
-//! means that often a simple call to `rand::random()` or `rng.gen()` will
-//! suffice, but sometimes an annotation is required, e.g. `rand::random::<f64>()`.
-//!
-//! See the `distributions` submodule for sampling random numbers from
-//! distributions like normal and exponential.
-//!
-//! # Thread-local RNG
-//!
-//! There is built-in support for a RNG associated with each thread stored
-//! in thread-local storage. This RNG can be accessed via `thread_rng`, or
-//! used implicitly via `random`. This RNG is normally randomly seeded
-//! from an operating-system source of randomness, e.g. `/dev/urandom` on
-//! Unix systems, and will automatically reseed itself from this source
-//! after generating 32 KiB of random data.
-//!
-//! # Cryptographic security
-//!
-//! An application that requires an entropy source for cryptographic purposes
-//! must use `OsRng`, which reads randomness from the source that the operating
-//! system provides (e.g. `/dev/urandom` on Unixes or `CryptGenRandom()` on Windows).
-//! The other random number generators provided by this module are not suitable
-//! for such purposes.
-//!
-//! *Note*: many Unix systems provide `/dev/random` as well as `/dev/urandom`.
-//! This module uses `/dev/urandom` for the following reasons:
-//!
-//! -   On Linux, `/dev/random` may block if entropy pool is empty; `/dev/urandom` will not block.
-//!     This does not mean that `/dev/random` provides better output than
-//!     `/dev/urandom`; the kernel internally runs a cryptographically secure pseudorandom
-//!     number generator (CSPRNG) based on entropy pool for random number generation,
-//!     so the "quality" of `/dev/random` is not better than `/dev/urandom` in most cases.
-//!     However, this means that `/dev/urandom` can yield somewhat predictable randomness
-//!     if the entropy pool is very small, such as immediately after first booting.
-//!     Linux 3.17 added the `getrandom(2)` system call which solves the issue: it blocks if entropy
-//!     pool is not initialized yet, but it does not block once initialized.
-//!     `getrandom(2)` was based on `getentropy(2)`, an existing system call in OpenBSD.
-//!     `OsRng` tries to use `getrandom(2)` if available, and use `/dev/urandom` fallback if not.
-//!     If an application does not have `getrandom` and likely to be run soon after first booting,
-//!     or on a system with very few entropy sources, one should consider using `/dev/random` via
-//!     `ReaderRng`.
-//! -   On some systems (e.g. FreeBSD, OpenBSD and macOS) there is no difference
-//!     between the two sources. (Also note that, on some systems e.g. FreeBSD, both `/dev/random`
-//!     and `/dev/urandom` may block once if the CSPRNG has not seeded yet.)
-
-#![unstable(feature = "rand", issue = "27703")]
-
-use cell::RefCell;
-use fmt;
-use io;
-use mem;
-use rc::Rc;
-use sys;
-
-#[cfg(target_pointer_width = "32")]
-use core_rand::IsaacRng as IsaacWordRng;
-#[cfg(target_pointer_width = "64")]
-use core_rand::Isaac64Rng as IsaacWordRng;
-
-pub use core_rand::{Rand, Rng, SeedableRng};
-pub use core_rand::{XorShiftRng, IsaacRng, Isaac64Rng};
-pub use core_rand::reseeding;
-
-pub mod reader;
-
-/// The standard RNG. This is designed to be efficient on the current
-/// platform.
-#[derive(Copy, Clone)]
-pub struct StdRng {
-    rng: IsaacWordRng,
-}
-
-impl StdRng {
-    /// Create a randomly seeded instance of `StdRng`.
-    ///
-    /// This is a very expensive operation as it has to read
-    /// randomness from the operating system and use this in an
-    /// expensive seeding operation. If one is only generating a small
-    /// number of random numbers, or doesn't need the utmost speed for
-    /// generating each number, `thread_rng` and/or `random` may be more
-    /// appropriate.
-    ///
-    /// Reading the randomness from the OS may fail, and any error is
-    /// propagated via the `io::Result` return value.
-    pub fn new() -> io::Result<StdRng> {
-        OsRng::new().map(|mut r| StdRng { rng: r.gen() })
-    }
-}
-
-impl Rng for StdRng {
-    #[inline]
-    fn next_u32(&mut self) -> u32 {
-        self.rng.next_u32()
-    }
-
-    #[inline]
-    fn next_u64(&mut self) -> u64 {
-        self.rng.next_u64()
-    }
-}
-
-impl<'a> SeedableRng<&'a [usize]> for StdRng {
-    fn reseed(&mut self, seed: &'a [usize]) {
-        // the internal RNG can just be seeded from the above
-        // randomness.
-        self.rng.reseed(unsafe {mem::transmute(seed)})
-    }
-
-    fn from_seed(seed: &'a [usize]) -> StdRng {
-        StdRng { rng: SeedableRng::from_seed(unsafe {mem::transmute(seed)}) }
-    }
-}
-
-/// Controls how the thread-local RNG is reseeded.
-struct ThreadRngReseeder;
-
-impl reseeding::Reseeder<StdRng> for ThreadRngReseeder {
-    fn reseed(&mut self, rng: &mut StdRng) {
-        *rng = match StdRng::new() {
-            Ok(r) => r,
-            Err(e) => panic!("could not reseed thread_rng: {}", e)
-        }
-    }
-}
-const THREAD_RNG_RESEED_THRESHOLD: usize = 32_768;
-type ThreadRngInner = reseeding::ReseedingRng<StdRng, ThreadRngReseeder>;
-
-/// The thread-local RNG.
-#[derive(Clone)]
-pub struct ThreadRng {
-    rng: Rc<RefCell<ThreadRngInner>>,
-}
-
-impl fmt::Debug for ThreadRng {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.pad("ThreadRng { .. }")
-    }
-}
-
-/// Retrieve the lazily-initialized thread-local random number
-/// generator, seeded by the system. Intended to be used in method
-/// chaining style, e.g. `thread_rng().gen::<isize>()`.
-///
-/// The RNG provided will reseed itself from the operating system
-/// after generating a certain amount of randomness.
-///
-/// The internal RNG used is platform and architecture dependent, even
-/// if the operating system random number generator is rigged to give
-/// the same sequence always. If absolute consistency is required,
-/// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`.
-pub fn thread_rng() -> ThreadRng {
-    // used to make space in TLS for a random number generator
-    thread_local!(static THREAD_RNG_KEY: Rc<RefCell<ThreadRngInner>> = {
-        let r = match StdRng::new() {
-            Ok(r) => r,
-            Err(e) => panic!("could not initialize thread_rng: {}", e)
-        };
-        let rng = reseeding::ReseedingRng::new(r,
-                                               THREAD_RNG_RESEED_THRESHOLD,
-                                               ThreadRngReseeder);
-        Rc::new(RefCell::new(rng))
-    });
-
-    ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.clone()) }
-}
-
-impl Rng for ThreadRng {
-    fn next_u32(&mut self) -> u32 {
-        self.rng.borrow_mut().next_u32()
-    }
-
-    fn next_u64(&mut self) -> u64 {
-        self.rng.borrow_mut().next_u64()
-    }
-
-    #[inline]
-    fn fill_bytes(&mut self, bytes: &mut [u8]) {
-        self.rng.borrow_mut().fill_bytes(bytes)
-    }
-}
-
-/// A random number generator that retrieves randomness straight from
-/// the operating system. Platform sources:
-///
-/// - Unix-like systems (Linux, Android, macOS): read directly from
-///   `/dev/urandom`, or from `getrandom(2)` system call if available.
-/// - Windows: calls `CryptGenRandom`, using the default cryptographic
-///   service provider with the `PROV_RSA_FULL` type.
-/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
-/// - OpenBSD: uses the `getentropy(2)` system call.
-///
-/// This does not block.
-pub struct OsRng(sys::rand::OsRng);
-
-impl OsRng {
-    /// Create a new `OsRng`.
-    pub fn new() -> io::Result<OsRng> {
-        sys::rand::OsRng::new().map(OsRng)
-    }
-}
-
-impl Rng for OsRng {
-    #[inline]
-    fn next_u32(&mut self) -> u32 {
-        self.0.next_u32()
-    }
-
-    #[inline]
-    fn next_u64(&mut self) -> u64 {
-        self.0.next_u64()
-    }
-
-    #[inline]
-    fn fill_bytes(&mut self, bytes: &mut [u8]) {
-        self.0.fill_bytes(bytes)
-    }
-}
-
-
-#[cfg(test)]
-mod tests {
-    use sync::mpsc::channel;
-    use rand::Rng;
-    use super::OsRng;
-    use thread;
-
-    #[test]
-    fn test_os_rng() {
-        let mut r = OsRng::new().unwrap();
-
-        r.next_u32();
-        r.next_u64();
-
-        let mut v = [0; 1000];
-        r.fill_bytes(&mut v);
-    }
-
-    #[test]
-    #[cfg_attr(target_os = "emscripten", ignore)]
-    fn test_os_rng_tasks() {
-
-        let mut txs = vec![];
-        for _ in 0..20 {
-            let (tx, rx) = channel();
-            txs.push(tx);
-
-            thread::spawn(move|| {
-                // wait until all the threads are ready to go.
-                rx.recv().unwrap();
-
-                // deschedule to attempt to interleave things as much
-                // as possible (XXX: is this a good test?)
-                let mut r = OsRng::new().unwrap();
-                thread::yield_now();
-                let mut v = [0; 1000];
-
-                for _ in 0..100 {
-                    r.next_u32();
-                    thread::yield_now();
-                    r.next_u64();
-                    thread::yield_now();
-                    r.fill_bytes(&mut v);
-                    thread::yield_now();
-                }
-            });
-        }
-
-        // start all the threads
-        for tx in &txs {
-            tx.send(()).unwrap();
-        }
-    }
-}
diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs
index 06fd838ea06..40b24cedcdc 100644
--- a/src/libstd/rt.rs
+++ b/src/libstd/rt.rs
@@ -23,7 +23,6 @@
 #![doc(hidden)]
 
 
-
 // Reexport some of our utilities which are expected by other crates.
 pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count};
 
diff --git a/src/libstd/sync/mpsc/cache_aligned.rs b/src/libstd/sync/mpsc/cache_aligned.rs
new file mode 100644
index 00000000000..5af01262573
--- /dev/null
+++ b/src/libstd/sync/mpsc/cache_aligned.rs
@@ -0,0 +1,37 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use ops::{Deref, DerefMut};
+
+#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[repr(align(64))]
+pub(super) struct Aligner;
+
+#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub(super) struct CacheAligned<T>(pub T, pub Aligner);
+
+impl<T> Deref for CacheAligned<T> {
+     type Target = T;
+     fn deref(&self) -> &Self::Target {
+         &self.0
+     }
+}
+
+impl<T> DerefMut for CacheAligned<T> {
+     fn deref_mut(&mut self) -> &mut Self::Target {
+         &mut self.0
+     }
+}
+
+impl<T> CacheAligned<T> {
+    pub(super) fn new(t: T) -> Self {
+        CacheAligned(t, Aligner)
+    }
+}
diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs
index dcd4c8dfdf5..2dd3aebe610 100644
--- a/src/libstd/sync/mpsc/mod.rs
+++ b/src/libstd/sync/mpsc/mod.rs
@@ -297,6 +297,8 @@ mod sync;
 mod mpsc_queue;
 mod spsc_queue;
 
+mod cache_aligned;
+
 /// The receiving half of Rust's [`channel`][] (or [`sync_channel`]) type.
 /// This half can only be owned by one thread.
 ///
@@ -919,7 +921,7 @@ impl<T> Drop for Sender<T> {
 #[stable(feature = "mpsc_debug", since = "1.8.0")]
 impl<T> fmt::Debug for Sender<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "Sender {{ .. }}")
+        f.debug_struct("Sender").finish()
     }
 }
 
@@ -1049,7 +1051,7 @@ impl<T> Drop for SyncSender<T> {
 #[stable(feature = "mpsc_debug", since = "1.8.0")]
 impl<T> fmt::Debug for SyncSender<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "SyncSender {{ .. }}")
+        f.debug_struct("SyncSender").finish()
     }
 }
 
@@ -1295,11 +1297,72 @@ impl<T> Receiver<T> {
             Err(TryRecvError::Disconnected)
                 => Err(RecvTimeoutError::Disconnected),
             Err(TryRecvError::Empty)
-                => self.recv_max_until(Instant::now() + timeout)
+                => self.recv_deadline(Instant::now() + timeout)
         }
     }
 
-    fn recv_max_until(&self, deadline: Instant) -> Result<T, RecvTimeoutError> {
+    /// Attempts to wait for a value on this receiver, returning an error if the
+    /// corresponding channel has hung up, or if `deadline` is reached.
+    ///
+    /// This function will always block the current thread if there is no data
+    /// available and it's possible for more data to be sent. Once a message is
+    /// sent to the corresponding [`Sender`][] (or [`SyncSender`]), then this
+    /// receiver will wake up and return that message.
+    ///
+    /// If the corresponding [`Sender`] has disconnected, or it disconnects while
+    /// this call is blocking, this call will wake up and return [`Err`] to
+    /// indicate that no more messages can ever be received on this channel.
+    /// However, since channels are buffered, messages sent before the disconnect
+    /// will still be properly received.
+    ///
+    /// [`Sender`]: struct.Sender.html
+    /// [`SyncSender`]: struct.SyncSender.html
+    /// [`Err`]: ../../../std/result/enum.Result.html#variant.Err
+    ///
+    /// # Examples
+    ///
+    /// Successfully receiving value before reaching deadline:
+    ///
+    /// ```no_run
+    /// #![feature(deadline_api)]
+    /// use std::thread;
+    /// use std::time::{Duration, Instant};
+    /// use std::sync::mpsc;
+    ///
+    /// let (send, recv) = mpsc::channel();
+    ///
+    /// thread::spawn(move || {
+    ///     send.send('a').unwrap();
+    /// });
+    ///
+    /// assert_eq!(
+    ///     recv.recv_deadline(Instant::now() + Duration::from_millis(400)),
+    ///     Ok('a')
+    /// );
+    /// ```
+    ///
+    /// Receiving an error upon reaching deadline:
+    ///
+    /// ```no_run
+    /// #![feature(deadline_api)]
+    /// use std::thread;
+    /// use std::time::{Duration, Instant};
+    /// use std::sync::mpsc;
+    ///
+    /// let (send, recv) = mpsc::channel();
+    ///
+    /// thread::spawn(move || {
+    ///     thread::sleep(Duration::from_millis(800));
+    ///     send.send('a').unwrap();
+    /// });
+    ///
+    /// assert_eq!(
+    ///     recv.recv_deadline(Instant::now() + Duration::from_millis(400)),
+    ///     Err(mpsc::RecvTimeoutError::Timeout)
+    /// );
+    /// ```
+    #[unstable(feature = "deadline_api", issue = "46316")]
+    pub fn recv_deadline(&self, deadline: Instant) -> Result<T, RecvTimeoutError> {
         use self::RecvTimeoutError::*;
 
         loop {
@@ -1551,7 +1614,7 @@ impl<T> Drop for Receiver<T> {
 #[stable(feature = "mpsc_debug", since = "1.8.0")]
 impl<T> fmt::Debug for Receiver<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "Receiver {{ .. }}")
+        f.debug_struct("Receiver").finish()
     }
 }
 
@@ -1623,6 +1686,15 @@ impl<T: Send> error::Error for TrySendError<T> {
     }
 }
 
+#[stable(feature = "mpsc_error_conversions", since = "1.24.0")]
+impl<T> From<SendError<T>> for TrySendError<T> {
+    fn from(err: SendError<T>) -> TrySendError<T> {
+        match err {
+            SendError(t) => TrySendError::Disconnected(t),
+        }
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for RecvError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -1675,6 +1747,15 @@ impl error::Error for TryRecvError {
     }
 }
 
+#[stable(feature = "mpsc_error_conversions", since = "1.24.0")]
+impl From<RecvError> for TryRecvError {
+    fn from(err: RecvError) -> TryRecvError {
+        match err {
+            RecvError => TryRecvError::Disconnected,
+        }
+    }
+}
+
 #[stable(feature = "mpsc_recv_timeout_error", since = "1.15.0")]
 impl fmt::Display for RecvTimeoutError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -1707,6 +1788,15 @@ impl error::Error for RecvTimeoutError {
     }
 }
 
+#[stable(feature = "mpsc_error_conversions", since = "1.24.0")]
+impl From<RecvError> for RecvTimeoutError {
+    fn from(err: RecvError) -> RecvTimeoutError {
+        match err {
+            RecvError => RecvTimeoutError::Disconnected,
+        }
+    }
+}
+
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use env;
@@ -3009,22 +3099,4 @@ mod sync_tests {
             repro()
         }
     }
-
-    #[test]
-    fn fmt_debug_sender() {
-        let (tx, _) = channel::<i32>();
-        assert_eq!(format!("{:?}", tx), "Sender { .. }");
-    }
-
-    #[test]
-    fn fmt_debug_recv() {
-        let (_, rx) = channel::<i32>();
-        assert_eq!(format!("{:?}", rx), "Receiver { .. }");
-    }
-
-    #[test]
-    fn fmt_debug_sync_sender() {
-        let (tx, _) = sync_channel::<i32>(1);
-        assert_eq!(format!("{:?}", tx), "SyncSender { .. }");
-    }
 }
diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs
index e49f4cff024..a9f3cea243f 100644
--- a/src/libstd/sync/mpsc/select.rs
+++ b/src/libstd/sync/mpsc/select.rs
@@ -354,13 +354,13 @@ impl Iterator for Packets {
 
 impl fmt::Debug for Select {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "Select {{ .. }}")
+        f.debug_struct("Select").finish()
     }
 }
 
 impl<'rx, T:Send+'rx> fmt::Debug for Handle<'rx, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "Handle {{ .. }}")
+        f.debug_struct("Handle").finish()
     }
 }
 
@@ -774,18 +774,4 @@ mod tests {
             }
         }
     }
-
-    #[test]
-    fn fmt_debug_select() {
-        let sel = Select::new();
-        assert_eq!(format!("{:?}", sel), "Select { .. }");
-    }
-
-    #[test]
-    fn fmt_debug_handle() {
-        let (_, rx) = channel::<i32>();
-        let sel = Select::new();
-        let handle = sel.handle(&rx);
-        assert_eq!(format!("{:?}", handle), "Handle { .. }");
-    }
 }
diff --git a/src/libstd/sync/mpsc/spsc_queue.rs b/src/libstd/sync/mpsc/spsc_queue.rs
index 1148bc66fba..cc4be92276a 100644
--- a/src/libstd/sync/mpsc/spsc_queue.rs
+++ b/src/libstd/sync/mpsc/spsc_queue.rs
@@ -22,12 +22,15 @@ use core::cell::UnsafeCell;
 
 use sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
 
+use super::cache_aligned::CacheAligned;
+
 // Node within the linked list queue of messages to send
 struct Node<T> {
     // FIXME: this could be an uninitialized T if we're careful enough, and
     //      that would reduce memory usage (and be a bit faster).
     //      is it worth it?
     value: Option<T>,           // nullable for re-use of nodes
+    cached: bool,               // This node goes into the node cache
     next: AtomicPtr<Node<T>>,   // next node in the queue
 }
 
@@ -35,38 +38,55 @@ struct Node<T> {
 /// but it can be safely shared in an Arc if it is guaranteed that there
 /// is only one popper and one pusher touching the queue at any one point in
 /// time.
-pub struct Queue<T> {
+pub struct Queue<T, ProducerAddition=(), ConsumerAddition=()> {
     // consumer fields
+    consumer: CacheAligned<Consumer<T, ConsumerAddition>>,
+
+    // producer fields
+    producer: CacheAligned<Producer<T, ProducerAddition>>,
+}
+
+struct Consumer<T, Addition> {
     tail: UnsafeCell<*mut Node<T>>, // where to pop from
     tail_prev: AtomicPtr<Node<T>>, // where to pop from
+    cache_bound: usize, // maximum cache size
+    cached_nodes: AtomicUsize, // number of nodes marked as cachable
+    addition: Addition,
+}
 
-    // producer fields
+struct Producer<T, Addition> {
     head: UnsafeCell<*mut Node<T>>,      // where to push to
     first: UnsafeCell<*mut Node<T>>,     // where to get new nodes from
     tail_copy: UnsafeCell<*mut Node<T>>, // between first/tail
-
-    // Cache maintenance fields. Additions and subtractions are stored
-    // separately in order to allow them to use nonatomic addition/subtraction.
-    cache_bound: usize,
-    cache_additions: AtomicUsize,
-    cache_subtractions: AtomicUsize,
+    addition: Addition,
 }
 
-unsafe impl<T: Send> Send for Queue<T> { }
+unsafe impl<T: Send, P: Send + Sync, C: Send + Sync> Send for Queue<T, P, C> { }
 
-unsafe impl<T: Send> Sync for Queue<T> { }
+unsafe impl<T: Send, P: Send + Sync, C: Send + Sync> Sync for Queue<T, P, C> { }
 
 impl<T> Node<T> {
     fn new() -> *mut Node<T> {
         Box::into_raw(box Node {
             value: None,
+            cached: false,
             next: AtomicPtr::new(ptr::null_mut::<Node<T>>()),
         })
     }
 }
 
-impl<T> Queue<T> {
-    /// Creates a new queue.
+impl<T, ProducerAddition, ConsumerAddition> Queue<T, ProducerAddition, ConsumerAddition> {
+
+    /// Creates a new queue. With given additional elements in the producer and
+    /// consumer portions of the queue.
+    ///
+    /// Due to the performance implications of cache-contention,
+    /// we wish to keep fields used mainly by the producer on a separate cache
+    /// line than those used by the consumer.
+    /// Since cache lines are usually 64 bytes, it is unreasonably expensive to
+    /// allocate one for small fields, so we allow users to insert additional
+    /// fields into the cache lines already allocated by this for the producer
+    /// and consumer.
     ///
     /// This is unsafe as the type system doesn't enforce a single
     /// consumer-producer relationship. It also allows the consumer to `pop`
@@ -83,19 +103,28 @@ impl<T> Queue<T> {
     ///               cache (if desired). If the value is 0, then the cache has
     ///               no bound. Otherwise, the cache will never grow larger than
     ///               `bound` (although the queue itself could be much larger.
-    pub unsafe fn new(bound: usize) -> Queue<T> {
+    pub unsafe fn with_additions(
+        bound: usize,
+        producer_addition: ProducerAddition,
+        consumer_addition: ConsumerAddition,
+    ) -> Self {
         let n1 = Node::new();
         let n2 = Node::new();
         (*n1).next.store(n2, Ordering::Relaxed);
         Queue {
-            tail: UnsafeCell::new(n2),
-            tail_prev: AtomicPtr::new(n1),
-            head: UnsafeCell::new(n2),
-            first: UnsafeCell::new(n1),
-            tail_copy: UnsafeCell::new(n1),
-            cache_bound: bound,
-            cache_additions: AtomicUsize::new(0),
-            cache_subtractions: AtomicUsize::new(0),
+            consumer: CacheAligned::new(Consumer {
+                tail: UnsafeCell::new(n2),
+                tail_prev: AtomicPtr::new(n1),
+                cache_bound: bound,
+                cached_nodes: AtomicUsize::new(0),
+                addition: consumer_addition
+            }),
+            producer: CacheAligned::new(Producer {
+                head: UnsafeCell::new(n2),
+                first: UnsafeCell::new(n1),
+                tail_copy: UnsafeCell::new(n1),
+                addition: producer_addition
+            }),
         }
     }
 
@@ -109,35 +138,25 @@ impl<T> Queue<T> {
             assert!((*n).value.is_none());
             (*n).value = Some(t);
             (*n).next.store(ptr::null_mut(), Ordering::Relaxed);
-            (**self.head.get()).next.store(n, Ordering::Release);
-            *self.head.get() = n;
+            (**self.producer.head.get()).next.store(n, Ordering::Release);
+            *(&self.producer.head).get() = n;
         }
     }
 
     unsafe fn alloc(&self) -> *mut Node<T> {
         // First try to see if we can consume the 'first' node for our uses.
-        // We try to avoid as many atomic instructions as possible here, so
-        // the addition to cache_subtractions is not atomic (plus we're the
-        // only one subtracting from the cache).
-        if *self.first.get() != *self.tail_copy.get() {
-            if self.cache_bound > 0 {
-                let b = self.cache_subtractions.load(Ordering::Relaxed);
-                self.cache_subtractions.store(b + 1, Ordering::Relaxed);
-            }
-            let ret = *self.first.get();
-            *self.first.get() = (*ret).next.load(Ordering::Relaxed);
+        if *self.producer.first.get() != *self.producer.tail_copy.get() {
+            let ret = *self.producer.first.get();
+            *self.producer.0.first.get() = (*ret).next.load(Ordering::Relaxed);
             return ret;
         }
         // If the above fails, then update our copy of the tail and try
         // again.
-        *self.tail_copy.get() = self.tail_prev.load(Ordering::Acquire);
-        if *self.first.get() != *self.tail_copy.get() {
-            if self.cache_bound > 0 {
-                let b = self.cache_subtractions.load(Ordering::Relaxed);
-                self.cache_subtractions.store(b + 1, Ordering::Relaxed);
-            }
-            let ret = *self.first.get();
-            *self.first.get() = (*ret).next.load(Ordering::Relaxed);
+        *self.producer.0.tail_copy.get() =
+            self.consumer.tail_prev.load(Ordering::Acquire);
+        if *self.producer.first.get() != *self.producer.tail_copy.get() {
+            let ret = *self.producer.first.get();
+            *self.producer.0.first.get() = (*ret).next.load(Ordering::Relaxed);
             return ret;
         }
         // If all of that fails, then we have to allocate a new node
@@ -153,27 +172,27 @@ impl<T> Queue<T> {
             // sentinel from where we should start popping from. Hence, look at
             // tail's next field and see if we can use it. If we do a pop, then
             // the current tail node is a candidate for going into the cache.
-            let tail = *self.tail.get();
+            let tail = *self.consumer.tail.get();
             let next = (*tail).next.load(Ordering::Acquire);
             if next.is_null() { return None }
             assert!((*next).value.is_some());
             let ret = (*next).value.take();
 
-            *self.tail.get() = next;
-            if self.cache_bound == 0 {
-                self.tail_prev.store(tail, Ordering::Release);
+            *self.consumer.0.tail.get() = next;
+            if self.consumer.cache_bound == 0 {
+                self.consumer.tail_prev.store(tail, Ordering::Release);
             } else {
-                // FIXME: this is dubious with overflow.
-                let additions = self.cache_additions.load(Ordering::Relaxed);
-                let subtractions = self.cache_subtractions.load(Ordering::Relaxed);
-                let size = additions - subtractions;
-
-                if size < self.cache_bound {
-                    self.tail_prev.store(tail, Ordering::Release);
-                    self.cache_additions.store(additions + 1, Ordering::Relaxed);
+                let cached_nodes = self.consumer.cached_nodes.load(Ordering::Relaxed);
+                if cached_nodes < self.consumer.cache_bound && !(*tail).cached {
+                    self.consumer.cached_nodes.store(cached_nodes, Ordering::Relaxed);
+                    (*tail).cached = true;
+                }
+
+                if (*tail).cached {
+                    self.consumer.tail_prev.store(tail, Ordering::Release);
                 } else {
-                    (*self.tail_prev.load(Ordering::Relaxed))
-                          .next.store(next, Ordering::Relaxed);
+                    (*self.consumer.tail_prev.load(Ordering::Relaxed))
+                        .next.store(next, Ordering::Relaxed);
                     // We have successfully erased all references to 'tail', so
                     // now we can safely drop it.
                     let _: Box<Node<T>> = Box::from_raw(tail);
@@ -194,17 +213,25 @@ impl<T> Queue<T> {
         // This is essentially the same as above with all the popping bits
         // stripped out.
         unsafe {
-            let tail = *self.tail.get();
+            let tail = *self.consumer.tail.get();
             let next = (*tail).next.load(Ordering::Acquire);
             if next.is_null() { None } else { (*next).value.as_mut() }
         }
     }
+
+    pub fn producer_addition(&self) -> &ProducerAddition {
+        &self.producer.addition
+    }
+
+    pub fn consumer_addition(&self) -> &ConsumerAddition {
+        &self.consumer.addition
+    }
 }
 
-impl<T> Drop for Queue<T> {
+impl<T, ProducerAddition, ConsumerAddition> Drop for Queue<T, ProducerAddition, ConsumerAddition> {
     fn drop(&mut self) {
         unsafe {
-            let mut cur = *self.first.get();
+            let mut cur = *self.producer.first.get();
             while !cur.is_null() {
                 let next = (*cur).next.load(Ordering::Relaxed);
                 let _n: Box<Node<T>> = Box::from_raw(cur);
@@ -224,7 +251,7 @@ mod tests {
     #[test]
     fn smoke() {
         unsafe {
-            let queue = Queue::new(0);
+            let queue = Queue::with_additions(0, (), ());
             queue.push(1);
             queue.push(2);
             assert_eq!(queue.pop(), Some(1));
@@ -241,7 +268,7 @@ mod tests {
     #[test]
     fn peek() {
         unsafe {
-            let queue = Queue::new(0);
+            let queue = Queue::with_additions(0, (), ());
             queue.push(vec![1]);
 
             // Ensure the borrowchecker works
@@ -264,7 +291,7 @@ mod tests {
     #[test]
     fn drop_full() {
         unsafe {
-            let q: Queue<Box<_>> = Queue::new(0);
+            let q: Queue<Box<_>> = Queue::with_additions(0, (), ());
             q.push(box 1);
             q.push(box 2);
         }
@@ -273,7 +300,7 @@ mod tests {
     #[test]
     fn smoke_bound() {
         unsafe {
-            let q = Queue::new(0);
+            let q = Queue::with_additions(0, (), ());
             q.push(1);
             q.push(2);
             assert_eq!(q.pop(), Some(1));
@@ -295,7 +322,7 @@ mod tests {
         }
 
         unsafe fn stress_bound(bound: usize) {
-            let q = Arc::new(Queue::new(bound));
+            let q = Arc::new(Queue::with_additions(bound, (), ()));
 
             let (tx, rx) = channel();
             let q2 = q.clone();
diff --git a/src/libstd/sync/mpsc/stream.rs b/src/libstd/sync/mpsc/stream.rs
index 47cd8977fda..d1515eba68c 100644
--- a/src/libstd/sync/mpsc/stream.rs
+++ b/src/libstd/sync/mpsc/stream.rs
@@ -41,15 +41,22 @@ const MAX_STEALS: isize = 5;
 const MAX_STEALS: isize = 1 << 20;
 
 pub struct Packet<T> {
-    queue: spsc::Queue<Message<T>>, // internal queue for all message
+    // internal queue for all messages
+    queue: spsc::Queue<Message<T>, ProducerAddition, ConsumerAddition>,
+}
 
+struct ProducerAddition {
     cnt: AtomicIsize, // How many items are on this channel
-    steals: UnsafeCell<isize>, // How many times has a port received without blocking?
     to_wake: AtomicUsize, // SignalToken for the blocked thread to wake up
 
     port_dropped: AtomicBool, // flag if the channel has been destroyed.
 }
 
+struct ConsumerAddition {
+    steals: UnsafeCell<isize>,  // How many times has a port received without blocking?
+}
+
+
 pub enum Failure<T> {
     Empty,
     Disconnected,
@@ -78,13 +85,18 @@ enum Message<T> {
 impl<T> Packet<T> {
     pub fn new() -> Packet<T> {
         Packet {
-            queue: unsafe { spsc::Queue::new(128) },
-
-            cnt: AtomicIsize::new(0),
-            steals: UnsafeCell::new(0),
-            to_wake: AtomicUsize::new(0),
-
-            port_dropped: AtomicBool::new(false),
+            queue: unsafe { spsc::Queue::with_additions(
+                128,
+                ProducerAddition {
+                    cnt: AtomicIsize::new(0),
+                    to_wake: AtomicUsize::new(0),
+
+                    port_dropped: AtomicBool::new(false),
+                },
+                ConsumerAddition {
+                    steals: UnsafeCell::new(0),
+                }
+            )},
         }
     }
 
@@ -92,7 +104,7 @@ impl<T> Packet<T> {
         // If the other port has deterministically gone away, then definitely
         // must return the data back up the stack. Otherwise, the data is
         // considered as being sent.
-        if self.port_dropped.load(Ordering::SeqCst) { return Err(t) }
+        if self.queue.producer_addition().port_dropped.load(Ordering::SeqCst) { return Err(t) }
 
         match self.do_send(Data(t)) {
             UpSuccess | UpDisconnected => {},
@@ -104,14 +116,16 @@ impl<T> Packet<T> {
     pub fn upgrade(&self, up: Receiver<T>) -> UpgradeResult {
         // If the port has gone away, then there's no need to proceed any
         // further.
-        if self.port_dropped.load(Ordering::SeqCst) { return UpDisconnected }
+        if self.queue.producer_addition().port_dropped.load(Ordering::SeqCst) {
+            return UpDisconnected
+        }
 
         self.do_send(GoUp(up))
     }
 
     fn do_send(&self, t: Message<T>) -> UpgradeResult {
         self.queue.push(t);
-        match self.cnt.fetch_add(1, Ordering::SeqCst) {
+        match self.queue.producer_addition().cnt.fetch_add(1, Ordering::SeqCst) {
             // As described in the mod's doc comment, -1 == wakeup
             -1 => UpWoke(self.take_to_wake()),
             // As as described before, SPSC queues must be >= -2
@@ -125,7 +139,7 @@ impl<T> Packet<T> {
             // will never remove this data. We can only have at most one item to
             // drain (the port drains the rest).
             DISCONNECTED => {
-                self.cnt.store(DISCONNECTED, Ordering::SeqCst);
+                self.queue.producer_addition().cnt.store(DISCONNECTED, Ordering::SeqCst);
                 let first = self.queue.pop();
                 let second = self.queue.pop();
                 assert!(second.is_none());
@@ -144,8 +158,8 @@ impl<T> Packet<T> {
 
     // Consumes ownership of the 'to_wake' field.
     fn take_to_wake(&self) -> SignalToken {
-        let ptr = self.to_wake.load(Ordering::SeqCst);
-        self.to_wake.store(0, Ordering::SeqCst);
+        let ptr = self.queue.producer_addition().to_wake.load(Ordering::SeqCst);
+        self.queue.producer_addition().to_wake.store(0, Ordering::SeqCst);
         assert!(ptr != 0);
         unsafe { SignalToken::cast_from_usize(ptr) }
     }
@@ -154,14 +168,16 @@ impl<T> Packet<T> {
     // back if it shouldn't sleep. Note that this is the location where we take
     // steals into account.
     fn decrement(&self, token: SignalToken) -> Result<(), SignalToken> {
-        assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
+        assert_eq!(self.queue.producer_addition().to_wake.load(Ordering::SeqCst), 0);
         let ptr = unsafe { token.cast_to_usize() };
-        self.to_wake.store(ptr, Ordering::SeqCst);
+        self.queue.producer_addition().to_wake.store(ptr, Ordering::SeqCst);
 
-        let steals = unsafe { ptr::replace(self.steals.get(), 0) };
+        let steals = unsafe { ptr::replace(self.queue.consumer_addition().steals.get(), 0) };
 
-        match self.cnt.fetch_sub(1 + steals, Ordering::SeqCst) {
-            DISCONNECTED => { self.cnt.store(DISCONNECTED, Ordering::SeqCst); }
+        match self.queue.producer_addition().cnt.fetch_sub(1 + steals, Ordering::SeqCst) {
+            DISCONNECTED => {
+                self.queue.producer_addition().cnt.store(DISCONNECTED, Ordering::SeqCst);
+            }
             // If we factor in our steals and notice that the channel has no
             // data, we successfully sleep
             n => {
@@ -170,7 +186,7 @@ impl<T> Packet<T> {
             }
         }
 
-        self.to_wake.store(0, Ordering::SeqCst);
+        self.queue.producer_addition().to_wake.store(0, Ordering::SeqCst);
         Err(unsafe { SignalToken::cast_from_usize(ptr) })
     }
 
@@ -201,7 +217,7 @@ impl<T> Packet<T> {
             // "steal" factored into the channel count above).
             data @ Ok(..) |
             data @ Err(Upgraded(..)) => unsafe {
-                *self.steals.get() -= 1;
+                *self.queue.consumer_addition().steals.get() -= 1;
                 data
             },
 
@@ -223,20 +239,21 @@ impl<T> Packet<T> {
             // down as much as possible (without going negative), and then
             // adding back in whatever we couldn't factor into steals.
             Some(data) => unsafe {
-                if *self.steals.get() > MAX_STEALS {
-                    match self.cnt.swap(0, Ordering::SeqCst) {
+                if *self.queue.consumer_addition().steals.get() > MAX_STEALS {
+                    match self.queue.producer_addition().cnt.swap(0, Ordering::SeqCst) {
                         DISCONNECTED => {
-                            self.cnt.store(DISCONNECTED, Ordering::SeqCst);
+                            self.queue.producer_addition().cnt.store(
+                                DISCONNECTED, Ordering::SeqCst);
                         }
                         n => {
-                            let m = cmp::min(n, *self.steals.get());
-                            *self.steals.get() -= m;
+                            let m = cmp::min(n, *self.queue.consumer_addition().steals.get());
+                            *self.queue.consumer_addition().steals.get() -= m;
                             self.bump(n - m);
                         }
                     }
-                    assert!(*self.steals.get() >= 0);
+                    assert!(*self.queue.consumer_addition().steals.get() >= 0);
                 }
-                *self.steals.get() += 1;
+                *self.queue.consumer_addition().steals.get() += 1;
                 match data {
                     Data(t) => Ok(t),
                     GoUp(up) => Err(Upgraded(up)),
@@ -244,7 +261,7 @@ impl<T> Packet<T> {
             },
 
             None => {
-                match self.cnt.load(Ordering::SeqCst) {
+                match self.queue.producer_addition().cnt.load(Ordering::SeqCst) {
                     n if n != DISCONNECTED => Err(Empty),
 
                     // This is a little bit of a tricky case. We failed to pop
@@ -273,7 +290,7 @@ impl<T> Packet<T> {
     pub fn drop_chan(&self) {
         // Dropping a channel is pretty simple, we just flag it as disconnected
         // and then wakeup a blocker if there is one.
-        match self.cnt.swap(DISCONNECTED, Ordering::SeqCst) {
+        match self.queue.producer_addition().cnt.swap(DISCONNECTED, Ordering::SeqCst) {
             -1 => { self.take_to_wake().signal(); }
             DISCONNECTED => {}
             n => { assert!(n >= 0); }
@@ -300,7 +317,7 @@ impl<T> Packet<T> {
         // sends are gated on this flag, so we're immediately guaranteed that
         // there are a bounded number of active sends that we'll have to deal
         // with.
-        self.port_dropped.store(true, Ordering::SeqCst);
+        self.queue.producer_addition().port_dropped.store(true, Ordering::SeqCst);
 
         // Now that we're guaranteed to deal with a bounded number of senders,
         // we need to drain the queue. This draining process happens atomically
@@ -310,9 +327,9 @@ impl<T> Packet<T> {
         // continue to fail while active senders send data while we're dropping
         // data, but eventually we're guaranteed to break out of this loop
         // (because there is a bounded number of senders).
-        let mut steals = unsafe { *self.steals.get() };
+        let mut steals = unsafe { *self.queue.consumer_addition().steals.get() };
         while {
-            let cnt = self.cnt.compare_and_swap(
+            let cnt = self.queue.producer_addition().cnt.compare_and_swap(
                             steals, DISCONNECTED, Ordering::SeqCst);
             cnt != DISCONNECTED && cnt != steals
         } {
@@ -353,9 +370,9 @@ impl<T> Packet<T> {
 
     // increment the count on the channel (used for selection)
     fn bump(&self, amt: isize) -> isize {
-        match self.cnt.fetch_add(amt, Ordering::SeqCst) {
+        match self.queue.producer_addition().cnt.fetch_add(amt, Ordering::SeqCst) {
             DISCONNECTED => {
-                self.cnt.store(DISCONNECTED, Ordering::SeqCst);
+                self.queue.producer_addition().cnt.store(DISCONNECTED, Ordering::SeqCst);
                 DISCONNECTED
             }
             n => n
@@ -404,8 +421,8 @@ impl<T> Packet<T> {
         // this end. This is fine because we know it's a small bounded windows
         // of time until the data is actually sent.
         if was_upgrade {
-            assert_eq!(unsafe { *self.steals.get() }, 0);
-            assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
+            assert_eq!(unsafe { *self.queue.consumer_addition().steals.get() }, 0);
+            assert_eq!(self.queue.producer_addition().to_wake.load(Ordering::SeqCst), 0);
             return Ok(true)
         }
 
@@ -418,7 +435,7 @@ impl<T> Packet<T> {
         // If we were previously disconnected, then we know for sure that there
         // is no thread in to_wake, so just keep going
         let has_data = if prev == DISCONNECTED {
-            assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
+            assert_eq!(self.queue.producer_addition().to_wake.load(Ordering::SeqCst), 0);
             true // there is data, that data is that we're disconnected
         } else {
             let cur = prev + steals + 1;
@@ -441,13 +458,13 @@ impl<T> Packet<T> {
             if prev < 0 {
                 drop(self.take_to_wake());
             } else {
-                while self.to_wake.load(Ordering::SeqCst) != 0 {
+                while self.queue.producer_addition().to_wake.load(Ordering::SeqCst) != 0 {
                     thread::yield_now();
                 }
             }
             unsafe {
-                assert_eq!(*self.steals.get(), 0);
-                *self.steals.get() = steals;
+                assert_eq!(*self.queue.consumer_addition().steals.get(), 0);
+                *self.queue.consumer_addition().steals.get() = steals;
             }
 
             // if we were previously positive, then there's surely data to
@@ -481,7 +498,7 @@ impl<T> Drop for Packet<T> {
         // disconnection, but also a proper fence before the read of
         // `to_wake`, so this assert cannot be removed with also removing
         // the `to_wake` assert.
-        assert_eq!(self.cnt.load(Ordering::SeqCst), DISCONNECTED);
-        assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
+        assert_eq!(self.queue.producer_addition().cnt.load(Ordering::SeqCst), DISCONNECTED);
+        assert_eq!(self.queue.producer_addition().to_wake.load(Ordering::SeqCst), 0);
     }
 }
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index 62d8de18f4b..81f5594bc52 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -19,10 +19,10 @@ use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
 /// A mutual exclusion primitive useful for protecting shared data
 ///
 /// This mutex will block threads waiting for the lock to become available. The
-/// mutex can also be statically initialized or created via a `new`
+/// mutex can also be statically initialized or created via a [`new`]
 /// constructor. Each mutex has a type parameter which represents the data that
 /// it is protecting. The data can only be accessed through the RAII guards
-/// returned from `lock` and `try_lock`, which guarantees that the data is only
+/// returned from [`lock`] and [`try_lock`], which guarantees that the data is only
 /// ever accessed when the mutex is locked.
 ///
 /// # Poisoning
@@ -33,16 +33,24 @@ use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
 /// data by default as it is likely tainted (some invariant is not being
 /// upheld).
 ///
-/// For a mutex, this means that the `lock` and `try_lock` methods return a
-/// `Result` which indicates whether a mutex has been poisoned or not. Most
-/// usage of a mutex will simply `unwrap()` these results, propagating panics
+/// For a mutex, this means that the [`lock`] and [`try_lock`] methods return a
+/// [`Result`] which indicates whether a mutex has been poisoned or not. Most
+/// usage of a mutex will simply [`unwrap()`] these results, propagating panics
 /// among threads to ensure that a possibly invalid invariant is not witnessed.
 ///
 /// A poisoned mutex, however, does not prevent all access to the underlying
-/// data. The `PoisonError` type has an `into_inner` method which will return
+/// data. The [`PoisonError`] type has an [`into_inner`] method which will return
 /// the guard that would have otherwise been returned on a successful lock. This
 /// allows access to the data, despite the lock being poisoned.
 ///
+/// [`new`]: #method.new
+/// [`lock`]: #method.lock
+/// [`try_lock`]: #method.try_lock
+/// [`Result`]: ../../std/result/enum.Result.html
+/// [`unwrap()`]: ../../std/result/enum.Result.html#method.unwrap
+/// [`PoisonError`]: ../../std/sync/struct.PoisonError.html
+/// [`into_inner`]: ../../std/sync/struct.PoisonError.html#method.into_inner
+///
 /// # Examples
 ///
 /// ```
@@ -226,7 +234,7 @@ impl<T: ?Sized> Mutex<T> {
 
     /// Attempts to acquire this lock.
     ///
-    /// If the lock could not be acquired at this time, then `Err` is returned.
+    /// If the lock could not be acquired at this time, then [`Err`] is returned.
     /// Otherwise, an RAII guard is returned. The lock will be unlocked when the
     /// guard is dropped.
     ///
@@ -238,6 +246,8 @@ impl<T: ?Sized> Mutex<T> {
     /// this call will return failure if the mutex would otherwise be
     /// acquired.
     ///
+    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
+    ///
     /// # Examples
     ///
     /// ```
@@ -372,6 +382,17 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Mutex<T> {
     }
 }
 
+#[stable(feature = "mutex_from", since = "1.22.0")]
+impl<T> From<T> for Mutex<T> {
+    /// Creates a new mutex in an unlocked state ready for use.
+    /// This is equivalent to [`Mutex::new`].
+    ///
+    /// [`Mutex::new`]: #method.new
+    fn from(t: T) -> Self {
+        Mutex::new(t)
+    }
+}
+
 #[stable(feature = "mutex_default", since = "1.10.0")]
 impl<T: ?Sized + Default> Default for Mutex<T> {
     /// Creates a `Mutex<T>`, with the `Default` value for T.
@@ -384,11 +405,18 @@ impl<T: ?Sized + Default> Default for Mutex<T> {
 impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self.try_lock() {
-            Ok(guard) => write!(f, "Mutex {{ data: {:?} }}", &*guard),
+            Ok(guard) => f.debug_struct("Mutex").field("data", &&*guard).finish(),
             Err(TryLockError::Poisoned(err)) => {
-                write!(f, "Mutex {{ data: Poisoned({:?}) }}", &**err.get_ref())
+                f.debug_struct("Mutex").field("data", &&**err.get_ref()).finish()
             },
-            Err(TryLockError::WouldBlock) => write!(f, "Mutex {{ <locked> }}")
+            Err(TryLockError::WouldBlock) => {
+                struct LockedPlaceholder;
+                impl fmt::Debug for LockedPlaceholder {
+                    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("<locked>") }
+                }
+
+                f.debug_struct("Mutex").field("data", &LockedPlaceholder).finish()
+            }
         }
     }
 }
diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs
index 015106fc2e5..6fd8b6a5bba 100644
--- a/src/libstd/sync/once.rs
+++ b/src/libstd/sync/once.rs
@@ -103,8 +103,8 @@ unsafe impl Sync for Once {}
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl Send for Once {}
 
-/// State yielded to the [`call_once_force`] method which can be used to query
-/// whether the [`Once`] was previously poisoned or not.
+/// State yielded to [`call_once_force`]’s closure parameter. The state can be
+/// used to query the poison status of the [`Once`].
 ///
 /// [`call_once_force`]: struct.Once.html#method.call_once_force
 /// [`Once`]: struct.Once.html
@@ -156,7 +156,6 @@ struct Finish {
 impl Once {
     /// Creates a new `Once` value.
     #[stable(feature = "once_new", since = "1.2.0")]
-    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_once_new"))]
     pub const fn new() -> Once {
         Once {
             state: AtomicUsize::new(INCOMPLETE),
@@ -230,17 +229,50 @@ impl Once {
 
     /// Performs the same function as [`call_once`] except ignores poisoning.
     ///
+    /// Unlike [`call_once`], if this `Once` has been poisoned (i.e. a previous
+    /// call to `call_once` or `call_once_force` caused a panic), calling
+    /// `call_once_force` will still invoke the closure `f` and will _not_
+    /// result in an immediate panic. If `f` panics, the `Once` will remain
+    /// in a poison state. If `f` does _not_ panic, the `Once` will no
+    /// longer be in a poison state and all future calls to `call_once` or
+    /// `call_one_force` will no-op.
+    ///
+    /// The closure `f` is yielded a [`OnceState`] structure which can be used
+    /// to query the poison status of the `Once`.
+    ///
     /// [`call_once`]: struct.Once.html#method.call_once
+    /// [`OnceState`]: struct.OnceState.html
     ///
-    /// If this `Once` has been poisoned (some initialization panicked) then
-    /// this function will continue to attempt to call initialization functions
-    /// until one of them doesn't panic.
+    /// # Examples
     ///
-    /// The closure `f` is yielded a [`OnceState`] structure which can be used to query the
-    /// state of this `Once` (whether initialization has previously panicked or
-    /// not).
+    /// ```
+    /// #![feature(once_poison)]
     ///
-    /// [`OnceState`]: struct.OnceState.html
+    /// use std::sync::{Once, ONCE_INIT};
+    /// use std::thread;
+    ///
+    /// static INIT: Once = ONCE_INIT;
+    ///
+    /// // poison the once
+    /// let handle = thread::spawn(|| {
+    ///     INIT.call_once(|| panic!());
+    /// });
+    /// assert!(handle.join().is_err());
+    ///
+    /// // poisoning propagates
+    /// let handle = thread::spawn(|| {
+    ///     INIT.call_once(|| {});
+    /// });
+    /// assert!(handle.join().is_err());
+    ///
+    /// // call_once_force will still run and reset the poisoned state
+    /// INIT.call_once_force(|state| {
+    ///     assert!(state.poisoned());
+    /// });
+    ///
+    /// // once any success happens, we stop propagating the poison
+    /// INIT.call_once(|| {});
+    /// ```
     #[unstable(feature = "once_poison", issue = "33577")]
     pub fn call_once_force<F>(&'static self, f: F) where F: FnOnce(&OnceState) {
         // same as above, just with a different parameter to `call_inner`.
@@ -386,12 +418,47 @@ impl Drop for Finish {
 }
 
 impl OnceState {
-    /// Returns whether the associated [`Once`] has been poisoned.
-    ///
-    /// Once an initialization routine for a [`Once`] has panicked it will forever
-    /// indicate to future forced initialization routines that it is poisoned.
+    /// Returns whether the associated [`Once`] was poisoned prior to the
+    /// invocation of the closure passed to [`call_once_force`].
     ///
+    /// [`call_once_force`]: struct.Once.html#method.call_once_force
     /// [`Once`]: struct.Once.html
+    ///
+    /// # Examples
+    ///
+    /// A poisoned `Once`:
+    ///
+    /// ```
+    /// #![feature(once_poison)]
+    ///
+    /// use std::sync::{Once, ONCE_INIT};
+    /// use std::thread;
+    ///
+    /// static INIT: Once = ONCE_INIT;
+    ///
+    /// // poison the once
+    /// let handle = thread::spawn(|| {
+    ///     INIT.call_once(|| panic!());
+    /// });
+    /// assert!(handle.join().is_err());
+    ///
+    /// INIT.call_once_force(|state| {
+    ///     assert!(state.poisoned());
+    /// });
+    /// ```
+    ///
+    /// An unpoisoned `Once`:
+    ///
+    /// ```
+    /// #![feature(once_poison)]
+    ///
+    /// use std::sync::{Once, ONCE_INIT};
+    ///
+    /// static INIT: Once = ONCE_INIT;
+    ///
+    /// INIT.call_once_force(|state| {
+    ///     assert!(!state.poisoned());
+    /// });
     #[unstable(feature = "once_poison", issue = "33577")]
     pub fn poisoned(&self) -> bool {
         self.poisoned
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
index 4757faabfb8..fd6cff6b69c 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -10,7 +10,6 @@
 
 use cell::UnsafeCell;
 use fmt;
-use marker;
 use mem;
 use ops::{Deref, DerefMut};
 use ptr;
@@ -82,7 +81,7 @@ pub struct RwLock<T: ?Sized> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<T: ?Sized + Send + Sync> Send for RwLock<T> {}
+unsafe impl<T: ?Sized + Send> Send for RwLock<T> {}
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {}
 
@@ -102,7 +101,10 @@ pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: ?Sized> !marker::Send for RwLockReadGuard<'a, T> {}
+impl<'a, T: ?Sized> !Send for RwLockReadGuard<'a, T> {}
+
+#[stable(feature = "rwlock_guard_sync", since = "1.23.0")]
+unsafe impl<'a, T: ?Sized + Sync> Sync for RwLockReadGuard<'a, T> {}
 
 /// RAII structure used to release the exclusive write access of a lock when
 /// dropped.
@@ -121,7 +123,10 @@ pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: ?Sized> !marker::Send for RwLockWriteGuard<'a, T> {}
+impl<'a, T: ?Sized> !Send for RwLockWriteGuard<'a, T> {}
+
+#[stable(feature = "rwlock_guard_sync", since = "1.23.0")]
+unsafe impl<'a, T: ?Sized + Sync> Sync for RwLockWriteGuard<'a, T> {}
 
 impl<T> RwLock<T> {
     /// Creates a new instance of an `RwLock<T>` which is unlocked.
@@ -428,11 +433,18 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for RwLock<T> {
 impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLock<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self.try_read() {
-            Ok(guard) => write!(f, "RwLock {{ data: {:?} }}", &*guard),
+            Ok(guard) => f.debug_struct("RwLock").field("data", &&*guard).finish(),
             Err(TryLockError::Poisoned(err)) => {
-                write!(f, "RwLock {{ data: Poisoned({:?}) }}", &**err.get_ref())
+                f.debug_struct("RwLock").field("data", &&**err.get_ref()).finish()
             },
-            Err(TryLockError::WouldBlock) => write!(f, "RwLock {{ <locked> }}")
+            Err(TryLockError::WouldBlock) => {
+                struct LockedPlaceholder;
+                impl fmt::Debug for LockedPlaceholder {
+                    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("<locked>") }
+                }
+
+                f.debug_struct("RwLock").field("data", &LockedPlaceholder).finish()
+            }
         }
     }
 }
@@ -445,6 +457,17 @@ impl<T: Default> Default for RwLock<T> {
     }
 }
 
+#[stable(feature = "rw_lock_from", since = "1.22.0")]
+impl<T> From<T> for RwLock<T> {
+    /// Creates a new instance of an `RwLock<T>` which is unlocked.
+    /// This is equivalent to [`RwLock::new`].
+    ///
+    /// [`RwLock::new`]: #method.new
+    fn from(t: T) -> Self {
+        RwLock::new(t)
+    }
+}
+
 impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
     unsafe fn new(lock: &'rwlock RwLock<T>)
                   -> LockResult<RwLockReadGuard<'rwlock, T>> {
@@ -542,8 +565,6 @@ impl<'a, T: ?Sized> Drop for RwLockWriteGuard<'a, T> {
 
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
-    #![allow(deprecated)] // rand
-
     use rand::{self, Rng};
     use sync::mpsc::channel;
     use thread;
@@ -564,7 +585,7 @@ mod tests {
 
     #[test]
     fn frob() {
-        const N: usize = 10;
+        const N: u32 = 10;
         const M: usize = 1000;
 
         let r = Arc::new(RwLock::new(()));
diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs
index d91c2073a23..be8cb88416b 100644
--- a/src/libstd/sys/mod.rs
+++ b/src/libstd/sys/mod.rs
@@ -32,46 +32,66 @@
 
 #![allow(missing_debug_implementations)]
 
-pub use self::imp::*;
-
-#[cfg(unix)]
-#[path = "unix/mod.rs"]
-mod imp;
-
-#[cfg(windows)]
-#[path = "windows/mod.rs"]
-mod imp;
-
-#[cfg(target_os = "redox")]
-#[path = "redox/mod.rs"]
-mod imp;
-
-
-// Import essential modules from both platforms when documenting.
-
-#[cfg(all(dox, not(unix)))]
-use os::linux as platform;
-
-#[cfg(all(dox, not(any(unix, target_os = "redox"))))]
-#[path = "unix/ext/mod.rs"]
-pub mod unix_ext;
-
-#[cfg(all(dox, any(unix, target_os = "redox")))]
-pub use self::ext as unix_ext;
-
-
-#[cfg(all(dox, not(windows)))]
-#[macro_use]
-#[path = "windows/compat.rs"]
-mod compat;
-
-#[cfg(all(dox, not(windows)))]
-#[path = "windows/c.rs"]
-mod c;
-
-#[cfg(all(dox, not(windows)))]
-#[path = "windows/ext/mod.rs"]
-pub mod windows_ext;
-
-#[cfg(all(dox, windows))]
-pub use self::ext as windows_ext;
+cfg_if! {
+    if #[cfg(unix)] {
+        mod unix;
+        pub use self::unix::*;
+    } else if #[cfg(windows)] {
+        mod windows;
+        pub use self::windows::*;
+    } else if #[cfg(target_os = "redox")] {
+        mod redox;
+        pub use self::redox::*;
+    } else if #[cfg(target_arch = "wasm32")] {
+        mod wasm;
+        pub use self::wasm::*;
+    } else {
+        compile_error!("libstd doesn't compile for this platform yet");
+    }
+}
+
+// Import essential modules from both platforms when documenting. These are
+// then later used in the `std::os` module when documenting, for example,
+// Windows when we're compiling for Linux.
+
+#[cfg(dox)]
+cfg_if! {
+    if #[cfg(any(unix, target_os = "redox"))] {
+        // On unix we'll document what's already available
+        pub use self::ext as unix_ext;
+    } else if #[cfg(target_arch = "wasm32")] {
+        // On wasm right now the module below doesn't compile (missing things
+        // in `libc` which is empty) so just omit everything with an empty module
+        #[unstable(issue = "0", feature = "std_internals")]
+        pub mod unix_ext {}
+    } else {
+        // On other platforms like Windows document the bare bones of unix
+        use os::linux as platform;
+        #[path = "unix/ext/mod.rs"]
+        pub mod unix_ext;
+    }
+}
+
+#[cfg(dox)]
+cfg_if! {
+    if #[cfg(windows)] {
+        // On windows we'll just be documenting what's already available
+        pub use self::ext as windows_ext;
+    } else if #[cfg(target_arch = "wasm32")] {
+        // On wasm right now the shim below doesn't compile, so just omit it
+        #[unstable(issue = "0", feature = "std_internals")]
+        pub mod windows_ext {}
+    } else {
+        // On all other platforms (aka linux/osx/etc) then pull in a "minimal"
+        // amount of windows goop which ends up compiling
+        #[macro_use]
+        #[path = "windows/compat.rs"]
+        mod compat;
+
+        #[path = "windows/c.rs"]
+        mod c;
+
+        #[path = "windows/ext/mod.rs"]
+        pub mod windows_ext;
+    }
+}
diff --git a/src/libstd/sys/redox/backtrace/tracing.rs b/src/libstd/sys/redox/backtrace/tracing.rs
index cfeabaddda9..0a174b3c3f5 100644
--- a/src/libstd/sys/redox/backtrace/tracing.rs
+++ b/src/libstd/sys/redox/backtrace/tracing.rs
@@ -96,8 +96,8 @@ extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
 
     if cx.idx < cx.frames.len() {
         cx.frames[cx.idx] = Frame {
-            symbol_addr: symaddr,
-            exact_position: ip,
+            symbol_addr: symaddr as *mut u8,
+            exact_position: ip as *mut u8,
         };
         cx.idx += 1;
     }
diff --git a/src/libstd/sys/redox/cmath.rs b/src/libstd/sys/redox/cmath.rs
new file mode 100644
index 00000000000..2bc96651b0c
--- /dev/null
+++ b/src/libstd/sys/redox/cmath.rs
@@ -0,0 +1,43 @@
+// Copyright 2017 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(not(test))]
+
+use libc::{c_float, c_double};
+
+#[link_name = "m"]
+extern {
+    pub fn acos(n: c_double) -> c_double;
+    pub fn acosf(n: c_float) -> c_float;
+    pub fn asin(n: c_double) -> c_double;
+    pub fn asinf(n: c_float) -> c_float;
+    pub fn atan(n: c_double) -> c_double;
+    pub fn atan2(a: c_double, b: c_double) -> c_double;
+    pub fn atan2f(a: c_float, b: c_float) -> c_float;
+    pub fn atanf(n: c_float) -> c_float;
+    pub fn cbrt(n: c_double) -> c_double;
+    pub fn cbrtf(n: c_float) -> c_float;
+    pub fn cosh(n: c_double) -> c_double;
+    pub fn coshf(n: c_float) -> c_float;
+    pub fn expm1(n: c_double) -> c_double;
+    pub fn expm1f(n: c_float) -> c_float;
+    pub fn fdim(a: c_double, b: c_double) -> c_double;
+    pub fn fdimf(a: c_float, b: c_float) -> c_float;
+    pub fn hypot(x: c_double, y: c_double) -> c_double;
+    pub fn hypotf(x: c_float, y: c_float) -> c_float;
+    pub fn log1p(n: c_double) -> c_double;
+    pub fn log1pf(n: c_float) -> c_float;
+    pub fn sinh(n: c_double) -> c_double;
+    pub fn sinhf(n: c_float) -> c_float;
+    pub fn tan(n: c_double) -> c_double;
+    pub fn tanf(n: c_float) -> c_float;
+    pub fn tanh(n: c_double) -> c_double;
+    pub fn tanhf(n: c_float) -> c_float;
+}
diff --git a/src/libstd/sys/redox/condvar.rs b/src/libstd/sys/redox/condvar.rs
index fe4a89c6f3e..2a611ed7dab 100644
--- a/src/libstd/sys/redox/condvar.rs
+++ b/src/libstd/sys/redox/condvar.rs
@@ -9,12 +9,12 @@
 // except according to those terms.
 
 use cell::UnsafeCell;
-use intrinsics::{atomic_cxchg, atomic_xadd, atomic_xchg};
+use intrinsics::{atomic_cxchg, atomic_load, atomic_xadd, atomic_xchg};
 use ptr;
 use time::Duration;
 
 use sys::mutex::{mutex_unlock, Mutex};
-use sys::syscall::{futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE};
+use sys::syscall::{futex, TimeSpec, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE};
 
 pub struct Condvar {
     lock: UnsafeCell<*mut i32>,
@@ -63,33 +63,50 @@ impl Condvar {
     }
 
     #[inline]
-    pub fn wait(&self, mutex: &Mutex) {
-        unsafe {
-            let lock = self.lock.get();
-            let seq = self.seq.get();
-
-            if *lock != mutex.lock.get() {
-                if *lock != ptr::null_mut() {
-                    panic!("Condvar used with more than one Mutex");
-                }
+    unsafe fn wait_inner(&self, mutex: &Mutex, timeout_ptr: *const TimeSpec) -> bool {
+        let lock = self.lock.get();
+        let seq = self.seq.get();
 
-                atomic_cxchg(lock as *mut usize, 0, mutex.lock.get() as usize);
+        if *lock != mutex.lock.get() {
+            if *lock != ptr::null_mut() {
+                panic!("Condvar used with more than one Mutex");
             }
 
-            mutex_unlock(*lock);
+            atomic_cxchg(lock as *mut usize, 0, mutex.lock.get() as usize);
+        }
 
-            let _ = futex(seq, FUTEX_WAIT, *seq, 0, ptr::null_mut());
+        mutex_unlock(*lock);
 
-            while atomic_xchg(*lock, 2) != 0 {
-                let _ = futex(*lock, FUTEX_WAIT, 2, 0, ptr::null_mut());
-            }
+        let seq_before = atomic_load(seq);
+
+        let _ = futex(seq, FUTEX_WAIT, seq_before, timeout_ptr as usize, ptr::null_mut());
+
+        let seq_after = atomic_load(seq);
+
+        while atomic_xchg(*lock, 2) != 0 {
+            let _ = futex(*lock, FUTEX_WAIT, 2, 0, ptr::null_mut());
+        }
+
+        seq_before != seq_after
+    }
+
+    #[inline]
+    pub fn wait(&self, mutex: &Mutex) {
+        unsafe {
+            assert!(self.wait_inner(mutex, ptr::null()));
         }
     }
 
     #[inline]
-    pub fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
-        ::sys_common::util::dumb_print(format_args!("condvar wait_timeout\n"));
-        unimplemented!();
+    pub fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
+        unsafe {
+            let timeout = TimeSpec {
+                tv_sec: dur.as_secs() as i64,
+                tv_nsec: dur.subsec_nanos() as i32
+            };
+
+            self.wait_inner(mutex, &timeout as *const TimeSpec)
+        }
     }
 
     #[inline]
diff --git a/src/libstd/sys/redox/fast_thread_local.rs b/src/libstd/sys/redox/fast_thread_local.rs
index 9f0eee024d5..6a007e98827 100644
--- a/src/libstd/sys/redox/fast_thread_local.rs
+++ b/src/libstd/sys/redox/fast_thread_local.rs
@@ -81,7 +81,7 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
     unsafe extern fn run_dtors(mut ptr: *mut u8) {
         while !ptr.is_null() {
             let list: Box<List> = Box::from_raw(ptr as *mut List);
-            for &(ptr, dtor) in list.iter() {
+            for (ptr, dtor) in list.into_iter() {
                 dtor(ptr);
             }
             ptr = DTORS.get();
diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs
index 918893097f8..3483477d40c 100644
--- a/src/libstd/sys/redox/fs.rs
+++ b/src/libstd/sys/redox/fs.rs
@@ -437,8 +437,7 @@ pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
 }
 
 pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
-    ::sys_common::util::dumb_print(format_args!("Link\n"));
-    unimplemented!();
+    Err(Error::from_raw_os_error(syscall::ENOSYS))
 }
 
 pub fn stat(p: &Path) -> io::Result<FileAttr> {
diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs
index 7c728ebb1af..4352b72c307 100644
--- a/src/libstd/sys/redox/mod.rs
+++ b/src/libstd/sys/redox/mod.rs
@@ -12,9 +12,13 @@
 
 use io::{self, ErrorKind};
 
+pub use libc::strlen;
+pub use self::rand::hashmap_random_keys;
+
 pub mod args;
 #[cfg(feature = "backtrace")]
 pub mod backtrace;
+pub mod cmath;
 pub mod condvar;
 pub mod env;
 pub mod ext;
diff --git a/src/libstd/sys/redox/os.rs b/src/libstd/sys/redox/os.rs
index efddd5f0294..480765b77a0 100644
--- a/src/libstd/sys/redox/os.rs
+++ b/src/libstd/sys/redox/os.rs
@@ -209,3 +209,11 @@ pub fn exit(code: i32) -> ! {
     let _ = syscall::exit(code as usize);
     unreachable!();
 }
+
+pub fn getpid() -> u32 {
+    syscall::getpid().unwrap() as u32
+}
+
+pub fn getppid() -> u32 {
+    syscall::getppid().unwrap() as u32
+}
diff --git a/src/libstd/sys/redox/os_str.rs b/src/libstd/sys/redox/os_str.rs
index c54286353a9..5c40d42fa0a 100644
--- a/src/libstd/sys/redox/os_str.rs
+++ b/src/libstd/sys/redox/os_str.rs
@@ -15,6 +15,8 @@ use borrow::Cow;
 use fmt;
 use str;
 use mem;
+use rc::Rc;
+use sync::Arc;
 use sys_common::{AsInner, IntoInner};
 use std_unicode::lossy::Utf8Lossy;
 
@@ -123,6 +125,16 @@ impl Buf {
         let inner: Box<[u8]> = unsafe { mem::transmute(boxed) };
         Buf { inner: inner.into_vec() }
     }
+
+    #[inline]
+    pub fn into_arc(&self) -> Arc<Slice> {
+        self.as_slice().into_arc()
+    }
+
+    #[inline]
+    pub fn into_rc(&self) -> Rc<Slice> {
+        self.as_slice().into_rc()
+    }
 }
 
 impl Slice {
@@ -156,4 +168,16 @@ impl Slice {
         let boxed: Box<[u8]> = Default::default();
         unsafe { mem::transmute(boxed) }
     }
+
+    #[inline]
+    pub fn into_arc(&self) -> Arc<Slice> {
+        let arc: Arc<[u8]> = Arc::from(&self.inner);
+        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) }
+    }
+
+    #[inline]
+    pub fn into_rc(&self) -> Rc<Slice> {
+        let rc: Rc<[u8]> = Rc::from(&self.inner);
+        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
+    }
 }
diff --git a/src/libstd/sys/redox/rand.rs b/src/libstd/sys/redox/rand.rs
index eb28eca38bc..3b378f53429 100644
--- a/src/libstd/sys/redox/rand.rs
+++ b/src/libstd/sys/redox/rand.rs
@@ -8,50 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use io;
-use rand::Rng;
-
-// FIXME: Use rand:
-pub struct OsRng {
-    state: [u64; 2]
-}
-
-impl OsRng {
-    /// Create a new `OsRng`.
-    pub fn new() -> io::Result<OsRng> {
-        Ok(OsRng {
-            state: [0xBADF00D1, 0xDEADBEEF]
-        })
-    }
-}
-
-impl Rng for OsRng {
-    fn next_u32(&mut self) -> u32 {
-        self.next_u64() as u32
-    }
-    fn next_u64(&mut self) -> u64 {
-        // Store the first and second part.
-        let mut x = self.state[0];
-        let y = self.state[1];
-
-        // Put the second part into the first slot.
-        self.state[0] = y;
-        // Twist the first slot.
-        x ^= x << 23;
-        // Update the second slot.
-        self.state[1] = x ^ y ^ (x >> 17) ^ (y >> 26);
-
-        // Generate the final integer.
-        self.state[1].wrapping_add(y)
-
-    }
-    fn fill_bytes(&mut self, buf: &mut [u8]) {
-        for chunk in buf.chunks_mut(8) {
-            let mut rand: u64 = self.next_u64();
-            for b in chunk.iter_mut() {
-                *b = rand as u8;
-                rand = rand >> 8;
-            }
-        }
-    }
+pub fn hashmap_random_keys() -> (u64, u64) {
+    (0, 0)
 }
diff --git a/src/libstd/sys/redox/stdio.rs b/src/libstd/sys/redox/stdio.rs
index c839531cc26..3abb094ac34 100644
--- a/src/libstd/sys/redox/stdio.rs
+++ b/src/libstd/sys/redox/stdio.rs
@@ -70,5 +70,8 @@ impl io::Write for Stderr {
     }
 }
 
-pub const EBADF_ERR: i32 = ::sys::syscall::EBADF;
+pub fn is_ebadf(err: &io::Error) -> bool {
+    err.raw_os_error() == Some(::sys::syscall::EBADF as i32)
+}
+
 pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
diff --git a/src/libstd/sys/unix/backtrace/printing/dladdr.rs b/src/libstd/sys/unix/backtrace/printing/dladdr.rs
index 21f0b3724c1..bc56fd6594e 100644
--- a/src/libstd/sys/unix/backtrace/printing/dladdr.rs
+++ b/src/libstd/sys/unix/backtrace/printing/dladdr.rs
@@ -22,7 +22,7 @@ pub fn resolve_symname<F>(frame: Frame,
 {
     unsafe {
         let mut info: Dl_info = intrinsics::init();
-        let symname = if dladdr(frame.exact_position, &mut info) == 0 ||
+        let symname = if dladdr(frame.exact_position as *mut _, &mut info) == 0 ||
                          info.dli_sname.is_null() {
             None
         } else {
@@ -41,6 +41,5 @@ struct Dl_info {
 }
 
 extern {
-    fn dladdr(addr: *const libc::c_void,
-              info: *mut Dl_info) -> libc::c_int;
+    fn dladdr(addr: *const libc::c_void, info: *mut Dl_info) -> libc::c_int;
 }
diff --git a/src/libstd/sys/unix/backtrace/printing/mod.rs b/src/libstd/sys/unix/backtrace/printing/mod.rs
index 8bd2d9eccd8..caa60712b1d 100644
--- a/src/libstd/sys/unix/backtrace/printing/mod.rs
+++ b/src/libstd/sys/unix/backtrace/printing/mod.rs
@@ -20,7 +20,7 @@ pub use self::dladdr::resolve_symname;
 #[cfg(target_os = "emscripten")]
 pub fn foreach_symbol_fileline<F>(_: Frame, _: F, _: &BacktraceContext) -> io::Result<bool>
 where
-    F: FnMut(&[u8], ::libc::c_int) -> io::Result<()>
+    F: FnMut(&[u8], u32) -> io::Result<()>
 {
     Ok(false)
 }
diff --git a/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs b/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs
index ecd32aa9462..400d39cd4bd 100644
--- a/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs
+++ b/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs
@@ -36,8 +36,8 @@ pub fn unwind_backtrace(frames: &mut [Frame])
     } as usize;
     for (from, to) in raw_frames.iter().zip(frames.iter_mut()).take(nb_frames) {
         *to = Frame {
-            exact_position: *from,
-            symbol_addr: *from,
+            exact_position: *from as *mut u8,
+            symbol_addr: *from as *mut u8,
         };
     }
     Ok((nb_frames as usize, BacktraceContext))
diff --git a/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs b/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs
index e3ffbe88acd..000c08d2e0d 100644
--- a/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs
+++ b/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs
@@ -96,8 +96,8 @@ extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
 
     if cx.idx < cx.frames.len() {
         cx.frames[cx.idx] = Frame {
-            symbol_addr: symaddr,
-            exact_position: ip,
+            symbol_addr: symaddr as *mut u8,
+            exact_position: ip as *mut u8,
         };
         cx.idx += 1;
     }
diff --git a/src/libstd/sys/unix/cmath.rs b/src/libstd/sys/unix/cmath.rs
new file mode 100644
index 00000000000..2bc96651b0c
--- /dev/null
+++ b/src/libstd/sys/unix/cmath.rs
@@ -0,0 +1,43 @@
+// Copyright 2017 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(not(test))]
+
+use libc::{c_float, c_double};
+
+#[link_name = "m"]
+extern {
+    pub fn acos(n: c_double) -> c_double;
+    pub fn acosf(n: c_float) -> c_float;
+    pub fn asin(n: c_double) -> c_double;
+    pub fn asinf(n: c_float) -> c_float;
+    pub fn atan(n: c_double) -> c_double;
+    pub fn atan2(a: c_double, b: c_double) -> c_double;
+    pub fn atan2f(a: c_float, b: c_float) -> c_float;
+    pub fn atanf(n: c_float) -> c_float;
+    pub fn cbrt(n: c_double) -> c_double;
+    pub fn cbrtf(n: c_float) -> c_float;
+    pub fn cosh(n: c_double) -> c_double;
+    pub fn coshf(n: c_float) -> c_float;
+    pub fn expm1(n: c_double) -> c_double;
+    pub fn expm1f(n: c_float) -> c_float;
+    pub fn fdim(a: c_double, b: c_double) -> c_double;
+    pub fn fdimf(a: c_float, b: c_float) -> c_float;
+    pub fn hypot(x: c_double, y: c_double) -> c_double;
+    pub fn hypotf(x: c_float, y: c_float) -> c_float;
+    pub fn log1p(n: c_double) -> c_double;
+    pub fn log1pf(n: c_float) -> c_float;
+    pub fn sinh(n: c_double) -> c_double;
+    pub fn sinhf(n: c_float) -> c_float;
+    pub fn tan(n: c_double) -> c_double;
+    pub fn tanf(n: c_float) -> c_float;
+    pub fn tanh(n: c_double) -> c_double;
+    pub fn tanhf(n: c_float) -> c_float;
+}
diff --git a/src/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs
index 89a44b97657..4f878d8ad1f 100644
--- a/src/libstd/sys/unix/condvar.rs
+++ b/src/libstd/sys/unix/condvar.rs
@@ -92,14 +92,15 @@ impl Condvar {
         assert_eq!(r, 0);
 
         // Nanosecond calculations can't overflow because both values are below 1e9.
-        let nsec = dur.subsec_nanos() as libc::c_long + now.tv_nsec as libc::c_long;
+        let nsec = dur.subsec_nanos() + now.tv_nsec as u32;
+
         let sec = saturating_cast_to_time_t(dur.as_secs())
             .checked_add((nsec / 1_000_000_000) as libc::time_t)
             .and_then(|s| s.checked_add(now.tv_sec));
         let nsec = nsec % 1_000_000_000;
 
         let timeout = sec.map(|s| {
-            libc::timespec { tv_sec: s, tv_nsec: nsec }
+            libc::timespec { tv_sec: s, tv_nsec: nsec as _}
         }).unwrap_or(TIMESPEC_MAX);
 
         let r = libc::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex),
diff --git a/src/libstd/sys/unix/env.rs b/src/libstd/sys/unix/env.rs
index 3d9a06bedd5..00cf7eca75d 100644
--- a/src/libstd/sys/unix/env.rs
+++ b/src/libstd/sys/unix/env.rs
@@ -118,27 +118,6 @@ pub mod os {
     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";
diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs
index 3e631ad40ac..2e17fd58e0a 100644
--- a/src/libstd/sys/unix/ext/fs.rs
+++ b/src/libstd/sys/unix/ext/fs.rs
@@ -20,7 +20,9 @@ use sys;
 use sys_common::{FromInner, AsInner, AsInnerMut};
 use sys::platform::fs::MetadataExt as UnixMetadataExt;
 
-/// Unix-specific extensions to `File`
+/// Unix-specific extensions to [`File`].
+///
+/// [`File`]: ../../../../std/fs/struct.File.html
 #[stable(feature = "file_offset", since = "1.15.0")]
 pub trait FileExt {
     /// Reads a number of bytes starting from a given offset.
@@ -32,8 +34,28 @@ pub trait FileExt {
     ///
     /// 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
+    /// Note that similar to [`File::read`], it is not an error to return with a
     /// short read.
+    ///
+    /// [`File::read`]: ../../../../std/fs/struct.File.html#method.read
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::os::unix::prelude::FileExt;
+    /// use std::fs::File;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let mut buf = [0u8; 8];
+    /// let file = File::open("foo.txt")?;
+    ///
+    /// // We now read 8 bytes from the offset 10.
+    /// let num_bytes_read = file.read_at(&mut buf, 10)?;
+    /// println!("read {} bytes: {:?}", num_bytes_read, buf);
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "file_offset", since = "1.15.0")]
     fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
 
@@ -49,8 +71,26 @@ pub trait FileExt {
     /// When writing beyond the end of the file, the file is appropriately
     /// 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
+    /// Note that similar to [`File::write`], it is not an error to return a
     /// short write.
+    ///
+    /// [`File::write`]: ../../../../std/fs/struct.File.html#write.v
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::os::unix::prelude::FileExt;
+    /// use std::fs::File;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let file = File::open("foo.txt")?;
+    ///
+    /// // We now write at the offset 10.
+    /// file.write_at(b"sushi", 10)?;
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "file_offset", since = "1.15.0")]
     fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
 }
@@ -215,36 +255,282 @@ impl OpenOptionsExt for OpenOptions {
 // casts and rely on manual lowering to `stat` if the raw type is desired.
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
+    /// Returns the ID of the device containing the file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let dev_id = meta.dev();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn dev(&self) -> u64;
+    /// Returns the inode number.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let inode = meta.ino();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn ino(&self) -> u64;
+    /// Returns the rights applied to this file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let mode = meta.mode();
+    /// let user_has_write_access      = mode & 0o200;
+    /// let user_has_read_write_access = mode & 0o600;
+    /// let group_has_read_access      = mode & 0o040;
+    /// let others_have_exec_access    = mode & 0o001;
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn mode(&self) -> u32;
+    /// Returns the number of hard links pointing to this file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let nb_hard_links = meta.nlink();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn nlink(&self) -> u64;
+    /// Returns the user ID of the owner of this file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let user_id = meta.uid();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn uid(&self) -> u32;
+    /// Returns the group ID of the owner of this file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let group_id = meta.gid();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn gid(&self) -> u32;
+    /// Returns the device ID of this file (if it is a special one).
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let device_id = meta.rdev();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn rdev(&self) -> u64;
+    /// Returns the total size of this file in bytes.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let file_size = meta.size();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn size(&self) -> u64;
+    /// Returns the time of the last access to the file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let last_access_time = meta.atime();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn atime(&self) -> i64;
+    /// Returns the time of the last access to the file in nanoseconds.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let nano_last_access_time = meta.atime_nsec();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn atime_nsec(&self) -> i64;
+    /// Returns the time of the last modification of the file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let last_modification_time = meta.mtime();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn mtime(&self) -> i64;
+    /// Returns the time of the last modification of the file in nanoseconds.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let nano_last_modification_time = meta.mtime_nsec();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn mtime_nsec(&self) -> i64;
+    /// Returns the time of the last status change of the file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let last_status_change_time = meta.ctime();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn ctime(&self) -> i64;
+    /// Returns the time of the last status change of the file in nanoseconds.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let nano_last_status_change_time = meta.ctime_nsec();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn ctime_nsec(&self) -> i64;
+    /// Returns the blocksize for filesystem I/O.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let blocksize = meta.blksize();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn blksize(&self) -> u64;
+    /// Returns the number of blocks allocated to the file, in 512-byte units.
+    ///
+    /// Please note that this may be smaller than `st_size / 512` when the file has holes.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let blocks = meta.blocks();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn blocks(&self) -> u64;
 }
@@ -269,19 +555,79 @@ impl MetadataExt for fs::Metadata {
     fn blocks(&self) -> u64 { self.st_blocks() }
 }
 
-/// Add special unix types (block/char device, fifo and socket)
+/// Add support for special unix types (block/char device, fifo and socket).
 #[stable(feature = "file_type_ext", since = "1.5.0")]
 pub trait FileTypeExt {
     /// Returns whether this file type is a block device.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::unix::fs::FileTypeExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("block_device_file")?;
+    /// let file_type = meta.file_type();
+    /// assert!(file_type.is_block_device());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "file_type_ext", since = "1.5.0")]
     fn is_block_device(&self) -> bool;
     /// Returns whether this file type is a char device.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::unix::fs::FileTypeExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("char_device_file")?;
+    /// let file_type = meta.file_type();
+    /// assert!(file_type.is_char_device());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "file_type_ext", since = "1.5.0")]
     fn is_char_device(&self) -> bool;
     /// Returns whether this file type is a fifo.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::unix::fs::FileTypeExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("fifo_file")?;
+    /// let file_type = meta.file_type();
+    /// assert!(file_type.is_fifo());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "file_type_ext", since = "1.5.0")]
     fn is_fifo(&self) -> bool;
     /// Returns whether this file type is a socket.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::unix::fs::FileTypeExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("unix.socket")?;
+    /// let file_type = meta.file_type();
+    /// assert!(file_type.is_socket());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "file_type_ext", since = "1.5.0")]
     fn is_socket(&self) -> bool;
 }
@@ -294,7 +640,9 @@ impl FileTypeExt for fs::FileType {
     fn is_socket(&self) -> bool { self.as_inner().is(libc::S_IFSOCK) }
 }
 
-/// Unix-specific extension methods for `fs::DirEntry`
+/// Unix-specific extension methods for [`fs::DirEntry`].
+///
+/// [`fs::DirEntry`]: ../../../../std/fs/struct.DirEntry.html
 #[stable(feature = "dir_entry_ext", since = "1.1.0")]
 pub trait DirEntryExt {
     /// Returns the underlying `d_ino` field in the contained `dirent`
@@ -354,7 +702,9 @@ pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
 }
 
 #[stable(feature = "dir_builder", since = "1.6.0")]
-/// An extension trait for `fs::DirBuilder` for unix-specific options.
+/// An extension trait for [`fs::DirBuilder`] for unix-specific options.
+///
+/// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html
 pub trait DirBuilderExt {
     /// Sets the mode to create new directories with. This option defaults to
     /// 0o777.
diff --git a/src/libstd/sys/unix/ext/mod.rs b/src/libstd/sys/unix/ext/mod.rs
index 98bc90dd4e1..c221f7c8cfe 100644
--- a/src/libstd/sys/unix/ext/mod.rs
+++ b/src/libstd/sys/unix/ext/mod.rs
@@ -10,8 +10,14 @@
 
 //! Experimental extensions to `std` for Unix platforms.
 //!
-//! For now, this module is limited to extracting file descriptors,
-//! but its functionality will grow over time.
+//! Provides access to platform-level information on Unix platforms, and
+//! exposes Unix-specific functions that would otherwise be inappropriate as
+//! part of the core `std` library.
+//!
+//! It exposes more ways to deal with platform-specific strings (`OsStr`,
+//! `OsString`), allows to set permissions more granularly, extract low-level
+//! file descriptors from files and sockets, and has platform-specific helpers
+//! for spawning processes.
 //!
 //! # Examples
 //!
diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs
index cde21b089a2..60309bec6d4 100644
--- a/src/libstd/sys/unix/ext/process.rs
+++ b/src/libstd/sys/unix/ext/process.rs
@@ -191,3 +191,9 @@ impl IntoRawFd for process::ChildStderr {
         self.into_inner().into_fd().into_raw()
     }
 }
+
+/// Returns the OS-assigned process identifier associated with this process's parent.
+#[unstable(feature = "unix_ppid", issue = "46104")]
+pub fn parent_id() -> u32 {
+    ::sys::os::getppid()
+}
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index c4616c3b395..a1ca839dc18 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -132,14 +132,14 @@ impl FileAttr {
     pub fn modified(&self) -> io::Result<SystemTime> {
         Ok(SystemTime::from(libc::timespec {
             tv_sec: self.stat.st_mtime as libc::time_t,
-            tv_nsec: self.stat.st_mtime_nsec as libc::c_long,
+            tv_nsec: self.stat.st_mtime_nsec as _,
         }))
     }
 
     pub fn accessed(&self) -> io::Result<SystemTime> {
         Ok(SystemTime::from(libc::timespec {
             tv_sec: self.stat.st_atime as libc::time_t,
-            tv_nsec: self.stat.st_atime_nsec as libc::c_long,
+            tv_nsec: self.stat.st_atime_nsec as _,
         }))
     }
 
diff --git a/src/libstd/sys/unix/l4re.rs b/src/libstd/sys/unix/l4re.rs
index 21218489679..c3e8d0b7d95 100644
--- a/src/libstd/sys/unix/l4re.rs
+++ b/src/libstd/sys/unix/l4re.rs
@@ -437,5 +437,9 @@ pub mod net {
     pub fn lookup_host(_: &str) -> io::Result<LookupHost> {
         unimpl!();
     }
+
+    pub fn res_init_if_glibc_before_2_26() -> io::Result<()> {
+        unimpl!();
+    }
 }
 
diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs
index 1b3f1000b77..9bdea945ea4 100644
--- a/src/libstd/sys/unix/mod.rs
+++ b/src/libstd/sys/unix/mod.rs
@@ -22,7 +22,6 @@ use libc;
 #[cfg(all(not(dox), target_os = "haiku"))]     pub use os::haiku as platform;
 #[cfg(all(not(dox), target_os = "ios"))]       pub use os::ios as platform;
 #[cfg(all(not(dox), target_os = "macos"))]     pub use os::macos as platform;
-#[cfg(all(not(dox), target_os = "nacl"))]      pub use os::nacl as platform;
 #[cfg(all(not(dox), target_os = "netbsd"))]    pub use os::netbsd as platform;
 #[cfg(all(not(dox), target_os = "openbsd"))]   pub use os::openbsd as platform;
 #[cfg(all(not(dox), target_os = "solaris"))]   pub use os::solaris as platform;
@@ -30,6 +29,9 @@ use libc;
 #[cfg(all(not(dox), target_os = "fuchsia"))]   pub use os::fuchsia as platform;
 #[cfg(all(not(dox), target_os = "l4re"))]      pub use os::linux as platform;
 
+pub use self::rand::hashmap_random_keys;
+pub use libc::strlen;
+
 #[macro_use]
 pub mod weak;
 
@@ -37,6 +39,7 @@ pub mod args;
 pub mod android;
 #[cfg(feature = "backtrace")]
 pub mod backtrace;
+pub mod cmath;
 pub mod condvar;
 pub mod env;
 pub mod ext;
@@ -77,11 +80,11 @@ pub fn init() {
         reset_sigpipe();
     }
 
-    #[cfg(not(any(target_os = "nacl", target_os = "emscripten", target_os="fuchsia")))]
+    #[cfg(not(any(target_os = "emscripten", target_os="fuchsia")))]
     unsafe fn reset_sigpipe() {
         assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR);
     }
-    #[cfg(any(target_os = "nacl", target_os = "emscripten", target_os="fuchsia"))]
+    #[cfg(any(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 668b2f92aba..e775f857f2b 100644
--- a/src/libstd/sys/unix/net.rs
+++ b/src/libstd/sys/unix/net.rs
@@ -176,11 +176,16 @@ impl Socket {
                 }
                 0 => {}
                 _ => {
-                    if pollfd.revents & libc::POLLOUT == 0 {
-                        if let Some(e) = self.take_error()? {
-                            return Err(e);
-                        }
+                    // linux returns POLLOUT|POLLERR|POLLHUP for refused connections (!), so look
+                    // for POLLHUP rather than read readiness
+                    if pollfd.revents & libc::POLLHUP != 0 {
+                        let e = self.take_error()?
+                            .unwrap_or_else(|| {
+                                io::Error::new(io::ErrorKind::Other, "no error set after POLLHUP")
+                            });
+                        return Err(e);
                     }
+
                     return Ok(());
                 }
             }
@@ -355,3 +360,82 @@ impl FromInner<c_int> for Socket {
 impl IntoInner<c_int> for Socket {
     fn into_inner(self) -> c_int { self.0.into_raw() }
 }
+
+// In versions of glibc prior to 2.26, there's a bug where the DNS resolver
+// will cache the contents of /etc/resolv.conf, so changes to that file on disk
+// can be ignored by a long-running program. That can break DNS lookups on e.g.
+// laptops where the network comes and goes. See
+// https://sourceware.org/bugzilla/show_bug.cgi?id=984. Note however that some
+// distros including Debian have patched glibc to fix this for a long time.
+//
+// A workaround for this bug is to call the res_init libc function, to clear
+// the cached configs. Unfortunately, while we believe glibc's implementation
+// of res_init is thread-safe, we know that other implementations are not
+// (https://github.com/rust-lang/rust/issues/43592). Code here in libstd could
+// try to synchronize its res_init calls with a Mutex, but that wouldn't
+// protect programs that call into libc in other ways. So instead of calling
+// res_init unconditionally, we call it only when we detect we're linking
+// against glibc version < 2.26. (That is, when we both know its needed and
+// believe it's thread-safe).
+pub fn res_init_if_glibc_before_2_26() -> io::Result<()> {
+    // If the version fails to parse, we treat it the same as "not glibc".
+    if let Some(Ok(version_str)) = glibc_version_cstr().map(CStr::to_str) {
+        if let Some(version) = parse_glibc_version(version_str) {
+            if version < (2, 26) {
+                let ret = unsafe { libc::res_init() };
+                if ret != 0 {
+                    return Err(io::Error::last_os_error());
+                }
+            }
+        }
+    }
+    Ok(())
+}
+
+fn glibc_version_cstr() -> Option<&'static CStr> {
+    weak! {
+        fn gnu_get_libc_version() -> *const libc::c_char
+    }
+    if let Some(f) = gnu_get_libc_version.get() {
+        unsafe { Some(CStr::from_ptr(f())) }
+    } else {
+        None
+    }
+}
+
+// Returns Some((major, minor)) if the string is a valid "x.y" version,
+// ignoring any extra dot-separated parts. Otherwise return None.
+fn parse_glibc_version(version: &str) -> Option<(usize, usize)> {
+    let mut parsed_ints = version.split(".").map(str::parse::<usize>).fuse();
+    match (parsed_ints.next(), parsed_ints.next()) {
+        (Some(Ok(major)), Some(Ok(minor))) => Some((major, minor)),
+        _ => None
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+
+    #[test]
+    fn test_res_init() {
+        // This mostly just tests that the weak linkage doesn't panic wildly...
+        res_init_if_glibc_before_2_26().unwrap();
+    }
+
+    #[test]
+    fn test_parse_glibc_version() {
+        let cases = [
+            ("0.0", Some((0, 0))),
+            ("01.+2", Some((1, 2))),
+            ("3.4.5.six", Some((3, 4))),
+            ("1", None),
+            ("1.-2", None),
+            ("1.foo", None),
+            ("foo.1", None),
+        ];
+        for &(version_str, parsed) in cases.iter() {
+            assert_eq!(parsed, parse_glibc_version(version_str));
+        }
+    }
+}
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
index 5ef98d24710..4f33a2b12fe 100644
--- a/src/libstd/sys/unix/os.rs
+++ b/src/libstd/sys/unix/os.rs
@@ -223,7 +223,34 @@ pub fn current_exe() -> io::Result<PathBuf> {
 
 #[cfg(target_os = "netbsd")]
 pub fn current_exe() -> io::Result<PathBuf> {
-    ::fs::read_link("/proc/curproc/exe")
+    fn sysctl() -> io::Result<PathBuf> {
+        unsafe {
+            let mib = [libc::CTL_KERN, libc::KERN_PROC_ARGS, -1, libc::KERN_PROC_PATHNAME];
+            let mut path_len: usize = 0;
+            cvt(libc::sysctl(mib.as_ptr(), mib.len() as ::libc::c_uint,
+                             ptr::null_mut(), &mut path_len,
+                             ptr::null(), 0))?;
+            if path_len <= 1 {
+                return Err(io::Error::new(io::ErrorKind::Other,
+                           "KERN_PROC_PATHNAME sysctl returned zero-length string"))
+            }
+            let mut path: Vec<u8> = Vec::with_capacity(path_len);
+            cvt(libc::sysctl(mib.as_ptr(), mib.len() as ::libc::c_uint,
+                             path.as_ptr() as *mut libc::c_void, &mut path_len,
+                             ptr::null(), 0))?;
+            path.set_len(path_len - 1); // chop off NUL
+            Ok(PathBuf::from(OsString::from_vec(path)))
+        }
+    }
+    fn procfs() -> io::Result<PathBuf> {
+        let curproc_exe = path::Path::new("/proc/curproc/exe");
+        if curproc_exe.is_file() {
+            return ::fs::read_link(curproc_exe);
+        }
+        Err(io::Error::new(io::ErrorKind::Other,
+                           "/proc/curproc/exe doesn't point to regular file."))
+    }
+    sysctl().or_else(|_| procfs())
 }
 
 #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
@@ -483,12 +510,10 @@ pub fn home_dir() -> Option<PathBuf> {
 
     #[cfg(any(target_os = "android",
               target_os = "ios",
-              target_os = "nacl",
               target_os = "emscripten"))]
     unsafe fn fallback() -> Option<OsString> { None }
     #[cfg(not(any(target_os = "android",
                   target_os = "ios",
-                  target_os = "nacl",
                   target_os = "emscripten")))]
     unsafe fn fallback() -> Option<OsString> {
         let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) {
@@ -513,3 +538,11 @@ pub fn home_dir() -> Option<PathBuf> {
 pub fn exit(code: i32) -> ! {
     unsafe { libc::exit(code as c_int) }
 }
+
+pub fn getpid() -> u32 {
+    unsafe { libc::getpid() as u32 }
+}
+
+pub fn getppid() -> u32 {
+    unsafe { libc::getppid() as u32 }
+}
diff --git a/src/libstd/sys/unix/os_str.rs b/src/libstd/sys/unix/os_str.rs
index 777db17e3e1..a27e76a0e3b 100644
--- a/src/libstd/sys/unix/os_str.rs
+++ b/src/libstd/sys/unix/os_str.rs
@@ -15,6 +15,8 @@ use borrow::Cow;
 use fmt;
 use str;
 use mem;
+use rc::Rc;
+use sync::Arc;
 use sys_common::{AsInner, IntoInner};
 use std_unicode::lossy::Utf8Lossy;
 
@@ -123,6 +125,16 @@ impl Buf {
         let inner: Box<[u8]> = unsafe { mem::transmute(boxed) };
         Buf { inner: inner.into_vec() }
     }
+
+    #[inline]
+    pub fn into_arc(&self) -> Arc<Slice> {
+        self.as_slice().into_arc()
+    }
+
+    #[inline]
+    pub fn into_rc(&self) -> Rc<Slice> {
+        self.as_slice().into_rc()
+    }
 }
 
 impl Slice {
@@ -156,4 +168,16 @@ impl Slice {
         let boxed: Box<[u8]> = Default::default();
         unsafe { mem::transmute(boxed) }
     }
+
+    #[inline]
+    pub fn into_arc(&self) -> Arc<Slice> {
+        let arc: Arc<[u8]> = Arc::from(&self.inner);
+        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) }
+    }
+
+    #[inline]
+    pub fn into_rc(&self) -> Rc<Slice> {
+        let rc: Rc<[u8]> = Rc::from(&self.inner);
+        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
+    }
 }
diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs
index 689ccd78524..383434b1cd8 100644
--- a/src/libstd/sys/unix/process/process_common.rs
+++ b/src/libstd/sys/unix/process/process_common.rs
@@ -464,7 +464,6 @@ mod tests {
     // test from being flaky we ignore it on macOS.
     #[test]
     #[cfg_attr(target_os = "macos", ignore)]
-    #[cfg_attr(target_os = "nacl", ignore)] // no signals on NaCl.
     // When run under our current QEMU emulation test suite this test fails,
     // although the reason isn't very clear as to why. For now this test is
     // ignored there.
diff --git a/src/libstd/sys/unix/process/process_fuchsia.rs b/src/libstd/sys/unix/process/process_fuchsia.rs
index 5d34da04446..a7a67ed36e8 100644
--- a/src/libstd/sys/unix/process/process_fuchsia.rs
+++ b/src/libstd/sys/unix/process/process_fuchsia.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use io;
-use libc;
+use libc::{self, size_t};
 use mem;
 use ptr;
 
@@ -148,8 +148,8 @@ impl Process {
         use sys::process::zircon::*;
 
         let mut proc_info: zx_info_process_t = Default::default();
-        let mut actual: zx_size_t = 0;
-        let mut avail: zx_size_t = 0;
+        let mut actual: size_t = 0;
+        let mut avail: size_t = 0;
 
         unsafe {
             zx_cvt(zx_object_wait_one(self.handle.raw(), ZX_TASK_TERMINATED,
@@ -171,8 +171,8 @@ impl Process {
         use sys::process::zircon::*;
 
         let mut proc_info: zx_info_process_t = Default::default();
-        let mut actual: zx_size_t = 0;
-        let mut avail: zx_size_t = 0;
+        let mut actual: size_t = 0;
+        let mut avail: size_t = 0;
 
         unsafe {
             let status = zx_object_wait_one(self.handle.raw(), ZX_TASK_TERMINATED,
diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs
index 870db820027..743c458d580 100644
--- a/src/libstd/sys/unix/process/process_unix.rs
+++ b/src/libstd/sys/unix/process/process_unix.rs
@@ -184,8 +184,8 @@ impl Command {
             *sys::os::environ() = envp.as_ptr();
         }
 
-        // NaCl has no signal support.
-        #[cfg(not(any(target_os = "nacl", target_os = "emscripten")))]
+        // emscripten has no signal support.
+        #[cfg(not(any(target_os = "emscripten")))]
         {
             use mem;
             // Reset signal handling so the child process starts in a
diff --git a/src/libstd/sys/unix/process/zircon.rs b/src/libstd/sys/unix/process/zircon.rs
index b5ec11b40fd..90864e6ef3f 100644
--- a/src/libstd/sys/unix/process/zircon.rs
+++ b/src/libstd/sys/unix/process/zircon.rs
@@ -15,15 +15,13 @@ use io;
 use os::raw::c_char;
 use u64;
 
-use libc::{c_int, c_void};
+use libc::{c_int, c_void, size_t};
 
-pub type zx_handle_t = i32;
+pub type zx_handle_t = u32;
 pub type zx_vaddr_t = usize;
 pub type zx_rights_t = u32;
 pub type zx_status_t = i32;
 
-pub type zx_size_t = usize;
-
 pub const ZX_HANDLE_INVALID: zx_handle_t = 0;
 
 pub type zx_time_t = u64;
@@ -115,36 +113,37 @@ extern {
                               pending: *mut zx_signals_t) -> zx_status_t;
 
     pub fn zx_object_get_info(handle: zx_handle_t, topic: u32, buffer: *mut c_void,
-                              buffer_size: zx_size_t, actual_size: *mut zx_size_t,
-                              avail: *mut zx_size_t) -> zx_status_t;
+                              buffer_size: size_t, actual_size: *mut size_t,
+                              avail: *mut size_t) -> zx_status_t;
 }
 
 // From `enum special_handles` in system/ulib/launchpad/launchpad.c
 // HND_LOADER_SVC = 0
 // HND_EXEC_VMO = 1
-pub const HND_SPECIAL_COUNT: usize = 2;
+// HND_SEGMENTS_VMAR = 2
+const HND_SPECIAL_COUNT: c_int = 3;
 
 #[repr(C)]
 pub struct launchpad_t {
     argc: u32,
     envc: u32,
     args: *const c_char,
-    args_len: usize,
+    args_len: size_t,
     env: *const c_char,
-    env_len: usize,
+    env_len: size_t,
 
     handles: *mut zx_handle_t,
     handles_info: *mut u32,
-    handle_count: usize,
-    handle_alloc: usize,
+    handle_count: size_t,
+    handle_alloc: size_t,
 
     entry: zx_vaddr_t,
     base: zx_vaddr_t,
     vdso_base: zx_vaddr_t,
 
-    stack_size: usize,
+    stack_size: size_t,
 
-    special_handles: [zx_handle_t; HND_SPECIAL_COUNT],
+    special_handles: [zx_handle_t; HND_SPECIAL_COUNT as usize],
     loader_message: bool,
 }
 
diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs
index fd066c9cdbe..caa18945765 100644
--- a/src/libstd/sys/unix/rand.rs
+++ b/src/libstd/sys/unix/rand.rs
@@ -8,20 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub use self::imp::OsRng;
-
 use mem;
+use slice;
 
-fn next_u32(fill_buf: &mut FnMut(&mut [u8])) -> u32 {
-    let mut buf: [u8; 4] = [0; 4];
-    fill_buf(&mut buf);
-    unsafe { mem::transmute::<[u8; 4], u32>(buf) }
-}
-
-fn next_u64(fill_buf: &mut FnMut(&mut [u8])) -> u64 {
-    let mut buf: [u8; 8] = [0; 8];
-    fill_buf(&mut buf);
-    unsafe { mem::transmute::<[u8; 8], u64>(buf) }
+pub fn hashmap_random_keys() -> (u64, u64) {
+    let mut v = (0, 0);
+    unsafe {
+        let view = slice::from_raw_parts_mut(&mut v as *mut _ as *mut u8,
+                                             mem::size_of_val(&v));
+        imp::fill_bytes(view);
+    }
+    return v
 }
 
 #[cfg(all(unix,
@@ -30,56 +27,22 @@ fn next_u64(fill_buf: &mut FnMut(&mut [u8])) -> u64 {
           not(target_os = "freebsd"),
           not(target_os = "fuchsia")))]
 mod imp {
-    use self::OsRngInner::*;
-    use super::{next_u32, next_u64};
-
     use fs::File;
-    use io;
+    use io::Read;
     use libc;
-    use rand::Rng;
-    use rand::reader::ReaderRng;
     use sys::os::errno;
 
-    #[cfg(all(target_os = "linux",
-              any(target_arch = "x86_64",
-                  target_arch = "x86",
-                  target_arch = "arm",
-                  target_arch = "aarch64",
-                  target_arch = "powerpc",
-                  target_arch = "powerpc64",
-                  target_arch = "s390x")))]
+    #[cfg(any(target_os = "linux", target_os = "android"))]
     fn getrandom(buf: &mut [u8]) -> libc::c_long {
-        #[cfg(target_arch = "x86_64")]
-        const NR_GETRANDOM: libc::c_long = 318;
-        #[cfg(target_arch = "x86")]
-        const NR_GETRANDOM: libc::c_long = 355;
-        #[cfg(target_arch = "arm")]
-        const NR_GETRANDOM: libc::c_long = 384;
-        #[cfg(target_arch = "s390x")]
-        const NR_GETRANDOM: libc::c_long = 349;
-        #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
-        const NR_GETRANDOM: libc::c_long = 359;
-        #[cfg(target_arch = "aarch64")]
-        const NR_GETRANDOM: libc::c_long = 278;
-
-        const GRND_NONBLOCK: libc::c_uint = 0x0001;
-
         unsafe {
-            libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)
+            libc::syscall(libc::SYS_getrandom, buf.as_mut_ptr(), buf.len(), libc::GRND_NONBLOCK)
         }
     }
 
-    #[cfg(not(all(target_os = "linux",
-                  any(target_arch = "x86_64",
-                      target_arch = "x86",
-                      target_arch = "arm",
-                      target_arch = "aarch64",
-                      target_arch = "powerpc",
-                      target_arch = "powerpc64",
-                      target_arch = "s390x"))))]
+    #[cfg(not(any(target_os = "linux", target_os = "android")))]
     fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }
 
-    fn getrandom_fill_bytes(v: &mut [u8]) {
+    fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
         let mut read = 0;
         while read < v.len() {
             let result = getrandom(&mut v[read..]);
@@ -88,18 +51,7 @@ mod imp {
                 if err == libc::EINTR {
                     continue;
                 } else if err == libc::EAGAIN {
-                    // if getrandom() returns EAGAIN it would have blocked
-                    // because the non-blocking pool (urandom) has not
-                    // initialized in the kernel yet due to a lack of entropy
-                    // the fallback we do here is to avoid blocking applications
-                    // which could depend on this call without ever knowing
-                    // they do and don't have a work around. The PRNG of
-                    // /dev/urandom will still be used but not over a completely
-                    // 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();
+                    return false
                 } else {
                     panic!("unexpected getrandom error: {}", err);
                 }
@@ -107,17 +59,13 @@ mod imp {
                 read += result as usize;
             }
         }
+
+        return true
     }
 
-    #[cfg(all(target_os = "linux",
-              any(target_arch = "x86_64",
-                  target_arch = "x86",
-                  target_arch = "arm",
-                  target_arch = "aarch64",
-                  target_arch = "powerpc",
-                  target_arch = "powerpc64",
-                  target_arch = "s390x")))]
+    #[cfg(any(target_os = "linux", target_os = "android"))]
     fn is_getrandom_available() -> bool {
+        use io;
         use sync::atomic::{AtomicBool, Ordering};
         use sync::Once;
 
@@ -139,99 +87,40 @@ mod imp {
         AVAILABLE.load(Ordering::Relaxed)
     }
 
-    #[cfg(not(all(target_os = "linux",
-                  any(target_arch = "x86_64",
-                      target_arch = "x86",
-                      target_arch = "arm",
-                      target_arch = "aarch64",
-                      target_arch = "powerpc",
-                      target_arch = "powerpc64",
-                      target_arch = "s390x"))))]
+    #[cfg(not(any(target_os = "linux", target_os = "android")))]
     fn is_getrandom_available() -> bool { false }
 
-    pub struct OsRng {
-        inner: OsRngInner,
-    }
-
-    enum OsRngInner {
-        OsGetrandomRng,
-        OsReaderRng(ReaderRng<File>),
-    }
-
-    impl OsRng {
-        /// Create a new `OsRng`.
-        pub fn new() -> io::Result<OsRng> {
-            if is_getrandom_available() {
-                return Ok(OsRng { inner: OsGetrandomRng });
-            }
-
-            let reader = File::open("/dev/urandom")?;
-            let reader_rng = ReaderRng::new(reader);
-
-            Ok(OsRng { inner: OsReaderRng(reader_rng) })
+    pub fn fill_bytes(v: &mut [u8]) {
+        // getrandom_fill_bytes here can fail if getrandom() returns EAGAIN,
+        // meaning it would have blocked because the non-blocking pool (urandom)
+        // has not initialized in the kernel yet due to a lack of entropy the
+        // fallback we do here is to avoid blocking applications which could
+        // depend on this call without ever knowing they do and don't have a
+        // work around.  The PRNG of /dev/urandom will still be used but not
+        // over a completely full entropy pool
+        if is_getrandom_available() && getrandom_fill_bytes(v) {
+            return
         }
-    }
 
-    impl Rng for OsRng {
-        fn next_u32(&mut self) -> u32 {
-            match self.inner {
-                OsGetrandomRng => next_u32(&mut getrandom_fill_bytes),
-                OsReaderRng(ref mut rng) => rng.next_u32(),
-            }
-        }
-        fn next_u64(&mut self) -> u64 {
-            match self.inner {
-                OsGetrandomRng => next_u64(&mut getrandom_fill_bytes),
-                OsReaderRng(ref mut rng) => rng.next_u64(),
-            }
-        }
-        fn fill_bytes(&mut self, v: &mut [u8]) {
-            match self.inner {
-                OsGetrandomRng => getrandom_fill_bytes(v),
-                OsReaderRng(ref mut rng) => rng.fill_bytes(v)
-            }
-        }
+        let mut file = File::open("/dev/urandom")
+            .expect("failed to open /dev/urandom");
+        file.read_exact(v).expect("failed to read /dev/urandom");
     }
 }
 
 #[cfg(target_os = "openbsd")]
 mod imp {
-    use super::{next_u32, next_u64};
-
-    use io;
     use libc;
     use sys::os::errno;
-    use rand::Rng;
-
-    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]) {
-            // getentropy(2) permits a maximum buffer size of 256 bytes
-            for s in v.chunks_mut(256) {
-                let ret = unsafe {
-                    libc::getentropy(s.as_mut_ptr() as *mut libc::c_void, s.len())
-                };
-                if ret == -1 {
-                    panic!("unexpected getentropy error: {}", errno());
-                }
+    pub fn fill_bytes(v: &mut [u8]) {
+        // getentropy(2) permits a maximum buffer size of 256 bytes
+        for s in v.chunks_mut(256) {
+            let ret = unsafe {
+                libc::getentropy(s.as_mut_ptr() as *mut libc::c_void, s.len())
+            };
+            if ret == -1 {
+                panic!("unexpected getentropy error: {}", errno());
             }
         }
     }
@@ -239,18 +128,9 @@ mod imp {
 
 #[cfg(target_os = "ios")]
 mod imp {
-    use super::{next_u32, next_u64};
-
     use io;
-    use ptr;
-    use rand::Rng;
     use libc::{c_int, size_t};
-
-    pub struct OsRng {
-        // dummy field to ensure that this struct cannot be constructed outside
-        // of this module
-        _dummy: (),
-    }
+    use ptr;
 
     enum SecRandom {}
 
@@ -259,79 +139,41 @@ mod imp {
 
     extern {
         fn SecRandomCopyBytes(rnd: *const SecRandom,
-                              count: size_t, bytes: *mut u8) -> c_int;
+                              count: size_t,
+                              bytes: *mut u8) -> c_int;
     }
 
-    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 ret = unsafe {
-                SecRandomCopyBytes(kSecRandomDefault, v.len(),
-                                   v.as_mut_ptr())
-            };
-            if ret == -1 {
-                panic!("couldn't generate random bytes: {}",
-                       io::Error::last_os_error());
-            }
+    pub fn fill_bytes(v: &mut [u8]) {
+        let ret = unsafe {
+            SecRandomCopyBytes(kSecRandomDefault,
+                               v.len(),
+                               v.as_mut_ptr())
+        };
+        if ret == -1 {
+            panic!("couldn't generate random bytes: {}",
+                   io::Error::last_os_error());
         }
     }
 }
 
 #[cfg(target_os = "freebsd")]
 mod imp {
-    use super::{next_u32, next_u64};
-
-    use io;
     use libc;
-    use rand::Rng;
     use ptr;
 
-    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 mib = [libc::CTL_KERN, libc::KERN_ARND];
-            // kern.arandom permits a maximum buffer size of 256 bytes
-            for s in v.chunks_mut(256) {
-                let mut s_len = s.len();
-                let ret = unsafe {
-                    libc::sysctl(mib.as_ptr(), mib.len() as libc::c_uint,
-                                 s.as_mut_ptr() as *mut _, &mut s_len,
-                                 ptr::null(), 0)
-                };
-                if ret == -1 || s_len != s.len() {
-                    panic!("kern.arandom sysctl failed! (returned {}, s.len() {}, oldlenp {})",
-                           ret, s.len(), s_len);
-                }
+    pub fn fill_bytes(v: &mut [u8]) {
+        let mib = [libc::CTL_KERN, libc::KERN_ARND];
+        // kern.arandom permits a maximum buffer size of 256 bytes
+        for s in v.chunks_mut(256) {
+            let mut s_len = s.len();
+            let ret = unsafe {
+                libc::sysctl(mib.as_ptr(), mib.len() as libc::c_uint,
+                             s.as_mut_ptr() as *mut _, &mut s_len,
+                             ptr::null(), 0)
+            };
+            if ret == -1 || s_len != s.len() {
+                panic!("kern.arandom sysctl failed! (returned {}, s.len() {}, oldlenp {})",
+                       ret, s.len(), s_len);
             }
         }
     }
@@ -339,11 +181,6 @@ mod imp {
 
 #[cfg(target_os = "fuchsia")]
 mod imp {
-    use super::{next_u32, next_u64};
-
-    use io;
-    use rand::Rng;
-
     #[link(name = "zircon")]
     extern {
         fn zx_cprng_draw(buffer: *mut u8, len: usize, actual: *mut usize) -> i32;
@@ -361,39 +198,18 @@ mod imp {
         }
     }
 
-    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);
-                match ret {
-                    Err(err) => {
-                        panic!("kernel zx_cprng_draw call failed! (returned {}, buf.len() {})",
-                            err, buf.len())
-                    }
-                    Ok(actual) => {
-                        let move_buf = buf;
-                        buf = &mut move_buf[(actual as usize)..];
-                    }
+    pub fn fill_bytes(v: &mut [u8]) {
+        let mut buf = v;
+        while !buf.is_empty() {
+            let ret = getrandom(buf);
+            match ret {
+                Err(err) => {
+                    panic!("kernel zx_cprng_draw call failed! (returned {}, buf.len() {})",
+                        err, buf.len())
+                }
+                Ok(actual) => {
+                    let move_buf = buf;
+                    buf = &mut move_buf[(actual as usize)..];
                 }
             }
         }
diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs
index 7a8fe25d98e..e9b3d4affc7 100644
--- a/src/libstd/sys/unix/stdio.rs
+++ b/src/libstd/sys/unix/stdio.rs
@@ -70,5 +70,8 @@ impl io::Write for Stderr {
     }
 }
 
-pub const EBADF_ERR: i32 = ::libc::EBADF as i32;
+pub fn is_ebadf(err: &io::Error) -> bool {
+    err.raw_os_error() == Some(libc::EBADF as i32)
+}
+
 pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index 6c4a3324296..9da33f5adac 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -87,7 +87,7 @@ impl Thread {
         };
 
         extern fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void {
-            unsafe { start_thread(main); }
+            unsafe { start_thread(main as *mut u8); }
             ptr::null_mut()
         }
     }
@@ -149,7 +149,7 @@ impl Thread {
 
     pub fn sleep(dur: Duration) {
         let mut secs = dur.as_secs();
-        let mut nsecs = dur.subsec_nanos() as libc::c_long;
+        let mut nsecs = dur.subsec_nanos() as _;
 
         // If we're awoken with a signal then the return value will be -1 and
         // nanosleep will fill in `ts` with the remaining time.
diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs
index c1bea95ce91..837cd7292e2 100644
--- a/src/libstd/sys/unix/time.rs
+++ b/src/libstd/sys/unix/time.rs
@@ -60,7 +60,7 @@ impl Timespec {
         Timespec {
             t: libc::timespec {
                 tv_sec: secs,
-                tv_nsec: nsec as libc::c_long,
+                tv_nsec: nsec as _,
             },
         }
     }
@@ -83,7 +83,7 @@ impl Timespec {
         Timespec {
             t: libc::timespec {
                 tv_sec: secs,
-                tv_nsec: nsec as libc::c_long,
+                tv_nsec: nsec as _,
             },
         }
     }
diff --git a/src/libstd/sys/wasm/args.rs b/src/libstd/sys/wasm/args.rs
new file mode 100644
index 00000000000..d2a4a7b19d5
--- /dev/null
+++ b/src/libstd/sys/wasm/args.rs
@@ -0,0 +1,90 @@
+// Copyright 2017 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 ffi::OsString;
+use marker::PhantomData;
+use mem;
+use vec;
+
+pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
+    // On wasm these should always be null, so there's nothing for us to do here
+}
+
+pub unsafe fn cleanup() {
+}
+
+pub fn args() -> Args {
+    // When the runtime debugging is enabled we'll link to some extra runtime
+    // functions to actually implement this. These are for now just implemented
+    // in a node.js script but they're off by default as they're sort of weird
+    // in a web-wasm world.
+    if !super::DEBUG {
+        return Args {
+            iter: Vec::new().into_iter(),
+            _dont_send_or_sync_me: PhantomData,
+        }
+    }
+
+    // You'll find the definitions of these in `src/etc/wasm32-shim.js`. These
+    // are just meant for debugging and should not be relied on.
+    extern {
+        fn rust_wasm_args_count() -> usize;
+        fn rust_wasm_args_arg_size(a: usize) -> usize;
+        fn rust_wasm_args_arg_fill(a: usize, ptr: *mut u8);
+    }
+
+    unsafe {
+        let cnt = rust_wasm_args_count();
+        let mut v = Vec::with_capacity(cnt);
+        for i in 0..cnt {
+            let n = rust_wasm_args_arg_size(i);
+            let mut data = vec![0; n];
+            rust_wasm_args_arg_fill(i, data.as_mut_ptr());
+            v.push(mem::transmute::<Vec<u8>, OsString>(data));
+        }
+        Args {
+            iter: v.into_iter(),
+            _dont_send_or_sync_me: PhantomData,
+        }
+    }
+}
+
+pub struct Args {
+    iter: vec::IntoIter<OsString>,
+    _dont_send_or_sync_me: PhantomData<*mut ()>,
+}
+
+impl Args {
+    pub fn inner_debug(&self) -> &[OsString] {
+        self.iter.as_slice()
+    }
+}
+
+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()
+    }
+}
diff --git a/src/libstd/sys/wasm/backtrace.rs b/src/libstd/sys/wasm/backtrace.rs
new file mode 100644
index 00000000000..9a8c48ff29f
--- /dev/null
+++ b/src/libstd/sys/wasm/backtrace.rs
@@ -0,0 +1,37 @@
+// Copyright 2017 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 io;
+use sys::unsupported;
+use sys_common::backtrace::Frame;
+
+pub struct BacktraceContext;
+
+pub fn unwind_backtrace(_frames: &mut [Frame])
+    -> io::Result<(usize, BacktraceContext)>
+{
+    unsupported()
+}
+
+pub fn resolve_symname<F>(_frame: Frame,
+                          _callback: F,
+                          _: &BacktraceContext) -> io::Result<()>
+    where F: FnOnce(Option<&str>) -> io::Result<()>
+{
+    unsupported()
+}
+
+pub fn foreach_symbol_fileline<F>(_: Frame,
+                                  _: F,
+                                  _: &BacktraceContext) -> io::Result<bool>
+    where F: FnMut(&[u8], u32) -> io::Result<()>
+{
+    unsupported()
+}
diff --git a/src/libstd/sys/wasm/cmath.rs b/src/libstd/sys/wasm/cmath.rs
new file mode 100644
index 00000000000..87ac2091cad
--- /dev/null
+++ b/src/libstd/sys/wasm/cmath.rs
@@ -0,0 +1,119 @@
+// Copyright 2017 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.
+
+#[inline]
+pub unsafe fn cbrtf(n: f32) -> f32 {
+    f64::cbrt(n as f64) as f32
+}
+
+#[inline]
+pub unsafe fn expm1f(n: f32) -> f32 {
+    f64::exp_m1(n as f64) as f32
+}
+
+#[inline]
+#[allow(deprecated)]
+pub unsafe fn fdimf(a: f32, b: f32) -> f32 {
+    f64::abs_sub(a as f64, b as f64) as f32
+}
+
+#[inline]
+pub unsafe fn log1pf(n: f32) -> f32 {
+    f64::ln_1p(n as f64) as f32
+}
+
+#[inline]
+pub unsafe fn hypotf(x: f32, y: f32) -> f32 {
+    f64::hypot(x as f64, y as f64) as f32
+}
+
+#[inline]
+pub unsafe fn acosf(n: f32) -> f32 {
+    f64::acos(n as f64) as f32
+}
+
+#[inline]
+pub unsafe fn asinf(n: f32) -> f32 {
+    f64::asin(n as f64) as f32
+}
+
+#[inline]
+pub unsafe fn atan2f(n: f32, b: f32) -> f32 {
+    f64::atan2(n as f64, b as f64) as f32
+}
+
+#[inline]
+pub unsafe fn atanf(n: f32) -> f32 {
+    f64::atan(n as f64) as f32
+}
+
+#[inline]
+pub unsafe fn coshf(n: f32) -> f32 {
+    f64::cosh(n as f64) as f32
+}
+
+#[inline]
+pub unsafe fn sinhf(n: f32) -> f32 {
+    f64::sinh(n as f64) as f32
+}
+
+#[inline]
+pub unsafe fn tanf(n: f32) -> f32 {
+    f64::tan(n as f64) as f32
+}
+
+#[inline]
+pub unsafe fn tanhf(n: f32) -> f32 {
+    f64::tanh(n as f64) as f32
+}
+
+// Right now all these functions, the f64 version of the functions above, all
+// shell out to random names. These names aren't actually defined anywhere, per
+// se, but we need this to compile somehow.
+//
+// The idea with this is that when you're using wasm then, for now, we have no
+// way of providing an implementation of these which delegates to a "correct"
+// implementation. For example most wasm applications probably just want to
+// delegate to the javascript `Math` object and its related functions, but wasm
+// doesn't currently have the ability to seamlessly do that (when you
+// instantiate a module you have to set that up).
+//
+// As a result these are just defined here with "hopefully helpful" names. The
+// symbols won't ever be needed or show up unless these functions are called,
+// and hopefully when they're called the errors are self-explanatory enough to
+// figure out what's going on.
+
+extern {
+    #[link_name = "Math_acos"]
+    pub fn acos(n: f64) -> f64;
+    #[link_name = "Math_asin"]
+    pub fn asin(n: f64) -> f64;
+    #[link_name = "Math_atan"]
+    pub fn atan(n: f64) -> f64;
+    #[link_name = "Math_atan2"]
+    pub fn atan2(a: f64, b: f64) -> f64;
+    #[link_name = "Math_cbrt"]
+    pub fn cbrt(n: f64) -> f64;
+    #[link_name = "Math_cosh"]
+    pub fn cosh(n: f64) -> f64;
+    #[link_name = "Math_expm1"]
+    pub fn expm1(n: f64) -> f64;
+    pub fn fdim(a: f64, b: f64) -> f64;
+    #[link_name = "Math_log1p"]
+    pub fn log1p(n: f64) -> f64;
+    #[link_name = "Math_sinh"]
+    pub fn sinh(n: f64) -> f64;
+    #[link_name = "Math_tan"]
+    pub fn tan(n: f64) -> f64;
+    #[link_name = "Math_tanh"]
+    pub fn tanh(n: f64) -> f64;
+    #[link_name = "Math_hypot"]
+    pub fn hypot(x: f64, y: f64) -> f64;
+}
diff --git a/src/libstd/sys/wasm/condvar.rs b/src/libstd/sys/wasm/condvar.rs
new file mode 100644
index 00000000000..afa7afeef59
--- /dev/null
+++ b/src/libstd/sys/wasm/condvar.rs
@@ -0,0 +1,43 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use sys::mutex::Mutex;
+use time::Duration;
+
+pub struct Condvar { }
+
+impl Condvar {
+    pub const fn new() -> Condvar {
+        Condvar { }
+    }
+
+    #[inline]
+    pub unsafe fn init(&mut self) {}
+
+    #[inline]
+    pub unsafe fn notify_one(&self) {
+    }
+
+    #[inline]
+    pub unsafe fn notify_all(&self) {
+    }
+
+    pub unsafe fn wait(&self, _mutex: &Mutex) {
+        panic!("can't block with web assembly")
+    }
+
+    pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
+        panic!("can't block with web assembly");
+    }
+
+    #[inline]
+    pub unsafe fn destroy(&self) {
+    }
+}
diff --git a/src/libstd/sys/wasm/env.rs b/src/libstd/sys/wasm/env.rs
new file mode 100644
index 00000000000..1422042bd02
--- /dev/null
+++ b/src/libstd/sys/wasm/env.rs
@@ -0,0 +1,19 @@
+// Copyright 2017 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 = "";
+    pub const OS: &'static str = "";
+    pub const DLL_PREFIX: &'static str = "";
+    pub const DLL_SUFFIX: &'static str = ".wasm";
+    pub const DLL_EXTENSION: &'static str = "wasm";
+    pub const EXE_SUFFIX: &'static str = ".wasm";
+    pub const EXE_EXTENSION: &'static str = "wasm";
+}
diff --git a/src/libstd/sys/wasm/fs.rs b/src/libstd/sys/wasm/fs.rs
new file mode 100644
index 00000000000..b3c70a6685a
--- /dev/null
+++ b/src/libstd/sys/wasm/fs.rs
@@ -0,0 +1,304 @@
+// Copyright 2017 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 ffi::OsString;
+use fmt;
+use hash::{Hash, Hasher};
+use io::{self, SeekFrom};
+use path::{Path, PathBuf};
+use sys::time::SystemTime;
+use sys::{unsupported, Void};
+
+pub struct File(Void);
+
+pub struct FileAttr(Void);
+
+pub struct ReadDir(Void);
+
+pub struct DirEntry(Void);
+
+#[derive(Clone, Debug)]
+pub struct OpenOptions { }
+
+pub struct FilePermissions(Void);
+
+pub struct FileType(Void);
+
+#[derive(Debug)]
+pub struct DirBuilder { }
+
+impl FileAttr {
+    pub fn size(&self) -> u64 {
+        match self.0 {}
+    }
+
+    pub fn perm(&self) -> FilePermissions {
+        match self.0 {}
+    }
+
+    pub fn file_type(&self) -> FileType {
+        match self.0 {}
+    }
+
+    pub fn modified(&self) -> io::Result<SystemTime> {
+        match self.0 {}
+    }
+
+    pub fn accessed(&self) -> io::Result<SystemTime> {
+        match self.0 {}
+    }
+
+    pub fn created(&self) -> io::Result<SystemTime> {
+        match self.0 {}
+    }
+}
+
+impl Clone for FileAttr {
+    fn clone(&self) -> FileAttr {
+        match self.0 {}
+    }
+}
+
+impl FilePermissions {
+    pub fn readonly(&self) -> bool {
+        match self.0 {}
+    }
+
+    pub fn set_readonly(&mut self, _readonly: bool) {
+        match self.0 {}
+    }
+}
+
+impl Clone for FilePermissions {
+    fn clone(&self) -> FilePermissions {
+        match self.0 {}
+    }
+}
+
+impl PartialEq for FilePermissions {
+    fn eq(&self, _other: &FilePermissions) -> bool {
+        match self.0 {}
+    }
+}
+
+impl Eq for FilePermissions {
+}
+
+impl fmt::Debug for FilePermissions {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        match self.0 {}
+    }
+}
+
+impl FileType {
+    pub fn is_dir(&self) -> bool {
+        match self.0 {}
+    }
+
+    pub fn is_file(&self) -> bool {
+        match self.0 {}
+    }
+
+    pub fn is_symlink(&self) -> bool {
+        match self.0 {}
+    }
+}
+
+impl Clone for FileType {
+    fn clone(&self) -> FileType {
+        match self.0 {}
+    }
+}
+
+impl Copy for FileType {}
+
+impl PartialEq for FileType {
+    fn eq(&self, _other: &FileType) -> bool {
+        match self.0 {}
+    }
+}
+
+impl Eq for FileType {
+}
+
+impl Hash for FileType {
+    fn hash<H: Hasher>(&self, _h: &mut H) {
+        match self.0 {}
+    }
+}
+
+impl fmt::Debug for FileType {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        match self.0 {}
+    }
+}
+
+impl fmt::Debug for ReadDir {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        match self.0 {}
+    }
+}
+
+impl Iterator for ReadDir {
+    type Item = io::Result<DirEntry>;
+
+    fn next(&mut self) -> Option<io::Result<DirEntry>> {
+        match self.0 {}
+    }
+}
+
+impl DirEntry {
+    pub fn path(&self) -> PathBuf {
+        match self.0 {}
+    }
+
+    pub fn file_name(&self) -> OsString {
+        match self.0 {}
+    }
+
+    pub fn metadata(&self) -> io::Result<FileAttr> {
+        match self.0 {}
+    }
+
+    pub fn file_type(&self) -> io::Result<FileType> {
+        match self.0 {}
+    }
+}
+
+impl OpenOptions {
+    pub fn new() -> OpenOptions {
+        OpenOptions { }
+    }
+
+    pub fn read(&mut self, _read: bool) { }
+    pub fn write(&mut self, _write: bool) { }
+    pub fn append(&mut self, _append: bool) { }
+    pub fn truncate(&mut self, _truncate: bool) { }
+    pub fn create(&mut self, _create: bool) { }
+    pub fn create_new(&mut self, _create_new: bool) { }
+}
+
+impl File {
+    pub fn open(_path: &Path, _opts: &OpenOptions) -> io::Result<File> {
+        unsupported()
+    }
+
+    pub fn file_attr(&self) -> io::Result<FileAttr> {
+        match self.0 {}
+    }
+
+    pub fn fsync(&self) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn datasync(&self) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn truncate(&self, _size: u64) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn flush(&self) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
+        match self.0 {}
+    }
+
+    pub fn duplicate(&self) -> io::Result<File> {
+        match self.0 {}
+    }
+
+    pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn diverge(&self) -> ! {
+        match self.0 {}
+    }
+}
+
+impl DirBuilder {
+    pub fn new() -> DirBuilder {
+        DirBuilder { }
+    }
+
+    pub fn mkdir(&self, _p: &Path) -> io::Result<()> {
+        unsupported()
+    }
+}
+
+impl fmt::Debug for File {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        match self.0 {}
+    }
+}
+
+pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
+    unsupported()
+}
+
+pub fn unlink(_p: &Path) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> {
+    match perm.0 {}
+}
+
+pub fn rmdir(_p: &Path) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
+    unsupported()
+}
+
+pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn stat(_p: &Path) -> io::Result<FileAttr> {
+    unsupported()
+}
+
+pub fn lstat(_p: &Path) -> io::Result<FileAttr> {
+    unsupported()
+}
+
+pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
+    unsupported()
+}
+
+pub fn copy(_from: &Path, _to: &Path) -> io::Result<u64> {
+    unsupported()
+}
diff --git a/src/libstd/os/nacl/mod.rs b/src/libstd/sys/wasm/memchr.rs
index 7dfa2eabe3e..e611d94af30 100644
--- a/src/libstd/os/nacl/mod.rs
+++ b/src/libstd/sys/wasm/memchr.rs
@@ -1,4 +1,4 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,9 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Nacl-specific definitions
-
-#![stable(feature = "raw_ext", since = "1.1.0")]
-
-pub mod raw;
-pub mod fs;
+pub use sys_common::memchr::fallback::{memchr, memrchr};
diff --git a/src/libstd/sys/wasm/mod.rs b/src/libstd/sys/wasm/mod.rs
new file mode 100644
index 00000000000..b838dbafd6f
--- /dev/null
+++ b/src/libstd/sys/wasm/mod.rs
@@ -0,0 +1,104 @@
+// Copyright 2017 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.
+
+//! System bindings for the wasm/web platform
+//!
+//! This module contains the facade (aka platform-specific) implementations of
+//! OS level functionality for wasm. Note that this wasm is *not* the emscripten
+//! wasm, so we have no runtime here.
+//!
+//! This is all super highly experimental and not actually intended for
+//! wide/production use yet, it's still all in the experimental category. This
+//! will likely change over time.
+//!
+//! Currently all functions here are basically stubs that immediately return
+//! errors. The hope is that with a portability lint we can turn actually just
+//! remove all this and just omit parts of the standard library if we're
+//! compiling for wasm. That way it's a compile time error for something that's
+//! guaranteed to be a runtime error!
+
+use io;
+use os::raw::c_char;
+
+// Right now the wasm backend doesn't even have the ability to print to the
+// console by default. Wasm can't import anything from JS! (you have to
+// explicitly provide it).
+//
+// Sometimes that's a real bummer, though, so this flag can be set to `true` to
+// enable calling various shims defined in `src/etc/wasm32-shim.js` which should
+// help receive debug output and see what's going on. In general this flag
+// currently controls "will we call out to our own defined shims in node.js",
+// and this flag should always be `false` for release builds.
+const DEBUG: bool = false;
+
+pub mod args;
+pub mod backtrace;
+pub mod cmath;
+pub mod condvar;
+pub mod env;
+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 rwlock;
+pub mod stack_overflow;
+pub mod thread;
+pub mod thread_local;
+pub mod time;
+pub mod stdio;
+
+#[cfg(not(test))]
+pub fn init() {
+}
+
+pub fn unsupported<T>() -> io::Result<T> {
+    Err(unsupported_err())
+}
+
+pub fn unsupported_err() -> io::Error {
+    io::Error::new(io::ErrorKind::Other,
+                   "operation not supported on wasm yet")
+}
+
+pub fn decode_error_kind(_code: i32) -> io::ErrorKind {
+    io::ErrorKind::Other
+}
+
+// This enum is used as the storage for a bunch of types which can't actually
+// exist.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+pub enum Void {}
+
+pub unsafe fn strlen(mut s: *const c_char) -> usize {
+    let mut n = 0;
+    while *s != 0 {
+        n += 1;
+        s = s.offset(1);
+    }
+    return n
+}
+
+pub unsafe fn abort_internal() -> ! {
+    ::intrinsics::abort();
+}
+
+// We don't have randomness yet, but I totally used a random number generator to
+// generate these numbers.
+//
+// More seriously though this is just for DOS protection in hash maps. It's ok
+// if we don't do that on wasm just yet.
+pub fn hashmap_random_keys() -> (u64, u64) {
+    (1, 2)
+}
diff --git a/src/libstd/sys/wasm/mutex.rs b/src/libstd/sys/wasm/mutex.rs
new file mode 100644
index 00000000000..4197bdcc808
--- /dev/null
+++ b/src/libstd/sys/wasm/mutex.rs
@@ -0,0 +1,79 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use cell::UnsafeCell;
+
+pub struct Mutex {
+    locked: UnsafeCell<bool>,
+}
+
+unsafe impl Send for Mutex {}
+unsafe impl Sync for Mutex {} // no threads on wasm
+
+impl Mutex {
+    pub const fn new() -> Mutex {
+        Mutex { locked: UnsafeCell::new(false) }
+    }
+
+    #[inline]
+    pub unsafe fn init(&mut self) {
+    }
+
+    #[inline]
+    pub unsafe fn lock(&self) {
+        let locked = self.locked.get();
+        assert!(!*locked, "cannot recursively acquire mutex");
+        *locked = true;
+    }
+
+    #[inline]
+    pub unsafe fn unlock(&self) {
+        *self.locked.get() = false;
+    }
+
+    #[inline]
+    pub unsafe fn try_lock(&self) -> bool {
+        let locked = self.locked.get();
+        if *locked {
+            false
+        } else {
+            *locked = true;
+            true
+        }
+    }
+
+    #[inline]
+    pub unsafe fn destroy(&self) {
+    }
+}
+
+// All empty stubs because wasm has no threads yet, so lock acquisition always
+// succeeds.
+pub struct ReentrantMutex {
+}
+
+impl ReentrantMutex {
+    pub unsafe fn uninitialized() -> ReentrantMutex {
+        ReentrantMutex { }
+    }
+
+    pub unsafe fn init(&mut self) {}
+
+    pub unsafe fn lock(&self) {}
+
+    #[inline]
+    pub unsafe fn try_lock(&self) -> bool {
+        true
+    }
+
+    pub unsafe fn unlock(&self) {}
+
+    pub unsafe fn destroy(&self) {}
+}
diff --git a/src/libstd/sys/wasm/net.rs b/src/libstd/sys/wasm/net.rs
new file mode 100644
index 00000000000..e7476ab37f7
--- /dev/null
+++ b/src/libstd/sys/wasm/net.rs
@@ -0,0 +1,337 @@
+// Copyright 2017 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 fmt;
+use io;
+use net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr};
+use time::Duration;
+use sys::{unsupported, Void};
+
+pub struct TcpStream(Void);
+
+impl TcpStream {
+    pub fn connect(_: &SocketAddr) -> io::Result<TcpStream> {
+        unsupported()
+    }
+
+    pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
+        unsupported()
+    }
+
+    pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
+        match self.0 {}
+    }
+
+    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
+        match self.0 {}
+    }
+
+    pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn write(&self, _: &[u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+        match self.0 {}
+    }
+
+    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
+        match self.0 {}
+    }
+
+    pub fn shutdown(&self, _: Shutdown) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn duplicate(&self) -> io::Result<TcpStream> {
+        match self.0 {}
+    }
+
+    pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn nodelay(&self) -> io::Result<bool> {
+        match self.0 {}
+    }
+
+    pub fn set_ttl(&self, _: u32) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn ttl(&self) -> io::Result<u32> {
+        match self.0 {}
+    }
+
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        match self.0 {}
+    }
+
+    pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
+        match self.0 {}
+    }
+}
+
+impl fmt::Debug for TcpStream {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        match self.0 {}
+    }
+}
+
+pub struct TcpListener(Void);
+
+impl TcpListener {
+    pub fn bind(_: &SocketAddr) -> io::Result<TcpListener> {
+        unsupported()
+    }
+
+    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
+        match self.0 {}
+    }
+
+    pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
+        match self.0 {}
+    }
+
+    pub fn duplicate(&self) -> io::Result<TcpListener> {
+        match self.0 {}
+    }
+
+    pub fn set_ttl(&self, _: u32) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn ttl(&self) -> io::Result<u32> {
+        match self.0 {}
+    }
+
+    pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn only_v6(&self) -> io::Result<bool> {
+        match self.0 {}
+    }
+
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        match self.0 {}
+    }
+
+    pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
+        match self.0 {}
+    }
+}
+
+impl fmt::Debug for TcpListener {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        match self.0 {}
+    }
+}
+
+pub struct UdpSocket(Void);
+
+impl UdpSocket {
+    pub fn bind(_: &SocketAddr) -> io::Result<UdpSocket> {
+        unsupported()
+    }
+
+    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
+        match self.0 {}
+    }
+
+    pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+        match self.0 {}
+    }
+
+    pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+        match self.0 {}
+    }
+
+    pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn duplicate(&self) -> io::Result<UdpSocket> {
+        match self.0 {}
+    }
+
+    pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
+        match self.0 {}
+    }
+
+    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
+        match self.0 {}
+    }
+
+    pub fn set_broadcast(&self, _: bool) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn broadcast(&self) -> io::Result<bool> {
+        match self.0 {}
+    }
+
+    pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn multicast_loop_v4(&self) -> io::Result<bool> {
+        match self.0 {}
+    }
+
+    pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
+        match self.0 {}
+    }
+
+    pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn multicast_loop_v6(&self) -> io::Result<bool> {
+        match self.0 {}
+    }
+
+    pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr)
+                         -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32)
+                         -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr)
+                          -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32)
+                          -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn set_ttl(&self, _: u32) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn ttl(&self) -> io::Result<u32> {
+        match self.0 {}
+    }
+
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        match self.0 {}
+    }
+
+    pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn send(&self, _: &[u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn connect(&self, _: &SocketAddr) -> io::Result<()> {
+        match self.0 {}
+    }
+}
+
+impl fmt::Debug for UdpSocket {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        match self.0 {}
+    }
+}
+
+pub struct LookupHost(Void);
+
+impl Iterator for LookupHost {
+    type Item = SocketAddr;
+    fn next(&mut self) -> Option<SocketAddr> {
+        match self.0 {}
+    }
+}
+
+pub fn lookup_host(_: &str) -> io::Result<LookupHost> {
+    unsupported()
+}
+
+#[allow(bad_style)]
+pub mod netc {
+    pub const AF_INET: u8 = 0;
+    pub const AF_INET6: u8 = 1;
+    pub type sa_family_t = u8;
+
+    #[derive(Copy, Clone)]
+    pub struct in_addr {
+        pub s_addr: u32,
+    }
+
+    #[derive(Copy, Clone)]
+    pub struct sockaddr_in {
+        pub sin_family: sa_family_t,
+        pub sin_port: u16,
+        pub sin_addr: in_addr,
+    }
+
+    #[derive(Copy, Clone)]
+    pub struct in6_addr {
+        pub s6_addr: [u8; 16],
+    }
+
+    #[derive(Copy, Clone)]
+    pub struct sockaddr_in6 {
+        pub sin6_family: sa_family_t,
+        pub sin6_port: u16,
+        pub sin6_addr: in6_addr,
+        pub sin6_flowinfo: u32,
+        pub sin6_scope_id: u32,
+    }
+
+    #[derive(Copy, Clone)]
+    pub struct sockaddr {
+    }
+
+    pub type socklen_t = usize;
+}
diff --git a/src/libstd/sys/wasm/os.rs b/src/libstd/sys/wasm/os.rs
new file mode 100644
index 00000000000..c98030f7ebf
--- /dev/null
+++ b/src/libstd/sys/wasm/os.rs
@@ -0,0 +1,136 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::intrinsics;
+
+use error::Error as StdError;
+use ffi::{OsString, OsStr};
+use fmt;
+use io;
+use mem;
+use path::{self, PathBuf};
+use str;
+use sys::{unsupported, Void};
+
+pub fn errno() -> i32 {
+    0
+}
+
+pub fn error_string(_errno: i32) -> String {
+    format!("operation successful")
+}
+
+pub fn getcwd() -> io::Result<PathBuf> {
+    unsupported()
+}
+
+pub fn chdir(_: &path::Path) -> io::Result<()> {
+    unsupported()
+}
+
+pub struct SplitPaths<'a>(&'a Void);
+
+pub fn split_paths(_unparsed: &OsStr) -> SplitPaths {
+    panic!("unsupported")
+}
+
+impl<'a> Iterator for SplitPaths<'a> {
+    type Item = PathBuf;
+    fn next(&mut self) -> Option<PathBuf> {
+        match *self.0 {}
+    }
+}
+
+#[derive(Debug)]
+pub struct JoinPathsError;
+
+pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
+    where I: Iterator<Item=T>, T: AsRef<OsStr>
+{
+    Err(JoinPathsError)
+}
+
+impl fmt::Display for JoinPathsError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "not supported on wasm yet".fmt(f)
+    }
+}
+
+impl StdError for JoinPathsError {
+    fn description(&self) -> &str {
+        "not supported on wasm yet"
+    }
+}
+
+pub fn current_exe() -> io::Result<PathBuf> {
+    unsupported()
+}
+
+pub struct Env(Void);
+
+impl Iterator for Env {
+    type Item = (OsString, OsString);
+    fn next(&mut self) -> Option<(OsString, OsString)> {
+        match self.0 {}
+    }
+}
+
+pub fn env() -> Env {
+    panic!("not supported on web assembly")
+}
+
+pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> {
+    // If we're debugging the runtime then we actually probe node.js to ask for
+    // the value of environment variables to help provide inputs to programs.
+    // The `extern` shims here are defined in `src/etc/wasm32-shim.js` and are
+    // intended for debugging only, you should not rely on them.
+    if !super::DEBUG {
+        return Ok(None)
+    }
+
+    extern {
+        fn rust_wasm_getenv_len(k: *const u8, kl: usize) -> isize;
+        fn rust_wasm_getenv_data(k: *const u8, kl: usize, v: *mut u8);
+    }
+    unsafe {
+        let k: &[u8] = mem::transmute(k);
+        let n = rust_wasm_getenv_len(k.as_ptr(), k.len());
+        if n == -1 {
+            return Ok(None)
+        }
+        let mut data = vec![0; n as usize];
+        rust_wasm_getenv_data(k.as_ptr(), k.len(), data.as_mut_ptr());
+        Ok(Some(mem::transmute(data)))
+    }
+}
+
+pub fn setenv(_k: &OsStr, _v: &OsStr) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn unsetenv(_n: &OsStr) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn temp_dir() -> PathBuf {
+    panic!("no filesystem on wasm")
+}
+
+pub fn home_dir() -> Option<PathBuf> {
+    None
+}
+
+pub fn exit(_code: i32) -> ! {
+    unsafe { intrinsics::abort() }
+}
+
+pub fn getpid() -> u32 {
+    panic!("no pids on wasm")
+}
diff --git a/src/libstd/sys/wasm/os_str.rs b/src/libstd/sys/wasm/os_str.rs
new file mode 100644
index 00000000000..0e64b5bc6b8
--- /dev/null
+++ b/src/libstd/sys/wasm/os_str.rs
@@ -0,0 +1,183 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// The underlying OsString/OsStr implementation on Unix systems: just
+/// a `Vec<u8>`/`[u8]`.
+
+use borrow::Cow;
+use fmt;
+use str;
+use mem;
+use rc::Rc;
+use sync::Arc;
+use sys_common::{AsInner, IntoInner};
+use std_unicode::lossy::Utf8Lossy;
+
+#[derive(Clone, Hash)]
+pub struct Buf {
+    pub inner: Vec<u8>
+}
+
+pub struct Slice {
+    pub inner: [u8]
+}
+
+impl fmt::Debug for Slice {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter)
+    }
+}
+
+impl fmt::Display for Slice {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter)
+    }
+}
+
+impl fmt::Debug for Buf {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(self.as_slice(), formatter)
+    }
+}
+
+impl fmt::Display for Buf {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(self.as_slice(), formatter)
+    }
+}
+
+impl IntoInner<Vec<u8>> for Buf {
+    fn into_inner(self) -> Vec<u8> {
+        self.inner
+    }
+}
+
+impl AsInner<[u8]> for Buf {
+    fn as_inner(&self) -> &[u8] {
+        &self.inner
+    }
+}
+
+
+impl Buf {
+    pub fn from_string(s: String) -> Buf {
+        Buf { inner: s.into_bytes() }
+    }
+
+    #[inline]
+    pub fn with_capacity(capacity: usize) -> Buf {
+        Buf {
+            inner: Vec::with_capacity(capacity)
+        }
+    }
+
+    #[inline]
+    pub fn clear(&mut self) {
+        self.inner.clear()
+    }
+
+    #[inline]
+    pub fn capacity(&self) -> usize {
+        self.inner.capacity()
+    }
+
+    #[inline]
+    pub fn reserve(&mut self, additional: usize) {
+        self.inner.reserve(additional)
+    }
+
+    #[inline]
+    pub fn reserve_exact(&mut self, additional: usize) {
+        self.inner.reserve_exact(additional)
+    }
+
+    #[inline]
+    pub fn shrink_to_fit(&mut self) {
+        self.inner.shrink_to_fit()
+    }
+
+    pub fn as_slice(&self) -> &Slice {
+        unsafe { mem::transmute(&*self.inner) }
+    }
+
+    pub fn into_string(self) -> Result<String, Buf> {
+        String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() } )
+    }
+
+    pub fn push_slice(&mut self, s: &Slice) {
+        self.inner.extend_from_slice(&s.inner)
+    }
+
+    #[inline]
+    pub fn into_box(self) -> Box<Slice> {
+        unsafe { mem::transmute(self.inner.into_boxed_slice()) }
+    }
+
+    #[inline]
+    pub fn from_box(boxed: Box<Slice>) -> Buf {
+        let inner: Box<[u8]> = unsafe { mem::transmute(boxed) };
+        Buf { inner: inner.into_vec() }
+    }
+
+    #[inline]
+    pub fn into_arc(&self) -> Arc<Slice> {
+        self.as_slice().into_arc()
+    }
+
+    #[inline]
+    pub fn into_rc(&self) -> Rc<Slice> {
+        self.as_slice().into_rc()
+    }
+}
+
+impl Slice {
+    fn from_u8_slice(s: &[u8]) -> &Slice {
+        unsafe { mem::transmute(s) }
+    }
+
+    pub fn from_str(s: &str) -> &Slice {
+        Slice::from_u8_slice(s.as_bytes())
+    }
+
+    pub fn to_str(&self) -> Option<&str> {
+        str::from_utf8(&self.inner).ok()
+    }
+
+    pub fn to_string_lossy(&self) -> Cow<str> {
+        String::from_utf8_lossy(&self.inner)
+    }
+
+    pub fn to_owned(&self) -> Buf {
+        Buf { inner: self.inner.to_vec() }
+    }
+
+    #[inline]
+    pub fn into_box(&self) -> Box<Slice> {
+        let boxed: Box<[u8]> = self.inner.into();
+        unsafe { mem::transmute(boxed) }
+    }
+
+    pub fn empty_box() -> Box<Slice> {
+        let boxed: Box<[u8]> = Default::default();
+        unsafe { mem::transmute(boxed) }
+    }
+
+    #[inline]
+    pub fn into_arc(&self) -> Arc<Slice> {
+        let arc: Arc<[u8]> = Arc::from(&self.inner);
+        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) }
+    }
+
+    #[inline]
+    pub fn into_rc(&self) -> Rc<Slice> {
+        let rc: Rc<[u8]> = Rc::from(&self.inner);
+        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
+    }
+}
diff --git a/src/libstd/sys/wasm/path.rs b/src/libstd/sys/wasm/path.rs
new file mode 100644
index 00000000000..395b8c1e40e
--- /dev/null
+++ b/src/libstd/sys/wasm/path.rs
@@ -0,0 +1,29 @@
+// Copyright 2017 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/wasm/pipe.rs b/src/libstd/sys/wasm/pipe.rs
new file mode 100644
index 00000000000..992e1ac409c
--- /dev/null
+++ b/src/libstd/sys/wasm/pipe.rs
@@ -0,0 +1,35 @@
+// Copyright 2017 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 io;
+use sys::Void;
+
+pub struct AnonPipe(Void);
+
+impl AnonPipe {
+    pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn diverge(&self) -> ! {
+        match self.0 {}
+    }
+}
+
+pub fn read2(p1: AnonPipe,
+             _v1: &mut Vec<u8>,
+             _p2: AnonPipe,
+             _v2: &mut Vec<u8>) -> io::Result<()> {
+    match p1.0 {}
+}
diff --git a/src/libstd/sys/wasm/process.rs b/src/libstd/sys/wasm/process.rs
new file mode 100644
index 00000000000..4febe8a1463
--- /dev/null
+++ b/src/libstd/sys/wasm/process.rs
@@ -0,0 +1,151 @@
+// Copyright 2017 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 ffi::OsStr;
+use fmt;
+use io;
+use sys::fs::File;
+use sys::pipe::AnonPipe;
+use sys::{unsupported, Void};
+
+////////////////////////////////////////////////////////////////////////////////
+// Command
+////////////////////////////////////////////////////////////////////////////////
+
+pub struct Command {
+}
+
+// passed back to std::process with the pipes connected to the child, if any
+// were requested
+pub struct StdioPipes {
+    pub stdin: Option<AnonPipe>,
+    pub stdout: Option<AnonPipe>,
+    pub stderr: Option<AnonPipe>,
+}
+
+pub enum Stdio {
+    Inherit,
+    Null,
+    MakePipe,
+}
+
+impl Command {
+    pub fn new(_program: &OsStr) -> Command {
+        Command {}
+    }
+
+    pub fn arg(&mut self, _arg: &OsStr) {
+    }
+
+    pub fn env(&mut self, _key: &OsStr, _val: &OsStr) {
+    }
+
+    pub fn env_remove(&mut self, _key: &OsStr) {
+    }
+
+    pub fn env_clear(&mut self) {
+    }
+
+    pub fn cwd(&mut self, _dir: &OsStr) {
+    }
+
+    pub fn stdin(&mut self, _stdin: Stdio) {
+    }
+
+    pub fn stdout(&mut self, _stdout: Stdio) {
+    }
+
+    pub fn stderr(&mut self, _stderr: Stdio) {
+    }
+
+    pub fn spawn(&mut self, _default: Stdio, _needs_stdin: bool)
+        -> io::Result<(Process, StdioPipes)> {
+        unsupported()
+    }
+}
+
+impl From<AnonPipe> for Stdio {
+    fn from(pipe: AnonPipe) -> Stdio {
+        pipe.diverge()
+    }
+}
+
+impl From<File> for Stdio {
+    fn from(file: File) -> Stdio {
+        file.diverge()
+    }
+}
+
+impl fmt::Debug for Command {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        Ok(())
+    }
+}
+
+pub struct ExitStatus(Void);
+
+impl ExitStatus {
+    pub fn success(&self) -> bool {
+        match self.0 {}
+    }
+
+    pub fn code(&self) -> Option<i32> {
+        match self.0 {}
+    }
+}
+
+impl Clone for ExitStatus {
+    fn clone(&self) -> ExitStatus {
+        match self.0 {}
+    }
+}
+
+impl Copy for ExitStatus {}
+
+impl PartialEq for ExitStatus {
+    fn eq(&self, _other: &ExitStatus) -> bool {
+        match self.0 {}
+    }
+}
+
+impl Eq for ExitStatus {
+}
+
+impl fmt::Debug for ExitStatus {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        match self.0 {}
+    }
+}
+
+impl fmt::Display for ExitStatus {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        match self.0 {}
+    }
+}
+
+pub struct Process(Void);
+
+impl Process {
+    pub fn id(&self) -> u32 {
+        match self.0 {}
+    }
+
+    pub fn kill(&mut self) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn wait(&mut self) -> io::Result<ExitStatus> {
+        match self.0 {}
+    }
+
+    pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
+        match self.0 {}
+    }
+}
diff --git a/src/libstd/sys/wasm/rwlock.rs b/src/libstd/sys/wasm/rwlock.rs
new file mode 100644
index 00000000000..8b06f541674
--- /dev/null
+++ b/src/libstd/sys/wasm/rwlock.rs
@@ -0,0 +1,82 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use cell::UnsafeCell;
+
+pub struct RWLock {
+    mode: UnsafeCell<isize>,
+}
+
+unsafe impl Send for RWLock {}
+unsafe impl Sync for RWLock {} // no threads on wasm
+
+impl RWLock {
+    pub const fn new() -> RWLock {
+        RWLock {
+            mode: UnsafeCell::new(0),
+        }
+    }
+
+    #[inline]
+    pub unsafe fn read(&self) {
+        let mode = self.mode.get();
+        if *mode >= 0 {
+            *mode += 1;
+        } else {
+            panic!("rwlock locked for writing");
+        }
+    }
+
+    #[inline]
+    pub unsafe fn try_read(&self) -> bool {
+        let mode = self.mode.get();
+        if *mode >= 0 {
+            *mode += 1;
+            true
+        } else {
+            false
+        }
+    }
+
+    #[inline]
+    pub unsafe fn write(&self) {
+        let mode = self.mode.get();
+        if *mode == 0 {
+            *mode = -1;
+        } else {
+            panic!("rwlock locked for reading")
+        }
+    }
+
+    #[inline]
+    pub unsafe fn try_write(&self) -> bool {
+        let mode = self.mode.get();
+        if *mode == 0 {
+            *mode = -1;
+            true
+        } else {
+            false
+        }
+    }
+
+    #[inline]
+    pub unsafe fn read_unlock(&self) {
+        *self.mode.get() -= 1;
+    }
+
+    #[inline]
+    pub unsafe fn write_unlock(&self) {
+        *self.mode.get() += 1;
+    }
+
+    #[inline]
+    pub unsafe fn destroy(&self) {
+    }
+}
diff --git a/src/libstd/sys/wasm/stack_overflow.rs b/src/libstd/sys/wasm/stack_overflow.rs
new file mode 100644
index 00000000000..bed274142f1
--- /dev/null
+++ b/src/libstd/sys/wasm/stack_overflow.rs
@@ -0,0 +1,23 @@
+// Copyright 2017 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 struct Handler;
+
+impl Handler {
+    pub unsafe fn new() -> Handler {
+        Handler
+    }
+}
+
+pub unsafe fn init() {
+}
+
+pub unsafe fn cleanup() {
+}
diff --git a/src/libstd/sys/wasm/stdio.rs b/src/libstd/sys/wasm/stdio.rs
new file mode 100644
index 00000000000..0f75f240251
--- /dev/null
+++ b/src/libstd/sys/wasm/stdio.rs
@@ -0,0 +1,92 @@
+// Copyright 2017 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 io;
+use sys::{Void, unsupported};
+
+pub struct Stdin(Void);
+pub struct Stdout;
+pub struct Stderr;
+
+impl Stdin {
+    pub fn new() -> io::Result<Stdin> {
+        unsupported()
+    }
+
+    pub fn read(&self, _data: &mut [u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+}
+
+impl Stdout {
+    pub fn new() -> io::Result<Stdout> {
+        Ok(Stdout)
+    }
+
+    pub fn write(&self, data: &[u8]) -> io::Result<usize> {
+        // If runtime debugging is enabled at compile time we'll invoke some
+        // runtime functions that are defined in our src/etc/wasm32-shim.js
+        // debugging script. Note that this ffi function call is intended
+        // *purely* for debugging only and should not be relied upon.
+        if !super::DEBUG {
+            return unsupported()
+        }
+        extern {
+            fn rust_wasm_write_stdout(data: *const u8, len: usize);
+        }
+        unsafe {
+            rust_wasm_write_stdout(data.as_ptr(), data.len())
+        }
+        Ok(data.len())
+    }
+
+    pub fn flush(&self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+impl Stderr {
+    pub fn new() -> io::Result<Stderr> {
+        Ok(Stderr)
+    }
+
+    pub fn write(&self, data: &[u8]) -> io::Result<usize> {
+        // See comments in stdout for what's going on here.
+        if !super::DEBUG {
+            return unsupported()
+        }
+        extern {
+            fn rust_wasm_write_stderr(data: *const u8, len: usize);
+        }
+        unsafe {
+            rust_wasm_write_stderr(data.as_ptr(), data.len())
+        }
+        Ok(data.len())
+    }
+
+    pub fn flush(&self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+impl io::Write for Stderr {
+    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
+        (&*self).write(data)
+    }
+    fn flush(&mut self) -> io::Result<()> {
+        (&*self).flush()
+    }
+}
+
+pub const STDIN_BUF_SIZE: usize = 0;
+
+pub fn is_ebadf(_err: &io::Error) -> bool {
+    true
+}
diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs
new file mode 100644
index 00000000000..13980e0cc19
--- /dev/null
+++ b/src/libstd/sys/wasm/thread.rs
@@ -0,0 +1,48 @@
+// Copyright 2017 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 alloc::boxed::FnBox;
+use ffi::CStr;
+use io;
+use sys::{unsupported, Void};
+use time::Duration;
+
+pub struct Thread(Void);
+
+pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
+
+impl Thread {
+    pub unsafe fn new<'a>(_stack: usize, _p: Box<FnBox() + 'a>)
+        -> io::Result<Thread>
+    {
+        unsupported()
+    }
+
+    pub fn yield_now() {
+        // do nothing
+    }
+
+    pub fn set_name(_name: &CStr) {
+        // nope
+    }
+
+    pub fn sleep(_dur: Duration) {
+        panic!("can't sleep");
+    }
+
+    pub fn join(self) {
+        match self.0 {}
+    }
+}
+
+pub mod guard {
+    pub unsafe fn current() -> Option<usize> { None }
+    pub unsafe fn init() -> Option<usize> { None }
+}
diff --git a/src/libstd/sys/wasm/thread_local.rs b/src/libstd/sys/wasm/thread_local.rs
new file mode 100644
index 00000000000..442dd3302a0
--- /dev/null
+++ b/src/libstd/sys/wasm/thread_local.rs
@@ -0,0 +1,50 @@
+// Copyright 2017 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 boxed::Box;
+use ptr;
+
+pub type Key = usize;
+
+struct Allocated {
+    value: *mut u8,
+    dtor: Option<unsafe extern fn(*mut u8)>,
+}
+
+#[inline]
+pub unsafe fn create(dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
+    Box::into_raw(Box::new(Allocated {
+        value: ptr::null_mut(),
+        dtor,
+    })) as usize
+}
+
+#[inline]
+pub unsafe fn set(key: Key, value: *mut u8) {
+    (*(key as *mut Allocated)).value = value;
+}
+
+#[inline]
+pub unsafe fn get(key: Key) -> *mut u8 {
+    (*(key as *mut Allocated)).value
+}
+
+#[inline]
+pub unsafe fn destroy(key: Key) {
+    let key = Box::from_raw(key as *mut Allocated);
+    if let Some(f) = key.dtor {
+        f(key.value);
+    }
+}
+
+#[inline]
+pub fn requires_synchronized_create() -> bool {
+    false
+}
diff --git a/src/libstd/sys/wasm/time.rs b/src/libstd/sys/wasm/time.rs
new file mode 100644
index 00000000000..7907720e4da
--- /dev/null
+++ b/src/libstd/sys/wasm/time.rs
@@ -0,0 +1,63 @@
+// Copyright 2017 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 fmt;
+use time::Duration;
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
+pub struct Instant;
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub struct SystemTime;
+
+pub const UNIX_EPOCH: SystemTime = SystemTime;
+
+impl Instant {
+    pub fn now() -> Instant {
+        panic!("not supported on web assembly");
+    }
+
+    pub fn sub_instant(&self, _other: &Instant) -> Duration {
+        panic!("can't sub yet");
+    }
+
+    pub fn add_duration(&self, _other: &Duration) -> Instant {
+        panic!("can't add yet");
+    }
+
+    pub fn sub_duration(&self, _other: &Duration) -> Instant {
+        panic!("can't sub yet");
+    }
+}
+
+impl SystemTime {
+    pub fn now() -> SystemTime {
+        panic!("not supported on web assembly");
+    }
+
+    pub fn sub_time(&self, _other: &SystemTime)
+                    -> Result<Duration, Duration> {
+        panic!()
+    }
+
+    pub fn add_duration(&self, _other: &Duration) -> SystemTime {
+        panic!()
+    }
+
+    pub fn sub_duration(&self, _other: &Duration) -> SystemTime {
+        panic!()
+    }
+}
+
+impl fmt::Debug for SystemTime {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        panic!()
+    }
+}
diff --git a/src/libstd/sys/windows/backtrace/mod.rs b/src/libstd/sys/windows/backtrace/mod.rs
index 26b4cb90e0a..176891fff23 100644
--- a/src/libstd/sys/windows/backtrace/mod.rs
+++ b/src/libstd/sys/windows/backtrace/mod.rs
@@ -95,8 +95,8 @@ pub fn unwind_backtrace(frames: &mut [Frame])
                frame.AddrReturn.Offset == 0 { break }
 
             frames[i] = Frame {
-                symbol_addr: (addr - 1) as *const c_void,
-                exact_position: (addr - 1) as *const c_void,
+                symbol_addr: (addr - 1) as *const u8,
+                exact_position: (addr - 1) as *const u8,
             };
             i += 1;
         }
diff --git a/src/libstd/sys/windows/backtrace/printing/msvc.rs b/src/libstd/sys/windows/backtrace/printing/msvc.rs
index 3107d784324..5a49b77af8e 100644
--- a/src/libstd/sys/windows/backtrace/printing/msvc.rs
+++ b/src/libstd/sys/windows/backtrace/printing/msvc.rs
@@ -10,7 +10,7 @@
 
 use ffi::CStr;
 use io;
-use libc::{c_ulong, c_int, c_char};
+use libc::{c_ulong, c_char};
 use mem;
 use sys::c;
 use sys::backtrace::BacktraceContext;
@@ -59,7 +59,7 @@ pub fn foreach_symbol_fileline<F>(frame: Frame,
                                   mut f: F,
                                   context: &BacktraceContext)
     -> io::Result<bool>
-    where F: FnMut(&[u8], c_int) -> io::Result<()>
+    where F: FnMut(&[u8], u32) -> io::Result<()>
 {
     let SymGetLineFromAddr64 = sym!(&context.dbghelp,
                                     "SymGetLineFromAddr64",
@@ -76,7 +76,7 @@ pub fn foreach_symbol_fileline<F>(frame: Frame,
                                        &mut line);
         if ret == c::TRUE {
             let name = CStr::from_ptr(line.Filename).to_bytes();
-            f(name, line.LineNumber as c_int)?;
+            f(name, line.LineNumber as u32)?;
         }
         Ok(false)
     }
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index 9535ddfe5ca..6e0cccff001 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -37,7 +37,6 @@ pub type BOOL = c_int;
 pub type BYTE = u8;
 pub type BOOLEAN = BYTE;
 pub type GROUP = c_uint;
-pub type LONG_PTR = isize;
 pub type LARGE_INTEGER = c_longlong;
 pub type LONG = c_long;
 pub type UINT = c_uint;
@@ -46,7 +45,6 @@ pub type USHORT = c_ushort;
 pub type SIZE_T = usize;
 pub type WORD = u16;
 pub type CHAR = c_char;
-pub type HCRYPTPROV = LONG_PTR;
 pub type ULONG_PTR = usize;
 pub type ULONG = c_ulong;
 #[cfg(target_arch = "x86_64")]
@@ -279,16 +277,15 @@ pub const WAIT_TIMEOUT: DWORD = 258;
 pub const WAIT_FAILED: DWORD = 0xFFFFFFFF;
 
 #[cfg(target_env = "msvc")]
+#[cfg(feature = "backtrace")]
 pub const MAX_SYM_NAME: usize = 2000;
 #[cfg(target_arch = "x86")]
+#[cfg(feature = "backtrace")]
 pub const IMAGE_FILE_MACHINE_I386: DWORD = 0x014c;
 #[cfg(target_arch = "x86_64")]
+#[cfg(feature = "backtrace")]
 pub const IMAGE_FILE_MACHINE_AMD64: DWORD = 0x8664;
 
-pub const PROV_RSA_FULL: DWORD = 1;
-pub const CRYPT_SILENT: DWORD = 64;
-pub const CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;
-
 pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
 pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
 pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15;
@@ -575,6 +572,7 @@ pub struct OVERLAPPED {
 
 #[repr(C)]
 #[cfg(target_env = "msvc")]
+#[cfg(feature = "backtrace")]
 pub struct SYMBOL_INFO {
     pub SizeOfStruct: c_ulong,
     pub TypeIndex: c_ulong,
@@ -598,6 +596,7 @@ pub struct SYMBOL_INFO {
 
 #[repr(C)]
 #[cfg(target_env = "msvc")]
+#[cfg(feature = "backtrace")]
 pub struct IMAGEHLP_LINE64 {
     pub SizeOfStruct: u32,
     pub Key: *const c_void,
@@ -616,6 +615,7 @@ pub enum ADDRESS_MODE {
 }
 
 #[repr(C)]
+#[cfg(feature = "backtrace")]
 pub struct ADDRESS64 {
     pub Offset: u64,
     pub Segment: u16,
@@ -623,6 +623,7 @@ pub struct ADDRESS64 {
 }
 
 #[repr(C)]
+#[cfg(feature = "backtrace")]
 pub struct STACKFRAME64 {
     pub AddrPC: ADDRESS64,
     pub AddrReturn: ADDRESS64,
@@ -638,6 +639,7 @@ pub struct STACKFRAME64 {
 }
 
 #[repr(C)]
+#[cfg(feature = "backtrace")]
 pub struct KDHELP64 {
     pub Thread: u64,
     pub ThCallbackStack: DWORD,
@@ -1089,6 +1091,7 @@ extern "system" {
     pub fn FindNextFileW(findFile: HANDLE, findFileData: LPWIN32_FIND_DATAW)
                          -> BOOL;
     pub fn FindClose(findFile: HANDLE) -> BOOL;
+    #[cfg(feature = "backtrace")]
     pub fn RtlCaptureContext(ctx: *mut CONTEXT);
     pub fn getsockopt(s: SOCKET,
                       level: c_int,
@@ -1120,20 +1123,13 @@ extern "system" {
                        res: *mut *mut ADDRINFOA) -> c_int;
     pub fn freeaddrinfo(res: *mut ADDRINFOA);
 
+    #[cfg(feature = "backtrace")]
     pub fn LoadLibraryW(name: LPCWSTR) -> HMODULE;
+    #[cfg(feature = "backtrace")]
     pub fn FreeLibrary(handle: HMODULE) -> BOOL;
     pub fn GetProcAddress(handle: HMODULE,
                           name: LPCSTR) -> *mut c_void;
     pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
-    pub fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
-                                pszContainer: LPCSTR,
-                                pszProvider: LPCSTR,
-                                dwProvType: DWORD,
-                                dwFlags: DWORD) -> BOOL;
-    pub fn CryptGenRandom(hProv: HCRYPTPROV,
-                          dwLen: DWORD,
-                          pbBuffer: *mut BYTE) -> BOOL;
-    pub fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
 
     pub fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: LPFILETIME);
 
@@ -1164,6 +1160,9 @@ extern "system" {
                   writefds: *mut fd_set,
                   exceptfds: *mut fd_set,
                   timeout: *const timeval) -> c_int;
+
+    #[link_name = "SystemFunction036"]
+    pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN;
 }
 
 // Functions that aren't available on every version of Windows that we support,
@@ -1229,7 +1228,7 @@ compat_fn! {
     }
 }
 
-#[cfg(target_env = "gnu")]
+#[cfg(all(target_env = "gnu", feature = "backtrace"))]
 mod gnu {
     use super::*;
 
@@ -1257,5 +1256,5 @@ mod gnu {
     }
 }
 
-#[cfg(target_env = "gnu")]
+#[cfg(all(target_env = "gnu", feature = "backtrace"))]
 pub use self::gnu::*;
diff --git a/src/libstd/sys/windows/cmath.rs b/src/libstd/sys/windows/cmath.rs
new file mode 100644
index 00000000000..b665a2c9ba4
--- /dev/null
+++ b/src/libstd/sys/windows/cmath.rs
@@ -0,0 +1,103 @@
+// Copyright 2017 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(not(test))]
+
+use libc::{c_float, c_double};
+
+#[link_name = "m"]
+extern {
+    pub fn acos(n: c_double) -> c_double;
+    pub fn asin(n: c_double) -> c_double;
+    pub fn atan(n: c_double) -> c_double;
+    pub fn atan2(a: c_double, b: c_double) -> c_double;
+    pub fn cbrt(n: c_double) -> c_double;
+    pub fn cbrtf(n: c_float) -> c_float;
+    pub fn cosh(n: c_double) -> c_double;
+    pub fn expm1(n: c_double) -> c_double;
+    pub fn expm1f(n: c_float) -> c_float;
+    pub fn fdim(a: c_double, b: c_double) -> c_double;
+    pub fn fdimf(a: c_float, b: c_float) -> c_float;
+    #[cfg_attr(target_env = "msvc", link_name = "_hypot")]
+    pub fn hypot(x: c_double, y: c_double) -> c_double;
+    #[cfg_attr(target_env = "msvc", link_name = "_hypotf")]
+    pub fn hypotf(x: c_float, y: c_float) -> c_float;
+    pub fn log1p(n: c_double) -> c_double;
+    pub fn log1pf(n: c_float) -> c_float;
+    pub fn sinh(n: c_double) -> c_double;
+    pub fn tan(n: c_double) -> c_double;
+    pub fn tanh(n: c_double) -> c_double;
+}
+
+pub use self::shims::*;
+
+#[cfg(not(target_env = "msvc"))]
+mod shims {
+    use libc::c_float;
+
+    extern {
+        pub fn acosf(n: c_float) -> c_float;
+        pub fn asinf(n: c_float) -> c_float;
+        pub fn atan2f(a: c_float, b: c_float) -> c_float;
+        pub fn atanf(n: c_float) -> c_float;
+        pub fn coshf(n: c_float) -> c_float;
+        pub fn sinhf(n: c_float) -> c_float;
+        pub fn tanf(n: c_float) -> c_float;
+        pub fn tanhf(n: c_float) -> c_float;
+    }
+}
+
+// On MSVC these functions aren't defined, so we just define shims which promote
+// everything fo f64, perform the calculation, and then demote back to f32.
+// While not precisely correct should be "correct enough" for now.
+#[cfg(target_env = "msvc")]
+mod shims {
+    use libc::c_float;
+
+    #[inline]
+    pub unsafe fn acosf(n: c_float) -> c_float {
+        f64::acos(n as f64) as c_float
+    }
+
+    #[inline]
+    pub unsafe fn asinf(n: c_float) -> c_float {
+        f64::asin(n as f64) as c_float
+    }
+
+    #[inline]
+    pub unsafe fn atan2f(n: c_float, b: c_float) -> c_float {
+        f64::atan2(n as f64, b as f64) as c_float
+    }
+
+    #[inline]
+    pub unsafe fn atanf(n: c_float) -> c_float {
+        f64::atan(n as f64) as c_float
+    }
+
+    #[inline]
+    pub unsafe fn coshf(n: c_float) -> c_float {
+        f64::cosh(n as f64) as c_float
+    }
+
+    #[inline]
+    pub unsafe fn sinhf(n: c_float) -> c_float {
+        f64::sinh(n as f64) as c_float
+    }
+
+    #[inline]
+    pub unsafe fn tanf(n: c_float) -> c_float {
+        f64::tan(n as f64) as c_float
+    }
+
+    #[inline]
+    pub unsafe fn tanhf(n: c_float) -> c_float {
+        f64::tanh(n as f64) as c_float
+    }
+}
diff --git a/src/libstd/sys/windows/ext/ffi.rs b/src/libstd/sys/windows/ext/ffi.rs
index 3f6c2827a3f..d6b8896ac09 100644
--- a/src/libstd/sys/windows/ext/ffi.rs
+++ b/src/libstd/sys/windows/ext/ffi.rs
@@ -9,6 +9,62 @@
 // except according to those terms.
 
 //! Windows-specific extensions to the primitives in the `std::ffi` module.
+//!
+//! # Overview
+//!
+//! For historical reasons, the Windows API uses a form of potentially
+//! ill-formed UTF-16 encoding for strings.  Specifically, the 16-bit
+//! code units in Windows strings may contain [isolated surrogate code
+//! points which are not paired together][ill-formed-utf-16].  The
+//! Unicode standard requires that surrogate code points (those in the
+//! range U+D800 to U+DFFF) always be *paired*, because in the UTF-16
+//! encoding a *surrogate code unit pair* is used to encode a single
+//! character.  For compatibility with code that does not enforce
+//! these pairings, Windows does not enforce them, either.
+//!
+//! While it is not always possible to convert such a string losslessly into
+//! a valid UTF-16 string (or even UTF-8), it is often desirable to be
+//! able to round-trip such a string from and to Windows APIs
+//! losslessly.  For example, some Rust code may be "bridging" some
+//! Windows APIs together, just passing `WCHAR` strings among those
+//! APIs without ever really looking into the strings.
+//!
+//! If Rust code *does* need to look into those strings, it can
+//! convert them to valid UTF-8, possibly lossily, by substituting
+//! invalid sequences with U+FFFD REPLACEMENT CHARACTER, as is
+//! conventionally done in other Rust APIs that deal with string
+//! encodings.
+//!
+//! # `OsStringExt` and `OsStrExt`
+//!
+//! [`OsString`] is the Rust wrapper for owned strings in the
+//! preferred representation of the operating system.  On Windows,
+//! this struct gets augmented with an implementation of the
+//! [`OsStringExt`] trait, which has a [`from_wide`] method.  This
+//! lets you create an [`OsString`] from a `&[u16]` slice; presumably
+//! you get such a slice out of a `WCHAR` Windows API.
+//!
+//! Similarly, [`OsStr`] is the Rust wrapper for borrowed strings from
+//! preferred representation of the operating system.  On Windows, the
+//! [`OsStrExt`] trait provides the [`encode_wide`] method, which
+//! outputs an [`EncodeWide`] iterator.  You can [`collect`] this
+//! iterator, for example, to obtain a `Vec<u16>`; you can later get a
+//! pointer to this vector's contents and feed it to Windows APIs.
+//!
+//! These traits, along with [`OsString`] and [`OsStr`], work in
+//! conjunction so that it is possible to **round-trip** strings from
+//! Windows and back, with no loss of data, even if the strings are
+//! ill-formed UTF-16.
+//!
+//! [ill-formed-utf-16]: https://simonsapin.github.io/wtf-8/#ill-formed-utf-16
+//! [`OsString`]: ../../../ffi/struct.OsString.html
+//! [`OsStr`]: ../../../ffi/struct.OsStr.html
+//! [`OsStringExt`]: trait.OsStringExt.html
+//! [`OsStrExt`]: trait.OsStrExt.html
+//! [`EncodeWide`]: struct.EncodeWide.html
+//! [`from_wide`]: trait.OsStringExt.html#tymethod.from_wide
+//! [`encode_wide`]: trait.OsStrExt.html#tymethod.encode_wide
+//! [`collect`]: ../../../iter/trait.Iterator.html#method.collect
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs
index d58a3505154..24c41046f26 100644
--- a/src/libstd/sys/windows/ext/fs.rs
+++ b/src/libstd/sys/windows/ext/fs.rs
@@ -32,7 +32,7 @@ pub trait FileExt {
     /// 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.
+    /// 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
@@ -393,8 +393,8 @@ pub trait MetadataExt {
     /// to. For a directory, the structure specifies when the directory was
     /// created.
     ///
-    /// If the underlying filesystem does not support the last write time
-    /// time, the returned value is 0.
+    /// If the underlying filesystem does not support the last write time,
+    /// the returned value is 0.
     ///
     /// # Examples
     ///
diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs
index f2487c1b0bd..ae9535139d9 100644
--- a/src/libstd/sys/windows/fs.rs
+++ b/src/libstd/sys/windows/fs.rs
@@ -722,16 +722,16 @@ pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
     unsafe extern "system" fn callback(
         _TotalFileSize: c::LARGE_INTEGER,
-        TotalBytesTransferred: c::LARGE_INTEGER,
+        _TotalBytesTransferred: c::LARGE_INTEGER,
         _StreamSize: c::LARGE_INTEGER,
-        _StreamBytesTransferred: c::LARGE_INTEGER,
-        _dwStreamNumber: c::DWORD,
+        StreamBytesTransferred: c::LARGE_INTEGER,
+        dwStreamNumber: c::DWORD,
         _dwCallbackReason: c::DWORD,
         _hSourceFile: c::HANDLE,
         _hDestinationFile: c::HANDLE,
         lpData: c::LPVOID,
     ) -> c::DWORD {
-        *(lpData as *mut i64) = TotalBytesTransferred;
+        if dwStreamNumber == 1 {*(lpData as *mut i64) = StreamBytesTransferred;}
         c::PROGRESS_CONTINUE
     }
     let pfrom = to_u16s(from)?;
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs
index ee58efc5144..0d12ecf8fe3 100644
--- a/src/libstd/sys/windows/mod.rs
+++ b/src/libstd/sys/windows/mod.rs
@@ -17,12 +17,18 @@ use os::windows::ffi::{OsStrExt, OsStringExt};
 use path::PathBuf;
 use time::Duration;
 
+pub use libc::strlen;
+pub use self::rand::hashmap_random_keys;
+
 #[macro_use] pub mod compat;
 
 pub mod args;
+#[cfg(feature = "backtrace")]
 pub mod backtrace;
 pub mod c;
+pub mod cmath;
 pub mod condvar;
+#[cfg(feature = "backtrace")]
 pub mod dynamic_lib;
 pub mod env;
 pub mod ext;
diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs
index a51b458451e..b9448243559 100644
--- a/src/libstd/sys/windows/os.rs
+++ b/src/libstd/sys/windows/os.rs
@@ -318,6 +318,10 @@ pub fn exit(code: i32) -> ! {
     unsafe { c::ExitProcess(code as c::UINT) }
 }
 
+pub fn getpid() -> u32 {
+    unsafe { c::GetCurrentProcessId() as u32 }
+}
+
 #[cfg(test)]
 mod tests {
     use io::Error;
diff --git a/src/libstd/sys/windows/os_str.rs b/src/libstd/sys/windows/os_str.rs
index 3eb4582718b..b8d2f7bc53c 100644
--- a/src/libstd/sys/windows/os_str.rs
+++ b/src/libstd/sys/windows/os_str.rs
@@ -15,6 +15,8 @@ use borrow::Cow;
 use fmt;
 use sys_common::wtf8::{Wtf8, Wtf8Buf};
 use mem;
+use rc::Rc;
+use sync::Arc;
 use sys_common::{AsInner, IntoInner};
 
 #[derive(Clone, Hash)]
@@ -115,6 +117,16 @@ impl Buf {
         let inner: Box<Wtf8> = unsafe { mem::transmute(boxed) };
         Buf { inner: Wtf8Buf::from_box(inner) }
     }
+
+    #[inline]
+    pub fn into_arc(&self) -> Arc<Slice> {
+        self.as_slice().into_arc()
+    }
+
+    #[inline]
+    pub fn into_rc(&self) -> Rc<Slice> {
+        self.as_slice().into_rc()
+    }
 }
 
 impl Slice {
@@ -144,4 +156,16 @@ impl Slice {
     pub fn empty_box() -> Box<Slice> {
         unsafe { mem::transmute(Wtf8::empty_box()) }
     }
+
+    #[inline]
+    pub fn into_arc(&self) -> Arc<Slice> {
+        let arc = self.inner.into_arc();
+        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) }
+    }
+
+    #[inline]
+    pub fn into_rc(&self) -> Rc<Slice> {
+        let rc = self.inner.into_rc();
+        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
+    }
 }
diff --git a/src/libstd/sys/windows/path.rs b/src/libstd/sys/windows/path.rs
index 2b47808451b..98d62a0c953 100644
--- a/src/libstd/sys/windows/path.rs
+++ b/src/libstd/sys/windows/path.rs
@@ -8,8 +8,6 @@
 // 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;
diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs
index 452d720ce59..f3b1185c6ea 100644
--- a/src/libstd/sys/windows/pipe.rs
+++ b/src/libstd/sys/windows/pipe.rs
@@ -15,11 +15,13 @@ use io;
 use mem;
 use path::Path;
 use ptr;
-use rand::{self, Rng};
 use slice;
+use sync::atomic::Ordering::SeqCst;
+use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
 use sys::c;
 use sys::fs::{File, OpenOptions};
 use sys::handle::Handle;
+use sys::hashmap_random_keys;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Anonymous pipes
@@ -71,10 +73,9 @@ pub fn anon_pipe(ours_readable: bool) -> io::Result<Pipes> {
         let mut reject_remote_clients_flag = c::PIPE_REJECT_REMOTE_CLIENTS;
         loop {
             tries += 1;
-            let key: u64 = rand::thread_rng().gen();
             name = format!(r"\\.\pipe\__rust_anonymous_pipe1__.{}.{}",
                            c::GetCurrentProcessId(),
-                           key);
+                           random_number());
             let wide_name = OsStr::new(&name)
                                   .encode_wide()
                                   .chain(Some(0))
@@ -156,6 +157,17 @@ pub fn anon_pipe(ours_readable: bool) -> io::Result<Pipes> {
     }
 }
 
+fn random_number() -> usize {
+    static N: AtomicUsize = ATOMIC_USIZE_INIT;
+    loop {
+        if N.load(SeqCst) != 0 {
+            return N.fetch_add(1, SeqCst)
+        }
+
+        N.store(hashmap_random_keys().0 as usize, SeqCst);
+    }
+}
+
 impl AnonPipe {
     pub fn handle(&self) -> &Handle { &self.inner }
     pub fn into_handle(self) -> Handle { self.inner }
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index 0d1766d5aec..631d69b05e1 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ascii::*;
+use ascii::AsciiExt;
 use collections::HashMap;
 use collections;
 use env::split_paths;
diff --git a/src/libstd/sys/windows/rand.rs b/src/libstd/sys/windows/rand.rs
index 10e3d45f9d5..262323656aa 100644
--- a/src/libstd/sys/windows/rand.rs
+++ b/src/libstd/sys/windows/rand.rs
@@ -8,69 +8,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
 use io;
 use mem;
-use rand::Rng;
 use sys::c;
 
-pub struct OsRng {
-    hcryptprov: c::HCRYPTPROV
-}
-
-impl OsRng {
-    /// Create a new `OsRng`.
-    pub fn new() -> io::Result<OsRng> {
-        let mut hcp = 0;
-        let ret = unsafe {
-            c::CryptAcquireContextA(&mut hcp, 0 as c::LPCSTR, 0 as c::LPCSTR,
-                                    c::PROV_RSA_FULL,
-                                    c::CRYPT_VERIFYCONTEXT | c::CRYPT_SILENT)
-        };
-
-        if ret == 0 {
-            Err(io::Error::last_os_error())
-        } else {
-            Ok(OsRng { hcryptprov: hcp })
-        }
-    }
-}
-
-impl Rng for OsRng {
-    fn next_u32(&mut self) -> u32 {
-        let mut v = [0; 4];
-        self.fill_bytes(&mut v);
-        unsafe { mem::transmute(v) }
-    }
-    fn next_u64(&mut self) -> u64 {
-        let mut v = [0; 8];
-        self.fill_bytes(&mut v);
-        unsafe { mem::transmute(v) }
-    }
-    fn fill_bytes(&mut self, v: &mut [u8]) {
-        // CryptGenRandom takes a DWORD (u32) for the length so we need to
-        // split up the buffer.
-        for slice in v.chunks_mut(<c::DWORD>::max_value() as usize) {
-            let ret = unsafe {
-                c::CryptGenRandom(self.hcryptprov, slice.len() as c::DWORD,
-                                  slice.as_mut_ptr())
-            };
-            if ret == 0 {
-                panic!("couldn't generate random bytes: {}",
-                       io::Error::last_os_error());
-            }
-        }
-    }
-}
-
-impl Drop for OsRng {
-    fn drop(&mut self) {
-        let ret = unsafe {
-            c::CryptReleaseContext(self.hcryptprov, 0)
-        };
-        if ret == 0 {
-            panic!("couldn't release context: {}",
-                   io::Error::last_os_error());
-        }
+pub fn hashmap_random_keys() -> (u64, u64) {
+    let mut v = (0, 0);
+    let ret = unsafe {
+        c::RtlGenRandom(&mut v as *mut _ as *mut u8,
+                        mem::size_of_val(&v) as c::ULONG)
+    };
+    if ret == 0 {
+        panic!("couldn't generate random bytes: {}",
+               io::Error::last_os_error());
     }
+    return v
 }
diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs
index b5e5b5760f2..b43df20bddd 100644
--- a/src/libstd/sys/windows/stdio.rs
+++ b/src/libstd/sys/windows/stdio.rs
@@ -218,7 +218,10 @@ fn readconsole_input_control(wakeup_mask: c::ULONG) -> c::CONSOLE_READCONSOLE_CO
 const CTRL_Z: u8 = 0x1A;
 const CTRL_Z_MASK: c::ULONG = 0x4000000; //1 << 0x1A
 
-pub const EBADF_ERR: i32 = ::sys::c::ERROR_INVALID_HANDLE as i32;
+pub fn is_ebadf(err: &io::Error) -> bool {
+    err.raw_os_error() == Some(c::ERROR_INVALID_HANDLE as i32)
+}
+
 // The default buffer capacity is 64k, but apparently windows
 // doesn't like 64k reads on stdin. See #13304 for details, but the
 // idea is that on windows we use a slightly smaller buffer that's
diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs
index c47baaa2434..74786d09285 100644
--- a/src/libstd/sys/windows/thread.rs
+++ b/src/libstd/sys/windows/thread.rs
@@ -52,7 +52,7 @@ impl Thread {
         };
 
         extern "system" fn thread_start(main: *mut c_void) -> c::DWORD {
-            unsafe { start_thread(main); }
+            unsafe { start_thread(main as *mut u8); }
             0
         }
     }
diff --git a/src/libstd/sys/windows/thread_local.rs b/src/libstd/sys/windows/thread_local.rs
index 7ae9ed917bd..cdad320e122 100644
--- a/src/libstd/sys/windows/thread_local.rs
+++ b/src/libstd/sys/windows/thread_local.rs
@@ -200,8 +200,9 @@ unsafe fn register_dtor(key: Key, dtor: Dtor) {
 // the address of the symbol to ensure it sticks around.
 
 #[link_section = ".CRT$XLB"]
-#[linkage = "external"]
 #[allow(dead_code, unused_variables)]
+#[used] // we don't want LLVM eliminating this symbol for any reason, and
+        // when the symbol makes it to the linker the linker will take over
 pub static p_thread_callback: unsafe extern "system" fn(c::LPVOID, c::DWORD,
                                                         c::LPVOID) =
         on_tls_callback;
diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs
index 617218fe7a5..b5cf6d7d34f 100644
--- a/src/libstd/sys_common/backtrace.rs
+++ b/src/libstd/sys_common/backtrace.rs
@@ -8,15 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![cfg_attr(target_os = "nacl", allow(dead_code))]
-
 /// Common code for printing the backtrace in the same way across the different
 /// supported platforms.
 
 use env;
 use io::prelude::*;
 use io;
-use libc;
 use str;
 use sync::atomic::{self, Ordering};
 use path::{self, Path};
@@ -41,9 +38,9 @@ pub const HEX_WIDTH: usize = 10;
 #[derive(Debug, Copy, Clone)]
 pub struct Frame {
     /// Exact address of the call that failed.
-    pub exact_position: *const libc::c_void,
+    pub exact_position: *const u8,
     /// Address of the enclosing function.
-    pub symbol_addr: *const libc::c_void,
+    pub symbol_addr: *const u8,
 }
 
 /// Max number of frames to print.
@@ -203,8 +200,10 @@ fn output(w: &mut Write, idx: usize, frame: Frame,
 ///
 /// See also `output`.
 #[allow(dead_code)]
-fn output_fileline(w: &mut Write, file: &[u8], line: libc::c_int,
-                       format: PrintFormat) -> io::Result<()> {
+fn output_fileline(w: &mut Write,
+                   file: &[u8],
+                   line: u32,
+                   format: PrintFormat) -> io::Result<()> {
     // prior line: "  ##: {:2$} - func"
     w.write_all(b"")?;
     match format {
@@ -253,8 +252,26 @@ fn output_fileline(w: &mut Write, file: &[u8], line: libc::c_int,
 // Note that this demangler isn't quite as fancy as it could be. We have lots
 // of other information in our symbols like hashes, version, type information,
 // etc. Additionally, this doesn't handle glue symbols at all.
-pub fn demangle(writer: &mut Write, s: &str, format: PrintFormat) -> io::Result<()> {
-    // First validate the symbol. If it doesn't look like anything we're
+pub fn demangle(writer: &mut Write, mut s: &str, format: PrintFormat) -> io::Result<()> {
+    // During ThinLTO LLVM may import and rename internal symbols, so strip out
+    // those endings first as they're one of the last manglings applied to
+    // symbol names.
+    let llvm = ".llvm.";
+    if let Some(i) = s.find(llvm) {
+        let candidate = &s[i + llvm.len()..];
+        let all_hex = candidate.chars().all(|c| {
+            match c {
+                'A' ... 'F' | '0' ... '9' => true,
+                _ => false,
+            }
+        });
+
+        if all_hex {
+            s = &s[..i];
+        }
+    }
+
+    // Validate the symbol. If it doesn't look like anything we're
     // expecting, we just print it literally. Note that we must handle non-rust
     // symbols because we could have any function in the backtrace.
     let mut valid = true;
diff --git a/src/libstd/sys_common/gnu/libbacktrace.rs b/src/libstd/sys_common/gnu/libbacktrace.rs
index 016c840d154..75c6bd5d2a2 100644
--- a/src/libstd/sys_common/gnu/libbacktrace.rs
+++ b/src/libstd/sys_common/gnu/libbacktrace.rs
@@ -20,13 +20,13 @@ use sys_common::backtrace::Frame;
 pub fn foreach_symbol_fileline<F>(frame: Frame,
                                   mut f: F,
                                   _: &BacktraceContext) -> io::Result<bool>
-where F: FnMut(&[u8], libc::c_int) -> io::Result<()>
+where F: FnMut(&[u8], u32) -> io::Result<()>
 {
     // pcinfo may return an arbitrary number of file:line pairs,
     // in the order of stack trace (i.e. inlined calls first).
     // in order to avoid allocation, we stack-allocate a fixed size of entries.
     const FILELINE_SIZE: usize = 32;
-    let mut fileline_buf = [(ptr::null(), -1); FILELINE_SIZE];
+    let mut fileline_buf = [(ptr::null(), !0); FILELINE_SIZE];
     let ret;
     let fileline_count = {
         let state = unsafe { init_state() };
@@ -136,7 +136,7 @@ extern {
 // helper callbacks
 ////////////////////////////////////////////////////////////////////////
 
-type FileLine = (*const libc::c_char, libc::c_int);
+type FileLine = (*const libc::c_char, u32);
 
 extern fn error_cb(_data: *mut libc::c_void, _msg: *const libc::c_char,
                    _errnum: libc::c_int) {
@@ -162,7 +162,7 @@ extern fn pcinfo_cb(data: *mut libc::c_void,
         // if the buffer is not full, add file:line to the buffer
         // and adjust the buffer for next possible calls to pcinfo_cb.
         if !buffer.is_empty() {
-            buffer[0] = (filename, lineno);
+            buffer[0] = (filename, lineno as u32);
             unsafe { ptr::write(slot, &mut buffer[1..]); }
         }
     }
diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs
index d7654ce9300..14e5697b94e 100644
--- a/src/libstd/sys_common/mod.rs
+++ b/src/libstd/sys_common/mod.rs
@@ -44,11 +44,15 @@ pub mod thread_local;
 pub mod util;
 pub mod wtf8;
 
-#[cfg(any(target_os = "redox", target_os = "l4re"))]
-pub use sys::net;
-
-#[cfg(not(any(target_os = "redox", target_os = "l4re")))]
-pub mod net;
+cfg_if! {
+    if #[cfg(any(target_os = "redox", target_os = "l4re"))] {
+        pub use sys::net;
+    } else if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] {
+        pub use sys::net;
+    } else {
+        pub mod net;
+    }
+}
 
 #[cfg(feature = "backtrace")]
 #[cfg(any(all(unix, not(target_os = "emscripten")),
diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs
index 19dc841b9b5..c76b0bcf1c9 100644
--- a/src/libstd/sys_common/net.rs
+++ b/src/libstd/sys_common/net.rs
@@ -175,10 +175,15 @@ pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
             },
             #[cfg(unix)]
             Err(e) => {
-                // The lookup failure could be caused by using a stale /etc/resolv.conf.
-                // See https://github.com/rust-lang/rust/issues/41570.
-                // We therefore force a reload of the nameserver information.
-                c::res_init();
+                // If we're running glibc prior to version 2.26, the lookup
+                // failure could be caused by caching a stale /etc/resolv.conf.
+                // We need to call libc::res_init() to clear the cache. But we
+                // shouldn't call it in on any other platform, because other
+                // res_init implementations aren't thread-safe. See
+                // https://github.com/rust-lang/rust/issues/41570 and
+                // https://github.com/rust-lang/rust/issues/43592.
+                use sys::net::res_init_if_glibc_before_2_26;
+                let _ = res_init_if_glibc_before_2_26();
                 Err(e)
             },
             // the cfg is needed here to avoid an "unreachable pattern" warning
diff --git a/src/libstd/sys_common/poison.rs b/src/libstd/sys_common/poison.rs
index 3c61593acc5..934ac3edbf1 100644
--- a/src/libstd/sys_common/poison.rs
+++ b/src/libstd/sys_common/poison.rs
@@ -65,6 +65,31 @@ pub struct Guard {
 /// each lock, but once a lock is poisoned then all future acquisitions will
 /// return this error.
 ///
+/// # Examples
+///
+/// ```
+/// use std::sync::{Arc, Mutex};
+/// use std::thread;
+///
+/// let mutex = Arc::new(Mutex::new(1));
+///
+/// // poison the mutex
+/// let c_mutex = mutex.clone();
+/// let _ = thread::spawn(move || {
+///     let mut data = c_mutex.lock().unwrap();
+///     *data = 2;
+///     panic!();
+/// }).join();
+///
+/// match mutex.lock() {
+///     Ok(_) => unreachable!(),
+///     Err(p_err) => {
+///         let data = p_err.get_ref();
+///         println!("recovered: {}", data);
+///     }
+/// };
+/// ```
+///
 /// [`Mutex`]: ../../std/sync/struct.Mutex.html
 /// [`RwLock`]: ../../std/sync/struct.RwLock.html
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -72,10 +97,16 @@ pub struct PoisonError<T> {
     guard: T,
 }
 
-/// An enumeration of possible errors which can occur while calling the
-/// [`try_lock`] method.
+/// An enumeration of possible errors associated with a [`TryLockResult`] which
+/// can occur while trying to aquire a lock, from the [`try_lock`] method on a
+/// [`Mutex`] or the [`try_read`] and [`try_write`] methods on an [`RwLock`].
 ///
+/// [`Mutex`]: struct.Mutex.html
+/// [`RwLock`]: struct.RwLock.html
+/// [`TryLockResult`]: type.TryLockResult.html
 /// [`try_lock`]: struct.Mutex.html#method.try_lock
+/// [`try_read`]: struct.RwLock.html#method.try_read
+/// [`try_write`]: struct.RwLock.html#method.try_write
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum TryLockError<T> {
     /// The lock could not be acquired because another thread failed while holding
@@ -148,6 +179,28 @@ impl<T> PoisonError<T> {
 
     /// Consumes this error indicating that a lock is poisoned, returning the
     /// underlying guard to allow access regardless.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashSet;
+    /// use std::sync::{Arc, Mutex};
+    /// use std::thread;
+    ///
+    /// let mutex = Arc::new(Mutex::new(HashSet::new()));
+    ///
+    /// // poison the mutex
+    /// let c_mutex = mutex.clone();
+    /// let _ = thread::spawn(move || {
+    ///     let mut data = c_mutex.lock().unwrap();
+    ///     data.insert(10);
+    ///     panic!();
+    /// }).join();
+    ///
+    /// let p_err = mutex.lock().unwrap_err();
+    /// let data = p_err.into_inner();
+    /// println!("recovered {} items", data.len());
+    /// ```
     #[stable(feature = "sync_poison", since = "1.2.0")]
     pub fn into_inner(self) -> T { self.guard }
 
diff --git a/src/libstd/sys_common/remutex.rs b/src/libstd/sys_common/remutex.rs
index 4d0407ccf6c..ce43ec6d9ab 100644
--- a/src/libstd/sys_common/remutex.rs
+++ b/src/libstd/sys_common/remutex.rs
@@ -116,11 +116,18 @@ impl<T> Drop for ReentrantMutex<T> {
 impl<T: fmt::Debug + 'static> fmt::Debug for ReentrantMutex<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self.try_lock() {
-            Ok(guard) => write!(f, "ReentrantMutex {{ data: {:?} }}", &*guard),
+            Ok(guard) => f.debug_struct("ReentrantMutex").field("data", &*guard).finish(),
             Err(TryLockError::Poisoned(err)) => {
-                write!(f, "ReentrantMutex {{ data: Poisoned({:?}) }}", &**err.get_ref())
+                f.debug_struct("ReentrantMutex").field("data", &**err.get_ref()).finish()
             },
-            Err(TryLockError::WouldBlock) => write!(f, "ReentrantMutex {{ <locked> }}")
+            Err(TryLockError::WouldBlock) => {
+                struct LockedPlaceholder;
+                impl fmt::Debug for LockedPlaceholder {
+                    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("<locked>") }
+                }
+
+                f.debug_struct("ReentrantMutex").field("data", &LockedPlaceholder).finish()
+            }
         }
     }
 }
diff --git a/src/libstd/sys_common/thread.rs b/src/libstd/sys_common/thread.rs
index 87fb34a9dec..f1379b6ec63 100644
--- a/src/libstd/sys_common/thread.rs
+++ b/src/libstd/sys_common/thread.rs
@@ -8,14 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use env;
 use alloc::boxed::FnBox;
-use libc;
+use env;
 use sync::atomic::{self, Ordering};
 use sys::stack_overflow;
 use sys::thread as imp;
 
-pub unsafe fn start_thread(main: *mut libc::c_void) {
+#[allow(dead_code)]
+pub unsafe fn start_thread(main: *mut u8) {
     // Next, set up our stack overflow handler which may get triggered if we run
     // out of stack.
     let _handler = stack_overflow::Handler::new();
diff --git a/src/libstd/sys_common/thread_local.rs b/src/libstd/sys_common/thread_local.rs
index 87ffd304e1a..a4aa3d96d25 100644
--- a/src/libstd/sys_common/thread_local.rs
+++ b/src/libstd/sys_common/thread_local.rs
@@ -262,7 +262,7 @@ pub unsafe fn register_dtor_fallback(t: *mut u8,
     unsafe extern fn run_dtors(mut ptr: *mut u8) {
         while !ptr.is_null() {
             let list: Box<List> = Box::from_raw(ptr as *mut List);
-            for &(ptr, dtor) in list.iter() {
+            for (ptr, dtor) in list.into_iter() {
                 dtor(ptr);
             }
             ptr = DTORS.get();
diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs
index b89a73cd28a..e212b5006f2 100644
--- a/src/libstd/sys_common/wtf8.rs
+++ b/src/libstd/sys_common/wtf8.rs
@@ -35,8 +35,10 @@ use hash::{Hash, Hasher};
 use iter::FromIterator;
 use mem;
 use ops;
+use rc::Rc;
 use slice;
 use str;
+use sync::Arc;
 use sys_common::AsInner;
 
 const UTF8_REPLACEMENT_CHARACTER: &'static str = "\u{FFFD}";
@@ -641,6 +643,18 @@ impl Wtf8 {
         let boxed: Box<[u8]> = Default::default();
         unsafe { mem::transmute(boxed) }
     }
+
+    #[inline]
+    pub fn into_arc(&self) -> Arc<Wtf8> {
+        let arc: Arc<[u8]> = Arc::from(&self.bytes);
+        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Wtf8) }
+    }
+
+    #[inline]
+    pub fn into_rc(&self) -> Rc<Wtf8> {
+        let rc: Rc<[u8]> = Rc::from(&self.bytes);
+        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Wtf8) }
+    }
 }
 
 
diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs
index a53c76a333a..fcbca38a98f 100644
--- a/src/libstd/thread/local.rs
+++ b/src/libstd/thread/local.rs
@@ -190,11 +190,6 @@ macro_rules! __thread_local_inner {
         }
     };
     ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $init:expr) => {
-        #[cfg(stage0)]
-        $(#[$attr])* $vis static $name: $crate::thread::LocalKey<$t> =
-            __thread_local_inner!(@key $(#[$attr])* $vis $name, $t, $init);
-
-        #[cfg(not(stage0))]
         $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> =
             __thread_local_inner!(@key $(#[$attr])* $vis $name, $t, $init);
     }
@@ -325,7 +320,10 @@ impl<T: 'static> LocalKey<T> {
     ///
     /// Once the initialization expression succeeds, the key transitions to the
     /// `Valid` state which will guarantee that future calls to [`with`] will
-    /// succeed within the thread.
+    /// succeed within the thread. Some keys might skip the `Uninitialized`
+    /// state altogether and start in the `Valid` state as an optimization
+    /// (e.g. keys initialized with a constant expression), but no guarantees
+    /// are made.
     ///
     /// When a thread exits, each key will be destroyed in turn, and as keys are
     /// destroyed they will enter the `Destroyed` state just before the
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index 30887b16c60..ee49bf796b8 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -25,11 +25,15 @@
 //!
 //! Fatal logic errors in Rust cause *thread panic*, during which
 //! a thread will unwind the stack, running destructors and freeing
-//! owned resources. Thread panic is unrecoverable from within
-//! the panicking thread (i.e. there is no 'try/catch' in Rust), but
-//! the panic may optionally be detected from a different thread. If
-//! the main thread panics, the application will exit with a non-zero
-//! exit code.
+//! owned resources. While not meant as a 'try/catch' mechanism, panics
+//! in Rust can nonetheless be caught (unless compiling with `panic=abort`) with
+//! [`catch_unwind`](../../std/panic/fn.catch_unwind.html) and recovered
+//! from, or alternatively be resumed with
+//! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic
+//! is not caught the thread will exit, but the panic may optionally be
+//! detected from a different thread with [`join`]. If the main thread panics
+//! without the panic being caught, the application will exit with a
+//! non-zero exit code.
 //!
 //! When the main thread of a Rust program terminates, the entire program shuts
 //! down, even if other threads are still running. However, this module provides
@@ -171,6 +175,8 @@ use panic;
 use panicking;
 use str;
 use sync::{Mutex, Condvar, Arc};
+use sync::atomic::AtomicUsize;
+use sync::atomic::Ordering::SeqCst;
 use sys::thread as imp;
 use sys_common::mutex;
 use sys_common::thread_info;
@@ -485,15 +491,17 @@ impl Builder {
 /// let (tx, rx) = channel();
 ///
 /// let sender = thread::spawn(move || {
-///     let _ = tx.send("Hello, thread".to_owned());
+///     tx.send("Hello, thread".to_owned())
+///         .expect("Unable to send on channel");
 /// });
 ///
 /// let receiver = thread::spawn(move || {
-///     println!("{}", rx.recv().unwrap());
+///     let value = rx.recv().expect("Unable to receive from channel");
+///     println!("{}", value);
 /// });
 ///
-/// let _ = sender.join();
-/// let _ = receiver.join();
+/// sender.join().expect("The sender thread has panicked");
+/// receiver.join().expect("The receiver thread has panicked");
 /// ```
 ///
 /// A thread can also return a value through its [`JoinHandle`], you can use
@@ -692,6 +700,11 @@ pub fn sleep(dur: Duration) {
     imp::Thread::sleep(dur)
 }
 
+// constants for park/unpark
+const EMPTY: usize = 0;
+const PARKED: usize = 1;
+const NOTIFIED: usize = 2;
+
 /// Blocks unless or until the current thread's token is made available.
 ///
 /// A call to `park` does not guarantee that the thread will remain parked
@@ -769,11 +782,27 @@ pub fn sleep(dur: Duration) {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn park() {
     let thread = current();
-    let mut guard = thread.inner.lock.lock().unwrap();
-    while !*guard {
-        guard = thread.inner.cvar.wait(guard).unwrap();
+
+    // If we were previously notified then we consume this notification and
+    // return quickly.
+    if thread.inner.state.compare_exchange(NOTIFIED, EMPTY, SeqCst, SeqCst).is_ok() {
+        return
+    }
+
+    // Otherwise we need to coordinate going to sleep
+    let mut m = thread.inner.lock.lock().unwrap();
+    match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) {
+        Ok(_) => {}
+        Err(NOTIFIED) => return, // notified after we locked
+        Err(_) => panic!("inconsistent park state"),
+    }
+    loop {
+        m = thread.inner.cvar.wait(m).unwrap();
+        match thread.inner.state.compare_exchange(NOTIFIED, EMPTY, SeqCst, SeqCst) {
+            Ok(_) => return, // got a notification
+            Err(_) => {} // spurious wakeup, go back to sleep
+        }
     }
-    *guard = false;
 }
 
 /// Use [`park_timeout`].
@@ -840,12 +869,30 @@ pub fn park_timeout_ms(ms: u32) {
 #[stable(feature = "park_timeout", since = "1.4.0")]
 pub fn park_timeout(dur: Duration) {
     let thread = current();
-    let mut guard = thread.inner.lock.lock().unwrap();
-    if !*guard {
-        let (g, _) = thread.inner.cvar.wait_timeout(guard, dur).unwrap();
-        guard = g;
+
+    // Like `park` above we have a fast path for an already-notified thread, and
+    // afterwards we start coordinating for a sleep.
+    // return quickly.
+    if thread.inner.state.compare_exchange(NOTIFIED, EMPTY, SeqCst, SeqCst).is_ok() {
+        return
+    }
+    let m = thread.inner.lock.lock().unwrap();
+    match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) {
+        Ok(_) => {}
+        Err(NOTIFIED) => return, // notified after we locked
+        Err(_) => panic!("inconsistent park_timeout state"),
+    }
+
+    // Wait with a timeout, and if we spuriously wake up or otherwise wake up
+    // from a notification we just want to unconditionally set the state back to
+    // empty, either consuming a notification or un-flagging ourselves as
+    // parked.
+    let (_m, _result) = thread.inner.cvar.wait_timeout(m, dur).unwrap();
+    match thread.inner.state.swap(EMPTY, SeqCst) {
+        NOTIFIED => {} // got a notification, hurray!
+        PARKED => {} // no notification, alas
+        n => panic!("inconsistent park_timeout state: {}", n),
     }
-    *guard = false;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -912,7 +959,10 @@ impl ThreadId {
 struct Inner {
     name: Option<CString>,      // Guaranteed to be UTF-8
     id: ThreadId,
-    lock: Mutex<bool>,          // true when there is a buffered unpark
+
+    // state for thread park/unpark
+    state: AtomicUsize,
+    lock: Mutex<()>,
     cvar: Condvar,
 }
 
@@ -956,7 +1006,8 @@ impl Thread {
             inner: Arc::new(Inner {
                 name: cname,
                 id: ThreadId::new(),
-                lock: Mutex::new(false),
+                state: AtomicUsize::new(EMPTY),
+                lock: Mutex::new(()),
                 cvar: Condvar::new(),
             })
         }
@@ -996,10 +1047,22 @@ impl Thread {
     /// [park]: fn.park.html
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unpark(&self) {
-        let mut guard = self.inner.lock.lock().unwrap();
-        if !*guard {
-            *guard = true;
-            self.inner.cvar.notify_one();
+        loop {
+            match self.inner.state.compare_exchange(EMPTY, NOTIFIED, SeqCst, SeqCst) {
+                Ok(_) => return, // no one was waiting
+                Err(NOTIFIED) => return, // already unparked
+                Err(PARKED) => {} // gotta go wake someone up
+                _ => panic!("inconsistent state in unpark"),
+            }
+
+            // Coordinate wakeup through the mutex and a condvar notification
+            let _lock = self.inner.lock.lock().unwrap();
+            match self.inner.state.compare_exchange(PARKED, NOTIFIED, SeqCst, SeqCst) {
+                Ok(_) => return self.inner.cvar.notify_one(),
+                Err(NOTIFIED) => return, // a different thread unparked
+                Err(EMPTY) => {} // parked thread went away, try again
+                _ => panic!("inconsistent state in unpark"),
+            }
         }
     }
 
@@ -1192,7 +1255,7 @@ impl<T> JoinInner<T> {
 ///     });
 /// });
 ///
-/// let _ = original_thread.join();
+/// original_thread.join().expect("The thread being joined has panicked");
 /// println!("Original thread is joined.");
 ///
 /// // We make sure that the new thread has time to run, before the main