about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2018-08-19 18:34:46 +0200
committerGitHub <noreply@github.com>2018-08-19 18:34:46 +0200
commit08b1d83a46848dd7bd778aeae67a1e529e95d8cd (patch)
tree9153a34f91860b175afb24f904fd50ac09e77c4e /src/libstd
parentac64ef33756d05557153e00211cdf8fcf65d4be3 (diff)
parentb355906919927ab3c879becd14392f023af883a1 (diff)
downloadrust-08b1d83a46848dd7bd778aeae67a1e529e95d8cd.tar.gz
rust-08b1d83a46848dd7bd778aeae67a1e529e95d8cd.zip
Merge branch 'master' into feature/core_convert_id
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/Cargo.toml5
-rw-r--r--src/libstd/alloc.rs184
-rw-r--r--src/libstd/ascii.rs766
-rw-r--r--src/libstd/build.rs82
-rw-r--r--src/libstd/collections/hash/map.rs526
-rw-r--r--src/libstd/collections/hash/set.rs70
-rw-r--r--src/libstd/collections/hash/table.rs226
-rw-r--r--src/libstd/collections/mod.rs20
-rw-r--r--src/libstd/env.rs84
-rw-r--r--src/libstd/error.rs184
-rw-r--r--src/libstd/f32.rs433
-rw-r--r--src/libstd/f64.rs441
-rw-r--r--src/libstd/ffi/c_str.rs112
-rw-r--r--src/libstd/ffi/os_str.rs115
-rw-r--r--src/libstd/fs.rs656
-rw-r--r--src/libstd/future.rs116
-rw-r--r--src/libstd/heap.rs175
-rw-r--r--src/libstd/io/buffered.rs270
-rw-r--r--src/libstd/io/cursor.rs37
-rw-r--r--src/libstd/io/error.rs33
-rw-r--r--src/libstd/io/lazy.rs30
-rw-r--r--src/libstd/io/mod.rs767
-rw-r--r--src/libstd/io/stdio.rs186
-rw-r--r--src/libstd/io/util.rs17
-rw-r--r--src/libstd/keyword_docs.rs58
-rw-r--r--src/libstd/lib.rs176
-rw-r--r--src/libstd/macros.rs201
-rw-r--r--src/libstd/net/addr.rs12
-rw-r--r--src/libstd/net/ip.rs313
-rw-r--r--src/libstd/net/mod.rs58
-rw-r--r--src/libstd/net/parser.rs26
-rw-r--r--src/libstd/net/tcp.rs85
-rw-r--r--src/libstd/net/udp.rs89
-rw-r--r--src/libstd/num.rs4
-rw-r--r--src/libstd/os/android/fs.rs4
-rw-r--r--src/libstd/os/bitrig/fs.rs4
-rw-r--r--src/libstd/os/dragonfly/fs.rs4
-rw-r--r--src/libstd/os/emscripten/fs.rs4
-rw-r--r--src/libstd/os/freebsd/fs.rs4
-rw-r--r--src/libstd/os/fuchsia/fs.rs4
-rw-r--r--src/libstd/os/haiku/fs.rs4
-rw-r--r--src/libstd/os/hermit/fs.rs389
-rw-r--r--src/libstd/os/hermit/mod.rs16
-rw-r--r--src/libstd/os/hermit/raw.rs27
-rw-r--r--src/libstd/os/ios/fs.rs4
-rw-r--r--src/libstd/os/linux/fs.rs242
-rw-r--r--src/libstd/os/macos/fs.rs4
-rw-r--r--src/libstd/os/mod.rs1
-rw-r--r--src/libstd/os/netbsd/fs.rs4
-rw-r--r--src/libstd/os/openbsd/fs.rs4
-rw-r--r--src/libstd/os/raw/char.md11
-rw-r--r--src/libstd/os/raw/double.md7
-rw-r--r--src/libstd/os/raw/float.md6
-rw-r--r--src/libstd/os/raw/int.md7
-rw-r--r--src/libstd/os/raw/long.md7
-rw-r--r--src/libstd/os/raw/longlong.md7
-rw-r--r--src/libstd/os/raw/mod.rs (renamed from src/libstd/os/raw.rs)44
-rw-r--r--src/libstd/os/raw/schar.md6
-rw-r--r--src/libstd/os/raw/short.md6
-rw-r--r--src/libstd/os/raw/uchar.md6
-rw-r--r--src/libstd/os/raw/uint.md7
-rw-r--r--src/libstd/os/raw/ulong.md7
-rw-r--r--src/libstd/os/raw/ulonglong.md7
-rw-r--r--src/libstd/os/raw/ushort.md6
-rw-r--r--src/libstd/os/solaris/fs.rs4
-rw-r--r--src/libstd/panic.rs96
-rw-r--r--src/libstd/panicking.rs394
-rw-r--r--src/libstd/path.rs139
-rw-r--r--src/libstd/prelude/v1.rs59
-rw-r--r--src/libstd/primitive_docs.rs150
-rw-r--r--src/libstd/process.rs156
-rw-r--r--src/libstd/rt.rs19
-rw-r--r--src/libstd/sync/condvar.rs222
-rw-r--r--src/libstd/sync/mod.rs2
-rw-r--r--src/libstd/sync/mpsc/mod.rs40
-rw-r--r--src/libstd/sync/mpsc/mpsc_queue.rs3
-rw-r--r--src/libstd/sync/mpsc/select.rs4
-rw-r--r--src/libstd/sync/mpsc/spsc_queue.rs2
-rw-r--r--src/libstd/sync/mutex.rs6
-rw-r--r--src/libstd/sync/once.rs63
-rw-r--r--src/libstd/sync/rwlock.rs8
-rw-r--r--src/libstd/sys/cloudabi/abi/cloudabi.rs18
-rw-r--r--src/libstd/sys/cloudabi/backtrace.rs17
-rw-r--r--src/libstd/sys/cloudabi/shims/process.rs12
-rw-r--r--src/libstd/sys/cloudabi/stdio.rs4
-rw-r--r--src/libstd/sys/cloudabi/thread.rs10
-rw-r--r--src/libstd/sys/mod.rs3
-rw-r--r--src/libstd/sys/redox/args.rs16
-rw-r--r--src/libstd/sys/redox/backtrace/tracing.rs17
-rw-r--r--src/libstd/sys/redox/ext/ffi.rs10
-rw-r--r--src/libstd/sys/redox/ext/fs.rs74
-rw-r--r--src/libstd/sys/redox/ext/mod.rs1
-rw-r--r--src/libstd/sys/redox/ext/net.rs769
-rw-r--r--src/libstd/sys/redox/ext/process.rs10
-rw-r--r--src/libstd/sys/redox/ext/thread.rs6
-rw-r--r--src/libstd/sys/redox/fd.rs5
-rw-r--r--src/libstd/sys/redox/net/mod.rs4
-rw-r--r--src/libstd/sys/redox/net/netc.rs2
-rw-r--r--src/libstd/sys/redox/net/tcp.rs10
-rw-r--r--src/libstd/sys/redox/net/udp.rs12
-rw-r--r--src/libstd/sys/redox/os.rs3
-rw-r--r--src/libstd/sys/redox/os_str.rs7
-rw-r--r--src/libstd/sys/redox/process.rs28
-rw-r--r--src/libstd/sys/redox/stdio.rs4
-rw-r--r--src/libstd/sys/redox/syscall/error.rs4
-rw-r--r--src/libstd/sys/redox/thread.rs10
-rw-r--r--src/libstd/sys/redox/time.rs2
-rw-r--r--src/libstd/sys/unix/args.rs19
-rw-r--r--src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs1
-rw-r--r--src/libstd/sys/unix/backtrace/tracing/gcc_s.rs17
-rw-r--r--src/libstd/sys/unix/condvar.rs13
-rw-r--r--src/libstd/sys/unix/env.rs11
-rw-r--r--src/libstd/sys/unix/ext/ffi.rs8
-rw-r--r--src/libstd/sys/unix/ext/fs.rs498
-rw-r--r--src/libstd/sys/unix/ext/mod.rs1
-rw-r--r--src/libstd/sys/unix/ext/net.rs137
-rw-r--r--src/libstd/sys/unix/ext/process.rs10
-rw-r--r--src/libstd/sys/unix/ext/thread.rs4
-rw-r--r--src/libstd/sys/unix/fast_thread_local.rs7
-rw-r--r--src/libstd/sys/unix/fd.rs25
-rw-r--r--src/libstd/sys/unix/fs.rs217
-rw-r--r--src/libstd/sys/unix/l4re.rs4
-rw-r--r--src/libstd/sys/unix/mod.rs5
-rw-r--r--src/libstd/sys/unix/mutex.rs9
-rw-r--r--src/libstd/sys/unix/net.rs45
-rw-r--r--src/libstd/sys/unix/os.rs69
-rw-r--r--src/libstd/sys/unix/os_str.rs7
-rw-r--r--src/libstd/sys/unix/pipe.rs37
-rw-r--r--src/libstd/sys/unix/process/mod.rs2
-rw-r--r--src/libstd/sys/unix/process/process_common.rs41
-rw-r--r--src/libstd/sys/unix/process/process_fuchsia.rs75
-rw-r--r--src/libstd/sys/unix/process/process_unix.rs118
-rw-r--r--src/libstd/sys/unix/process/zircon.rs85
-rw-r--r--src/libstd/sys/unix/rand.rs29
-rw-r--r--src/libstd/sys/unix/stack_overflow.rs9
-rw-r--r--src/libstd/sys/unix/stdio.rs4
-rw-r--r--src/libstd/sys/unix/thread.rs169
-rw-r--r--src/libstd/sys/unix/time.rs6
-rw-r--r--src/libstd/sys/wasm/args.rs38
-rw-r--r--src/libstd/sys/wasm/mod.rs233
-rw-r--r--src/libstd/sys/wasm/os.rs40
-rw-r--r--src/libstd/sys/wasm/os_str.rs7
-rw-r--r--src/libstd/sys/wasm/process.rs12
-rw-r--r--src/libstd/sys/wasm/rwlock.rs4
-rw-r--r--src/libstd/sys/wasm/stdio.rs39
-rw-r--r--src/libstd/sys/wasm/thread.rs10
-rw-r--r--src/libstd/sys/wasm/time.rs44
-rw-r--r--src/libstd/sys/windows/backtrace/mod.rs298
-rw-r--r--src/libstd/sys/windows/backtrace/printing/mod.rs14
-rw-r--r--src/libstd/sys/windows/backtrace/printing/msvc.rs198
-rw-r--r--src/libstd/sys/windows/c.rs84
-rw-r--r--src/libstd/sys/windows/ext/ffi.rs11
-rw-r--r--src/libstd/sys/windows/ext/fs.rs128
-rw-r--r--src/libstd/sys/windows/ext/mod.rs1
-rw-r--r--src/libstd/sys/windows/ext/process.rs8
-rw-r--r--src/libstd/sys/windows/fs.rs47
-rw-r--r--src/libstd/sys/windows/mod.rs10
-rw-r--r--src/libstd/sys/windows/mutex.rs2
-rw-r--r--src/libstd/sys/windows/os_str.rs5
-rw-r--r--src/libstd/sys/windows/pipe.rs2
-rw-r--r--src/libstd/sys/windows/process.rs26
-rw-r--r--src/libstd/sys/windows/stdio.rs4
-rw-r--r--src/libstd/sys/windows/thread.rs13
-rw-r--r--src/libstd/sys_common/at_exit_imp.rs38
-rw-r--r--src/libstd/sys_common/backtrace.rs39
-rw-r--r--src/libstd/sys_common/bytestring.rs2
-rw-r--r--src/libstd/sys_common/mod.rs14
-rw-r--r--src/libstd/sys_common/mutex.rs32
-rw-r--r--src/libstd/sys_common/net.rs24
-rw-r--r--src/libstd/sys_common/poison.rs4
-rw-r--r--src/libstd/sys_common/process.rs14
-rw-r--r--src/libstd/sys_common/remutex.rs6
-rw-r--r--src/libstd/sys_common/thread.rs4
-rw-r--r--src/libstd/sys_common/thread_info.rs13
-rw-r--r--src/libstd/sys_common/thread_local.rs9
-rw-r--r--src/libstd/sys_common/util.rs5
-rw-r--r--src/libstd/sys_common/wtf8.rs67
-rw-r--r--src/libstd/termination.rs86
-rw-r--r--src/libstd/tests/env.rs94
-rw-r--r--src/libstd/thread/local.rs169
-rw-r--r--src/libstd/thread/mod.rs48
-rw-r--r--src/libstd/time.rs (renamed from src/libstd/time/mod.rs)32
-rw-r--r--src/libstd/time/duration.rs587
183 files changed, 8190 insertions, 5892 deletions
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 3430ecabcbe..5348c9a0f34 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -22,11 +22,10 @@ core = { path = "../libcore" }
 libc = { path = "../rustc/libc_shim" }
 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"
+rand = "0.4"
 
 [target.x86_64-apple-darwin.dependencies]
 rustc_asan = { path = "../librustc_asan" }
@@ -39,6 +38,7 @@ rustc_msan = { path = "../librustc_msan" }
 rustc_tsan = { path = "../librustc_tsan" }
 
 [build-dependencies]
+cc = "1.0"
 build_helper = { path = "../build_helper" }
 
 [features]
@@ -48,3 +48,4 @@ jemalloc = ["alloc_jemalloc"]
 force_alloc_system = []
 panic-unwind = ["panic_unwind"]
 profiler = ["profiler_builtins"]
+wasm_syscall = []
diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs
new file mode 100644
index 00000000000..b9aba1e9cab
--- /dev/null
+++ b/src/libstd/alloc.rs
@@ -0,0 +1,184 @@
+// 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.
+
+//! Memory allocation APIs
+//!
+//! In a given program, the standard library has one “global” memory allocator
+//! that is used for example by `Box<T>` and `Vec<T>`.
+//!
+//! Currently the default global allocator is unspecified.
+//! The compiler may link to a version of [jemalloc] on some platforms,
+//! but this is not guaranteed.
+//! Libraries, however, like `cdylib`s and `staticlib`s are guaranteed
+//! to use the [`System`] by default.
+//!
+//! [jemalloc]: https://github.com/jemalloc/jemalloc
+//! [`System`]: struct.System.html
+//!
+//! # The `#[global_allocator]` attribute
+//!
+//! This attribute allows configuring the choice of global allocator.
+//! You can use this to implement a completely custom global allocator
+//! to route all default allocation requests to a custom object.
+//!
+//! ```rust
+//! use std::alloc::{GlobalAlloc, System, Layout};
+//!
+//! struct MyAllocator;
+//!
+//! unsafe impl GlobalAlloc for MyAllocator {
+//!     unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+//!         System.alloc(layout)
+//!     }
+//!
+//!     unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
+//!         System.dealloc(ptr, layout)
+//!     }
+//! }
+//!
+//! #[global_allocator]
+//! static GLOBAL: MyAllocator = MyAllocator;
+//!
+//! fn main() {
+//!     // This `Vec` will allocate memory through `GLOBAL` above
+//!     let mut v = Vec::new();
+//!     v.push(1);
+//! }
+//! ```
+//!
+//! The attribute is used on a `static` item whose type implements the
+//! [`GlobalAlloc`] trait. This type can be provided by an external library:
+//!
+//! [`GlobalAlloc`]: ../../core/alloc/trait.GlobalAlloc.html
+//!
+//! ```rust,ignore (demonstrates crates.io usage)
+//! extern crate jemallocator;
+//!
+//! use jemallocator::Jemalloc;
+//!
+//! #[global_allocator]
+//! static GLOBAL: Jemalloc = Jemalloc;
+//!
+//! fn main() {}
+//! ```
+//!
+//! The `#[global_allocator]` can only be used once in a crate
+//! or its recursive dependencies.
+
+#![stable(feature = "alloc_module", since = "1.28.0")]
+
+use core::sync::atomic::{AtomicPtr, Ordering};
+use core::{mem, ptr};
+use sys_common::util::dumb_print;
+
+#[stable(feature = "alloc_module", since = "1.28.0")]
+#[doc(inline)]
+pub use alloc_crate::alloc::*;
+
+#[stable(feature = "alloc_system_type", since = "1.28.0")]
+#[doc(inline)]
+pub use alloc_system::System;
+
+static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
+
+/// Registers a custom allocation error hook, replacing any that was previously registered.
+///
+/// The allocation error hook is invoked when an infallible memory allocation fails, before
+/// the runtime aborts. The default hook prints a message to standard error,
+/// but this behavior can be customized with the [`set_alloc_error_hook`] and
+/// [`take_alloc_error_hook`] functions.
+///
+/// The hook is provided with a `Layout` struct which contains information
+/// about the allocation that failed.
+///
+/// The allocation error hook is a global resource.
+#[unstable(feature = "alloc_error_hook", issue = "51245")]
+pub fn set_alloc_error_hook(hook: fn(Layout)) {
+    HOOK.store(hook as *mut (), Ordering::SeqCst);
+}
+
+/// Unregisters the current allocation error hook, returning it.
+///
+/// *See also the function [`set_alloc_error_hook`].*
+///
+/// If no custom hook is registered, the default hook will be returned.
+#[unstable(feature = "alloc_error_hook", issue = "51245")]
+pub fn take_alloc_error_hook() -> fn(Layout) {
+    let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst);
+    if hook.is_null() {
+        default_alloc_error_hook
+    } else {
+        unsafe { mem::transmute(hook) }
+    }
+}
+
+fn default_alloc_error_hook(layout: Layout) {
+    dumb_print(format_args!("memory allocation of {} bytes failed", layout.size()));
+}
+
+#[cfg(not(test))]
+#[doc(hidden)]
+#[alloc_error_handler]
+#[unstable(feature = "alloc_internals", issue = "0")]
+pub fn rust_oom(layout: Layout) -> ! {
+    let hook = HOOK.load(Ordering::SeqCst);
+    let hook: fn(Layout) = if hook.is_null() {
+        default_alloc_error_hook
+    } else {
+        unsafe { mem::transmute(hook) }
+    };
+    hook(layout);
+    unsafe { ::sys::abort_internal(); }
+}
+
+#[cfg(not(test))]
+#[doc(hidden)]
+#[allow(unused_attributes)]
+#[unstable(feature = "alloc_internals", issue = "0")]
+pub mod __default_lib_allocator {
+    use super::{System, Layout, GlobalAlloc};
+    // for symbol names src/librustc/middle/allocator.rs
+    // for signatures src/librustc_allocator/lib.rs
+
+    // linkage directives are provided as part of the current compiler allocator
+    // ABI
+
+    #[no_mangle]
+    #[rustc_std_internal_symbol]
+    pub unsafe extern fn __rdl_alloc(size: usize, align: usize) -> *mut u8 {
+        let layout = Layout::from_size_align_unchecked(size, align);
+        System.alloc(layout)
+    }
+
+    #[no_mangle]
+    #[rustc_std_internal_symbol]
+    pub unsafe extern fn __rdl_dealloc(ptr: *mut u8,
+                                       size: usize,
+                                       align: usize) {
+        System.dealloc(ptr, Layout::from_size_align_unchecked(size, align))
+    }
+
+    #[no_mangle]
+    #[rustc_std_internal_symbol]
+    pub unsafe extern fn __rdl_realloc(ptr: *mut u8,
+                                       old_size: usize,
+                                       align: usize,
+                                       new_size: usize) -> *mut u8 {
+        let old_layout = Layout::from_size_align_unchecked(old_size, align);
+        System.realloc(ptr, old_layout, new_size)
+    }
+
+    #[no_mangle]
+    #[rustc_std_internal_symbol]
+    pub unsafe extern fn __rdl_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
+        let layout = Layout::from_size_align_unchecked(size, align);
+        System.alloc_zeroed(layout)
+    }
+}
diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs
index 82e1a3447dc..0c8e95aa426 100644
--- a/src/libstd/ascii.rs
+++ b/src/libstd/ascii.rs
@@ -26,9 +26,8 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use fmt;
-use ops::Range;
-use iter::FusedIterator;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use core::ascii::{EscapeDefault, escape_default};
 
 /// Extension methods for ASCII-subset only operations.
 ///
@@ -53,6 +52,7 @@ use iter::FusedIterator;
 ///
 /// [combining character]: https://en.wikipedia.org/wiki/Combining_character
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
 pub trait AsciiExt {
     /// Container type for copied ASCII characters.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -85,6 +85,7 @@ pub trait AsciiExt {
     /// [`make_ascii_uppercase`]: #tymethod.make_ascii_uppercase
     /// [`str::to_uppercase`]: ../primitive.str.html#method.to_uppercase
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow(deprecated)]
     fn to_ascii_uppercase(&self) -> Self::Owned;
 
     /// Makes a copy of the value in its ASCII lower case equivalent.
@@ -105,6 +106,7 @@ pub trait AsciiExt {
     /// [`make_ascii_lowercase`]: #tymethod.make_ascii_lowercase
     /// [`str::to_lowercase`]: ../primitive.str.html#method.to_lowercase
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow(deprecated)]
     fn to_ascii_lowercase(&self) -> Self::Owned;
 
     /// Checks that two values are an ASCII case-insensitive match.
@@ -152,150 +154,6 @@ pub trait AsciiExt {
     /// [`to_ascii_lowercase`]: #tymethod.to_ascii_lowercase
     #[stable(feature = "ascii", since = "1.9.0")]
     fn make_ascii_lowercase(&mut self);
-
-    /// Checks if the value is an ASCII alphabetic character:
-    /// U+0041 'A' ... U+005A 'Z' or U+0061 'a' ... U+007A 'z'.
-    /// For strings, true if all characters in the string are
-    /// ASCII alphabetic.
-    ///
-    /// # Note
-    ///
-    /// 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!(); }
-
-    /// Checks if the value is an ASCII uppercase character:
-    /// U+0041 'A' ... U+005A 'Z'.
-    /// For strings, true if all characters in the string are
-    /// ASCII uppercase.
-    ///
-    /// # Note
-    ///
-    /// 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!(); }
-
-    /// Checks if the value is an ASCII lowercase character:
-    /// U+0061 'a' ... U+007A 'z'.
-    /// For strings, true if all characters in the string are
-    /// ASCII lowercase.
-    ///
-    /// # Note
-    ///
-    /// 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!(); }
-
-    /// Checks if the value is an ASCII alphanumeric character:
-    /// U+0041 'A' ... U+005A 'Z', U+0061 'a' ... U+007A 'z', or
-    /// U+0030 '0' ... U+0039 '9'.
-    /// For strings, true if all characters in the string are
-    /// ASCII alphanumeric.
-    ///
-    /// # Note
-    ///
-    /// 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!(); }
-
-    /// Checks if the value is an ASCII decimal digit:
-    /// U+0030 '0' ... U+0039 '9'.
-    /// For strings, true if all characters in the string are
-    /// ASCII digits.
-    ///
-    /// # Note
-    ///
-    /// 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!(); }
-
-    /// Checks if the value is an ASCII hexadecimal digit:
-    /// U+0030 '0' ... U+0039 '9', U+0041 'A' ... U+0046 'F', or
-    /// U+0061 'a' ... U+0066 'f'.
-    /// For strings, true if all characters in the string are
-    /// ASCII hex digits.
-    ///
-    /// # Note
-    ///
-    /// 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+007B ... U+007E `{ | } ~`
-    ///
-    /// For strings, true if all characters in the string are
-    /// ASCII punctuation.
-    ///
-    /// # Note
-    ///
-    /// 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!(); }
-
-    /// Checks if the value is an ASCII graphic character:
-    /// U+0021 '@' ... U+007E '~'.
-    /// For strings, true if all characters in the string are
-    /// ASCII graphic characters.
-    ///
-    /// # Note
-    ///
-    /// 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!(); }
-
-    /// Checks if the value is an ASCII whitespace character:
-    /// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
-    /// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
-    /// For strings, true if all characters in the string are
-    /// ASCII whitespace.
-    ///
-    /// Rust uses the WhatWG Infra Standard's [definition of ASCII
-    /// whitespace][infra-aw].  There are several other definitions in
-    /// wide use.  For instance, [the POSIX locale][pct] includes
-    /// U+000B VERTICAL TAB as well as all the above characters,
-    /// but—from the very same specification—[the default rule for
-    /// "field splitting" in the Bourne shell][bfs] considers *only*
-    /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace.
-    ///
-    /// If you are writing a program that will process an existing
-    /// file format, check what that format's definition of whitespace is
-    /// before using this function.
-    ///
-    /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
-    /// [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
-    ///
-    /// # Note
-    ///
-    /// 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!(); }
-
-    /// Checks if the value is an ASCII control character:
-    /// U+0000 NUL ... U+001F UNIT SEPARATOR, or U+007F DELETE.
-    /// Note that most ASCII whitespace characters are control
-    /// characters, but SPACE is not.
-    ///
-    /// # Note
-    ///
-    /// 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!(); }
 }
 
 macro_rules! delegating_ascii_methods {
@@ -320,640 +178,34 @@ macro_rules! delegating_ascii_methods {
     }
 }
 
-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.is_ascii_uppercase() }
-
-        #[inline]
-        fn is_ascii_lowercase(&self) -> bool { self.is_ascii_lowercase() }
-
-        #[inline]
-        fn is_ascii_alphanumeric(&self) -> bool { self.is_ascii_alphanumeric() }
-
-        #[inline]
-        fn is_ascii_digit(&self) -> bool { self.is_ascii_digit() }
-
-        #[inline]
-        fn is_ascii_hexdigit(&self) -> bool { self.is_ascii_hexdigit() }
-
-        #[inline]
-        fn is_ascii_punctuation(&self) -> bool { self.is_ascii_punctuation() }
-
-        #[inline]
-        fn is_ascii_graphic(&self) -> bool { self.is_ascii_graphic() }
-
-        #[inline]
-        fn is_ascii_whitespace(&self) -> bool { self.is_ascii_whitespace() }
-
-        #[inline]
-        fn is_ascii_control(&self) -> bool { self.is_ascii_control() }
-    }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 impl AsciiExt for u8 {
     type Owned = u8;
 
     delegating_ascii_methods!();
-    delegating_ascii_ctype_methods!();
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 impl AsciiExt for char {
     type Owned = char;
 
     delegating_ascii_methods!();
-    delegating_ascii_ctype_methods!();
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 impl AsciiExt for [u8] {
     type Owned = Vec<u8>;
 
     delegating_ascii_methods!();
-
-    #[inline]
-    fn is_ascii_alphabetic(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_alphabetic())
-    }
-
-    #[inline]
-    fn is_ascii_uppercase(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_uppercase())
-    }
-
-    #[inline]
-    fn is_ascii_lowercase(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_lowercase())
-    }
-
-    #[inline]
-    fn is_ascii_alphanumeric(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_alphanumeric())
-    }
-
-    #[inline]
-    fn is_ascii_digit(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_digit())
-    }
-
-    #[inline]
-    fn is_ascii_hexdigit(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_hexdigit())
-    }
-
-    #[inline]
-    fn is_ascii_punctuation(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_punctuation())
-    }
-
-    #[inline]
-    fn is_ascii_graphic(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_graphic())
-    }
-
-    #[inline]
-    fn is_ascii_whitespace(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_whitespace())
-    }
-
-    #[inline]
-    fn is_ascii_control(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_control())
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 impl AsciiExt for str {
     type Owned = String;
 
     delegating_ascii_methods!();
-
-    #[inline]
-    fn is_ascii_alphabetic(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_alphabetic())
-    }
-
-    #[inline]
-    fn is_ascii_uppercase(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_uppercase())
-    }
-
-    #[inline]
-    fn is_ascii_lowercase(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_lowercase())
-    }
-
-    #[inline]
-    fn is_ascii_alphanumeric(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_alphanumeric())
-    }
-
-    #[inline]
-    fn is_ascii_digit(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_digit())
-    }
-
-    #[inline]
-    fn is_ascii_hexdigit(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_hexdigit())
-    }
-
-    #[inline]
-    fn is_ascii_punctuation(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_punctuation())
-    }
-
-    #[inline]
-    fn is_ascii_graphic(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_graphic())
-    }
-
-    #[inline]
-    fn is_ascii_whitespace(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_whitespace())
-    }
-
-    #[inline]
-    fn is_ascii_control(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_control())
-    }
-}
-
-/// An iterator over the escaped version of a byte.
-///
-/// This `struct` is created by the [`escape_default`] function. See its
-/// documentation for more.
-///
-/// [`escape_default`]: fn.escape_default.html
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct EscapeDefault {
-    range: Range<usize>,
-    data: [u8; 4],
-}
-
-/// Returns an iterator that produces an escaped version of a `u8`.
-///
-/// The default is chosen with a bias toward producing literals that are
-/// legal in a variety of languages, including C++11 and similar C-family
-/// languages. The exact rules are:
-///
-/// - Tab, CR and LF are escaped as '\t', '\r' and '\n' respectively.
-/// - Single-quote, double-quote and backslash chars are backslash-escaped.
-/// - Any other chars in the range [0x20,0x7e] are not escaped.
-/// - Any other chars are given hex escapes of the form '\xNN'.
-/// - Unicode escapes are never generated by this function.
-///
-/// # Examples
-///
-/// ```
-/// use std::ascii;
-///
-/// let escaped = ascii::escape_default(b'0').next().unwrap();
-/// assert_eq!(b'0', escaped);
-///
-/// let mut escaped = ascii::escape_default(b'\t');
-///
-/// assert_eq!(b'\\', escaped.next().unwrap());
-/// assert_eq!(b't', escaped.next().unwrap());
-///
-/// let mut escaped = ascii::escape_default(b'\r');
-///
-/// assert_eq!(b'\\', escaped.next().unwrap());
-/// assert_eq!(b'r', escaped.next().unwrap());
-///
-/// let mut escaped = ascii::escape_default(b'\n');
-///
-/// assert_eq!(b'\\', escaped.next().unwrap());
-/// assert_eq!(b'n', escaped.next().unwrap());
-///
-/// let mut escaped = ascii::escape_default(b'\'');
-///
-/// assert_eq!(b'\\', escaped.next().unwrap());
-/// assert_eq!(b'\'', escaped.next().unwrap());
-///
-/// let mut escaped = ascii::escape_default(b'"');
-///
-/// assert_eq!(b'\\', escaped.next().unwrap());
-/// assert_eq!(b'"', escaped.next().unwrap());
-///
-/// let mut escaped = ascii::escape_default(b'\\');
-///
-/// assert_eq!(b'\\', escaped.next().unwrap());
-/// assert_eq!(b'\\', escaped.next().unwrap());
-///
-/// let mut escaped = ascii::escape_default(b'\x9d');
-///
-/// assert_eq!(b'\\', escaped.next().unwrap());
-/// assert_eq!(b'x', escaped.next().unwrap());
-/// assert_eq!(b'9', escaped.next().unwrap());
-/// assert_eq!(b'd', escaped.next().unwrap());
-/// ```
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn escape_default(c: u8) -> EscapeDefault {
-    let (data, len) = match c {
-        b'\t' => ([b'\\', b't', 0, 0], 2),
-        b'\r' => ([b'\\', b'r', 0, 0], 2),
-        b'\n' => ([b'\\', b'n', 0, 0], 2),
-        b'\\' => ([b'\\', b'\\', 0, 0], 2),
-        b'\'' => ([b'\\', b'\'', 0, 0], 2),
-        b'"' => ([b'\\', b'"', 0, 0], 2),
-        b'\x20' ... b'\x7e' => ([c, 0, 0, 0], 1),
-        _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4),
-    };
-
-    return EscapeDefault { range: (0.. len), data: data };
-
-    fn hexify(b: u8) -> u8 {
-        match b {
-            0 ... 9 => b'0' + b,
-            _ => b'a' + b - 10,
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Iterator for EscapeDefault {
-    type Item = u8;
-    fn next(&mut self) -> Option<u8> { self.range.next().map(|i| self.data[i]) }
-    fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl DoubleEndedIterator for EscapeDefault {
-    fn next_back(&mut self) -> Option<u8> {
-        self.range.next_back().map(|i| self.data[i])
-    }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl ExactSizeIterator for EscapeDefault {}
-#[unstable(feature = "fused", issue = "35602")]
-impl FusedIterator for EscapeDefault {}
-
-#[stable(feature = "std_debug", since = "1.16.0")]
-impl fmt::Debug for EscapeDefault {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.pad("EscapeDefault { .. }")
-    }
-}
-
-
-#[cfg(test)]
-mod tests {
-    //! 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]
-    fn test_is_ascii() {
-        assert!(b"".is_ascii());
-        assert!(b"banana\0\x7F".is_ascii());
-        assert!(b"banana\0\x7F".iter().all(|b| b.is_ascii()));
-        assert!(!b"Vi\xe1\xbb\x87t Nam".is_ascii());
-        assert!(!b"Vi\xe1\xbb\x87t Nam".iter().all(|b| b.is_ascii()));
-        assert!(!b"\xe1\xbb\x87".iter().any(|b| b.is_ascii()));
-
-        assert!("".is_ascii());
-        assert!("banana\0\u{7F}".is_ascii());
-        assert!("banana\0\u{7F}".chars().all(|c| c.is_ascii()));
-        assert!(!"ประเทศไทย中华Việt Nam".chars().all(|c| c.is_ascii()));
-        assert!(!"ประเทศไทย中华ệ ".chars().any(|c| c.is_ascii()));
-    }
-
-    #[test]
-    fn test_to_ascii_uppercase() {
-        assert_eq!("url()URL()uRl()ürl".to_ascii_uppercase(), "URL()URL()URL()üRL");
-        assert_eq!("hıKß".to_ascii_uppercase(), "HıKß");
-
-        for i in 0..501 {
-            let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
-                        else { i };
-            assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_uppercase(),
-                       (from_u32(upper).unwrap()).to_string());
-        }
-    }
-
-    #[test]
-    fn test_to_ascii_lowercase() {
-        assert_eq!("url()URL()uRl()Ürl".to_ascii_lowercase(), "url()url()url()Ürl");
-        // Dotted capital I, Kelvin sign, Sharp S.
-        assert_eq!("HİKß".to_ascii_lowercase(), "hİKß");
-
-        for i in 0..501 {
-            let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
-                        else { i };
-            assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_lowercase(),
-                       (from_u32(lower).unwrap()).to_string());
-        }
-    }
-
-    #[test]
-    fn test_make_ascii_lower_case() {
-        macro_rules! test {
-            ($from: expr, $to: expr) => {
-                {
-                    let mut x = $from;
-                    x.make_ascii_lowercase();
-                    assert_eq!(x, $to);
-                }
-            }
-        }
-        test!(b'A', b'a');
-        test!(b'a', b'a');
-        test!(b'!', b'!');
-        test!('A', 'a');
-        test!('À', 'À');
-        test!('a', 'a');
-        test!('!', '!');
-        test!(b"H\xc3\x89".to_vec(), b"h\xc3\x89");
-        test!("HİKß".to_string(), "hİKß");
-    }
-
-
-    #[test]
-    fn test_make_ascii_upper_case() {
-        macro_rules! test {
-            ($from: expr, $to: expr) => {
-                {
-                    let mut x = $from;
-                    x.make_ascii_uppercase();
-                    assert_eq!(x, $to);
-                }
-            }
-        }
-        test!(b'a', b'A');
-        test!(b'A', b'A');
-        test!(b'!', b'!');
-        test!('a', 'A');
-        test!('à', 'à');
-        test!('A', 'A');
-        test!('!', '!');
-        test!(b"h\xc3\xa9".to_vec(), b"H\xc3\xa9");
-        test!("hıKß".to_string(), "HıKß");
-
-        let mut x = "Hello".to_string();
-        x[..3].make_ascii_uppercase();  // Test IndexMut on String.
-        assert_eq!(x, "HELlo")
-    }
-
-    #[test]
-    fn test_eq_ignore_ascii_case() {
-        assert!("url()URL()uRl()Ürl".eq_ignore_ascii_case("url()url()url()Ürl"));
-        assert!(!"Ürl".eq_ignore_ascii_case("ürl"));
-        // Dotted capital I, Kelvin sign, Sharp S.
-        assert!("HİKß".eq_ignore_ascii_case("hİKß"));
-        assert!(!"İ".eq_ignore_ascii_case("i"));
-        assert!(!"K".eq_ignore_ascii_case("k"));
-        assert!(!"ß".eq_ignore_ascii_case("s"));
-
-        for i in 0..501 {
-            let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
-                        else { i };
-            assert!((from_u32(i).unwrap()).to_string().eq_ignore_ascii_case(
-                    &from_u32(lower).unwrap().to_string()));
-        }
-    }
-
-    #[test]
-    fn inference_works() {
-        let x = "a".to_string();
-        x.eq_ignore_ascii_case("A");
-    }
-
-    // Shorthands used by the is_ascii_* tests.
-    macro_rules! assert_all {
-        ($what:ident, $($str:tt),+) => {{
-            $(
-                for b in $str.chars() {
-                    if !b.$what() {
-                        panic!("expected {}({}) but it isn't",
-                               stringify!($what), b);
-                    }
-                }
-                for b in $str.as_bytes().iter() {
-                    if !b.$what() {
-                        panic!("expected {}(0x{:02x})) but it isn't",
-                               stringify!($what), b);
-                    }
-                }
-                assert!($str.$what());
-                assert!($str.as_bytes().$what());
-            )+
-        }};
-        ($what:ident, $($str:tt),+,) => (assert_all!($what,$($str),+))
-    }
-    macro_rules! assert_none {
-        ($what:ident, $($str:tt),+) => {{
-            $(
-                for b in $str.chars() {
-                    if b.$what() {
-                        panic!("expected not-{}({}) but it is",
-                               stringify!($what), b);
-                    }
-                }
-                for b in $str.as_bytes().iter() {
-                    if b.$what() {
-                        panic!("expected not-{}(0x{:02x})) but it is",
-                               stringify!($what), b);
-                    }
-                }
-            )*
-        }};
-        ($what:ident, $($str:tt),+,) => (assert_none!($what,$($str),+))
-    }
-
-    #[test]
-    fn test_is_ascii_alphabetic() {
-        assert_all!(is_ascii_alphabetic,
-            "",
-            "abcdefghijklmnopqrstuvwxyz",
-            "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
-        );
-        assert_none!(is_ascii_alphabetic,
-            "0123456789",
-            "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
-            " \t\n\x0c\r",
-            "\x00\x01\x02\x03\x04\x05\x06\x07",
-            "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
-            "\x10\x11\x12\x13\x14\x15\x16\x17",
-            "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
-            "\x7f",
-        );
-    }
-
-    #[test]
-    fn test_is_ascii_uppercase() {
-        assert_all!(is_ascii_uppercase,
-            "",
-            "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
-        );
-        assert_none!(is_ascii_uppercase,
-            "abcdefghijklmnopqrstuvwxyz",
-            "0123456789",
-            "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
-            " \t\n\x0c\r",
-            "\x00\x01\x02\x03\x04\x05\x06\x07",
-            "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
-            "\x10\x11\x12\x13\x14\x15\x16\x17",
-            "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
-            "\x7f",
-        );
-    }
-
-    #[test]
-    fn test_is_ascii_lowercase() {
-        assert_all!(is_ascii_lowercase,
-            "abcdefghijklmnopqrstuvwxyz",
-        );
-        assert_none!(is_ascii_lowercase,
-            "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
-            "0123456789",
-            "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
-            " \t\n\x0c\r",
-            "\x00\x01\x02\x03\x04\x05\x06\x07",
-            "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
-            "\x10\x11\x12\x13\x14\x15\x16\x17",
-            "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
-            "\x7f",
-        );
-    }
-
-    #[test]
-    fn test_is_ascii_alphanumeric() {
-        assert_all!(is_ascii_alphanumeric,
-            "",
-            "abcdefghijklmnopqrstuvwxyz",
-            "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
-            "0123456789",
-        );
-        assert_none!(is_ascii_alphanumeric,
-            "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
-            " \t\n\x0c\r",
-            "\x00\x01\x02\x03\x04\x05\x06\x07",
-            "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
-            "\x10\x11\x12\x13\x14\x15\x16\x17",
-            "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
-            "\x7f",
-        );
-    }
-
-    #[test]
-    fn test_is_ascii_digit() {
-        assert_all!(is_ascii_digit,
-            "",
-            "0123456789",
-        );
-        assert_none!(is_ascii_digit,
-            "abcdefghijklmnopqrstuvwxyz",
-            "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
-            "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
-            " \t\n\x0c\r",
-            "\x00\x01\x02\x03\x04\x05\x06\x07",
-            "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
-            "\x10\x11\x12\x13\x14\x15\x16\x17",
-            "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
-            "\x7f",
-        );
-    }
-
-    #[test]
-    fn test_is_ascii_hexdigit() {
-        assert_all!(is_ascii_hexdigit,
-            "",
-            "0123456789",
-            "abcdefABCDEF",
-        );
-        assert_none!(is_ascii_hexdigit,
-            "ghijklmnopqrstuvwxyz",
-            "GHIJKLMNOQPRSTUVWXYZ",
-            "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
-            " \t\n\x0c\r",
-            "\x00\x01\x02\x03\x04\x05\x06\x07",
-            "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
-            "\x10\x11\x12\x13\x14\x15\x16\x17",
-            "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
-            "\x7f",
-        );
-    }
-
-    #[test]
-    fn test_is_ascii_punctuation() {
-        assert_all!(is_ascii_punctuation,
-            "",
-            "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
-        );
-        assert_none!(is_ascii_punctuation,
-            "abcdefghijklmnopqrstuvwxyz",
-            "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
-            "0123456789",
-            " \t\n\x0c\r",
-            "\x00\x01\x02\x03\x04\x05\x06\x07",
-            "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
-            "\x10\x11\x12\x13\x14\x15\x16\x17",
-            "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
-            "\x7f",
-        );
-    }
-
-    #[test]
-    fn test_is_ascii_graphic() {
-        assert_all!(is_ascii_graphic,
-            "",
-            "abcdefghijklmnopqrstuvwxyz",
-            "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
-            "0123456789",
-            "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
-        );
-        assert_none!(is_ascii_graphic,
-            " \t\n\x0c\r",
-            "\x00\x01\x02\x03\x04\x05\x06\x07",
-            "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
-            "\x10\x11\x12\x13\x14\x15\x16\x17",
-            "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
-            "\x7f",
-        );
-    }
-
-    #[test]
-    fn test_is_ascii_whitespace() {
-        assert_all!(is_ascii_whitespace,
-            "",
-            " \t\n\x0c\r",
-        );
-        assert_none!(is_ascii_whitespace,
-            "abcdefghijklmnopqrstuvwxyz",
-            "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
-            "0123456789",
-            "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
-            "\x00\x01\x02\x03\x04\x05\x06\x07",
-            "\x08\x0b\x0e\x0f",
-            "\x10\x11\x12\x13\x14\x15\x16\x17",
-            "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
-            "\x7f",
-        );
-    }
-
-    #[test]
-    fn test_is_ascii_control() {
-        assert_all!(is_ascii_control,
-            "",
-            "\x00\x01\x02\x03\x04\x05\x06\x07",
-            "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
-            "\x10\x11\x12\x13\x14\x15\x16\x17",
-            "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
-            "\x7f",
-        );
-        assert_none!(is_ascii_control,
-            "abcdefghijklmnopqrstuvwxyz",
-            "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
-            "0123456789",
-            "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
-            " ",
-        );
-    }
 }
diff --git a/src/libstd/build.rs b/src/libstd/build.rs
index a41c155f3fb..016e7adb4c9 100644
--- a/src/libstd/build.rs
+++ b/src/libstd/build.rs
@@ -11,22 +11,21 @@
 #![deny(warnings)]
 
 extern crate build_helper;
+extern crate cc;
 
+use build_helper::native_lib_boilerplate;
 use std::env;
-use std::process::Command;
-use build_helper::{run, native_lib_boilerplate};
+use std::fs::File;
 
 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("cloudabi") &&
         !target.contains("emscripten") &&
-        !target.contains("fuchsia") &&
         !target.contains("msvc") &&
         !target.contains("wasm32")
     {
-        let _ = build_libbacktrace(&host, &target);
+        let _ = build_libbacktrace(&target);
     }
 
     if target.contains("linux") {
@@ -68,13 +67,8 @@ fn main() {
         println!("cargo:rustc-link-lib=userenv");
         println!("cargo:rustc-link-lib=shell32");
     } else if target.contains("fuchsia") {
-        // use system-provided libbacktrace
-        if cfg!(feature = "backtrace") {
-            println!("cargo:rustc-link-lib=backtrace");
-        }
         println!("cargo:rustc-link-lib=zircon");
         println!("cargo:rustc-link-lib=fdio");
-        println!("cargo:rustc-link-lib=launchpad"); // for std::process
     } else if target.contains("cloudabi") {
         if cfg!(feature = "backtrace") {
             println!("cargo:rustc-link-lib=unwind");
@@ -84,25 +78,57 @@ fn main() {
     }
 }
 
-fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> {
-    let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", ".libs")?;
+fn build_libbacktrace(target: &str) -> Result<(), ()> {
+    let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", "")?;
+
+    let mut build = cc::Build::new();
+    build
+        .flag("-fvisibility=hidden")
+        .include("../libbacktrace")
+        .include(&native.out_dir)
+        .out_dir(&native.out_dir)
+        .warnings(false)
+        .file("../libbacktrace/alloc.c")
+        .file("../libbacktrace/backtrace.c")
+        .file("../libbacktrace/dwarf.c")
+        .file("../libbacktrace/fileline.c")
+        .file("../libbacktrace/posix.c")
+        .file("../libbacktrace/read.c")
+        .file("../libbacktrace/sort.c")
+        .file("../libbacktrace/state.c");
+
+    if target.contains("darwin") {
+        build.file("../libbacktrace/macho.c");
+    } else if target.contains("windows") {
+        build.file("../libbacktrace/pecoff.c");
+    } else {
+        build.file("../libbacktrace/elf.c");
+
+        let pointer_width = env::var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap();
+        if pointer_width == "64" {
+            build.define("BACKTRACE_ELF_SIZE", "64");
+        } else {
+            build.define("BACKTRACE_ELF_SIZE", "32");
+        }
+    }
 
-    run(Command::new("sh")
-                .current_dir(&native.out_dir)
-                .arg(native.src_dir.join("configure").to_str().unwrap()
-                                   .replace("C:\\", "/c/")
-                                   .replace("\\", "/"))
-                .arg("--with-pic")
-                .arg("--disable-multilib")
-                .arg("--disable-shared")
-                .arg("--disable-host-shared")
-                .arg(format!("--host={}", build_helper::gnu_target(target)))
-                .arg(format!("--build={}", build_helper::gnu_target(host)))
-                .env("CFLAGS", env::var("CFLAGS").unwrap_or_default() + " -fvisibility=hidden"));
+    File::create(native.out_dir.join("backtrace-supported.h")).unwrap();
+    build.define("BACKTRACE_SUPPORTED", "1");
+    build.define("BACKTRACE_USES_MALLOC", "1");
+    build.define("BACKTRACE_SUPPORTS_THREADS", "0");
+    build.define("BACKTRACE_SUPPORTS_DATA", "0");
+
+    File::create(native.out_dir.join("config.h")).unwrap();
+    if !target.contains("apple-ios") &&
+       !target.contains("solaris") &&
+       !target.contains("redox") &&
+       !target.contains("android") &&
+       !target.contains("haiku") {
+        build.define("HAVE_DL_ITERATE_PHDR", "1");
+    }
+    build.define("_GNU_SOURCE", "1");
+    build.define("_LARGE_FILES", "1");
 
-    run(Command::new(build_helper::make(host))
-                .current_dir(&native.out_dir)
-                .arg(format!("INCDIR={}", native.src_dir.display()))
-                .arg("-j").arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set")));
+    build.compile("backtrace");
     Ok(())
 }
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 4e5385c17e9..91912e5f241 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -11,6 +11,7 @@
 use self::Entry::*;
 use self::VacantEntryState::*;
 
+use collections::CollectionAllocErr;
 use cell::Cell;
 use borrow::Borrow;
 use cmp::max;
@@ -19,12 +20,13 @@ use fmt::{self, Debug};
 use hash::{Hash, Hasher, BuildHasher, SipHasher13};
 use iter::{FromIterator, FusedIterator};
 use mem::{self, replace};
-use ops::{Deref, Index, InPlace, Place, Placer};
-use ptr;
+use ops::{Deref, Index};
 use sys;
 
-use super::table::{self, Bucket, EmptyBucket, FullBucket, FullBucketMut, RawTable, SafeHash};
+use super::table::{self, Bucket, EmptyBucket, Fallibility, FullBucket, FullBucketMut, RawTable,
+                   SafeHash};
 use super::table::BucketState::{Empty, Full};
+use super::table::Fallibility::{Fallible, Infallible};
 
 const MIN_NONZERO_RAW_CAPACITY: usize = 32;     // must be a power of two
 
@@ -33,6 +35,7 @@ const MIN_NONZERO_RAW_CAPACITY: usize = 32;     // must be a power of two
 struct DefaultResizePolicy;
 
 impl DefaultResizePolicy {
+    #[inline]
     fn new() -> DefaultResizePolicy {
         DefaultResizePolicy
     }
@@ -42,21 +45,28 @@ impl DefaultResizePolicy {
     /// provide that capacity, accounting for maximum loading. The raw capacity
     /// is always zero or a power of two.
     #[inline]
-    fn raw_capacity(&self, len: usize) -> usize {
+    fn try_raw_capacity(&self, len: usize) -> Result<usize, CollectionAllocErr> {
         if len == 0 {
-            0
+            Ok(0)
         } else {
             // 1. Account for loading: `raw_capacity >= len * 1.1`.
             // 2. Ensure it is a power of two.
             // 3. Ensure it is at least the minimum size.
-            let mut raw_cap = len * 11 / 10;
-            assert!(raw_cap >= len, "raw_cap overflow");
-            raw_cap = raw_cap.checked_next_power_of_two().expect("raw_capacity overflow");
+            let mut raw_cap = len.checked_mul(11)
+                .map(|l| l / 10)
+                .and_then(|l| l.checked_next_power_of_two())
+                .ok_or(CollectionAllocErr::CapacityOverflow)?;
+
             raw_cap = max(MIN_NONZERO_RAW_CAPACITY, raw_cap);
-            raw_cap
+            Ok(raw_cap)
         }
     }
 
+    #[inline]
+    fn raw_capacity(&self, len: usize) -> usize {
+        self.try_raw_capacity(len).expect("raw_capacity overflow")
+    }
+
     /// The capacity of the given raw capacity.
     #[inline]
     fn capacity(&self, raw_cap: usize) -> usize {
@@ -266,17 +276,31 @@ const DISPLACEMENT_THRESHOLD: usize = 128;
 /// ```
 /// use std::collections::HashMap;
 ///
-/// // type inference lets us omit an explicit type signature (which
-/// // would be `HashMap<&str, &str>` in this example).
+/// // Type inference lets us omit an explicit type signature (which
+/// // would be `HashMap<String, String>` in this example).
 /// let mut book_reviews = HashMap::new();
 ///
-/// // review some books.
-/// book_reviews.insert("Adventures of Huckleberry Finn",    "My favorite book.");
-/// book_reviews.insert("Grimms' Fairy Tales",               "Masterpiece.");
-/// book_reviews.insert("Pride and Prejudice",               "Very enjoyable.");
-/// book_reviews.insert("The Adventures of Sherlock Holmes", "Eye lyked it alot.");
+/// // Review some books.
+/// book_reviews.insert(
+///     "Adventures of Huckleberry Finn".to_string(),
+///     "My favorite book.".to_string(),
+/// );
+/// book_reviews.insert(
+///     "Grimms' Fairy Tales".to_string(),
+///     "Masterpiece.".to_string(),
+/// );
+/// book_reviews.insert(
+///     "Pride and Prejudice".to_string(),
+///     "Very enjoyable.".to_string(),
+/// );
+/// book_reviews.insert(
+///     "The Adventures of Sherlock Holmes".to_string(),
+///     "Eye lyked it alot.".to_string(),
+/// );
 ///
-/// // check for a specific one.
+/// // Check for a specific one.
+/// // When collections store owned values (String), they can still be
+/// // queried using references (&str).
 /// if !book_reviews.contains_key("Les Misérables") {
 ///     println!("We've got {} reviews, but Les Misérables ain't one.",
 ///              book_reviews.len());
@@ -285,16 +309,16 @@ const DISPLACEMENT_THRESHOLD: usize = 128;
 /// // oops, this review has a lot of spelling mistakes, let's delete it.
 /// book_reviews.remove("The Adventures of Sherlock Holmes");
 ///
-/// // look up the values associated with some keys.
+/// // Look up the values associated with some keys.
 /// let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"];
-/// for book in &to_find {
+/// for &book in &to_find {
 ///     match book_reviews.get(book) {
 ///         Some(review) => println!("{}: {}", book, review),
 ///         None => println!("{} is unreviewed.", book)
 ///     }
 /// }
 ///
-/// // iterate over everything.
+/// // Iterate over everything.
 /// for (book, review) in &book_reviews {
 ///     println!("{}: \"{}\"", book, review);
 /// }
@@ -398,8 +422,9 @@ pub struct HashMap<K, V, S = RandomState> {
 }
 
 /// Search for a pre-hashed key.
+/// If you don't already know the hash, use search or search_mut instead
 #[inline]
-fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> InternalEntry<K, V, M>
+fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, is_match: F) -> InternalEntry<K, V, M>
     where M: Deref<Target = RawTable<K, V>>,
           F: FnMut(&K) -> bool
 {
@@ -410,6 +435,18 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> Inter
         return InternalEntry::TableIsEmpty;
     }
 
+    search_hashed_nonempty(table, hash, is_match)
+}
+
+/// Search for a pre-hashed key when the hash map is known to be non-empty.
+#[inline]
+fn search_hashed_nonempty<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F)
+    -> InternalEntry<K, V, M>
+    where M: Deref<Target = RawTable<K, V>>,
+          F: FnMut(&K) -> bool
+{
+    // Do not check the capacity as an extra branch could slow the lookup.
+
     let size = table.size();
     let mut probe = Bucket::new(table, hash);
     let mut displacement = 0;
@@ -543,24 +580,36 @@ impl<K, V, S> HashMap<K, V, S>
     }
 
     /// Search for a key, yielding the index if it's found in the hashtable.
-    /// If you already have the hash for the key lying around, use
-    /// search_hashed.
+    /// If you already have the hash for the key lying around, or if you need an
+    /// InternalEntry, use search_hashed or search_hashed_nonempty.
     #[inline]
-    fn search<'a, Q: ?Sized>(&'a self, q: &Q) -> InternalEntry<K, V, &'a RawTable<K, V>>
+    fn search<'a, Q: ?Sized>(&'a self, q: &Q)
+        -> Option<FullBucket<K, V, &'a RawTable<K, V>>>
         where K: Borrow<Q>,
               Q: Eq + Hash
     {
+        if self.is_empty() {
+            return None;
+        }
+
         let hash = self.make_hash(q);
-        search_hashed(&self.table, hash, |k| q.eq(k.borrow()))
+        search_hashed_nonempty(&self.table, hash, |k| q.eq(k.borrow()))
+            .into_occupied_bucket()
     }
 
     #[inline]
-    fn search_mut<'a, Q: ?Sized>(&'a mut self, q: &Q) -> InternalEntry<K, V, &'a mut RawTable<K, V>>
+    fn search_mut<'a, Q: ?Sized>(&'a mut self, q: &Q)
+        -> Option<FullBucket<K, V, &'a mut RawTable<K, V>>>
         where K: Borrow<Q>,
               Q: Eq + Hash
     {
+        if self.is_empty() {
+            return None;
+        }
+
         let hash = self.make_hash(q);
-        search_hashed(&mut self.table, hash, |k| q.eq(k.borrow()))
+        search_hashed_nonempty(&mut self.table, hash, |k| q.eq(k.borrow()))
+            .into_occupied_bucket()
     }
 
     // The caller should ensure that invariants by Robin Hood Hashing hold
@@ -595,7 +644,7 @@ impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
     ///
     /// ```
     /// use std::collections::HashMap;
-    /// let mut map: HashMap<&str, isize> = HashMap::new();
+    /// let mut map: HashMap<&str, i32> = HashMap::new();
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -612,7 +661,7 @@ impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
     ///
     /// ```
     /// use std::collections::HashMap;
-    /// let mut map: HashMap<&str, isize> = HashMap::with_capacity(10);
+    /// let mut map: HashMap<&str, i32> = HashMap::with_capacity(10);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -699,7 +748,7 @@ impl<K, V, S> HashMap<K, V, S>
     /// use std::collections::hash_map::RandomState;
     ///
     /// let hasher = RandomState::new();
-    /// let map: HashMap<isize, isize> = HashMap::with_hasher(hasher);
+    /// let map: HashMap<i32, i32> = HashMap::with_hasher(hasher);
     /// let hasher: &RandomState = map.hasher();
     /// ```
     #[stable(feature = "hashmap_public_hasher", since = "1.9.0")]
@@ -716,7 +765,7 @@ impl<K, V, S> HashMap<K, V, S>
     ///
     /// ```
     /// use std::collections::HashMap;
-    /// let map: HashMap<isize, isize> = HashMap::with_capacity(100);
+    /// let map: HashMap<i32, i32> = HashMap::with_capacity(100);
     /// assert!(map.capacity() >= 100);
     /// ```
     #[inline]
@@ -745,22 +794,57 @@ impl<K, V, S> HashMap<K, V, S>
     ///
     /// ```
     /// use std::collections::HashMap;
-    /// let mut map: HashMap<&str, isize> = HashMap::new();
+    /// let mut map: HashMap<&str, i32> = HashMap::new();
     /// map.reserve(10);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve(&mut self, additional: usize) {
+        match self.reserve_internal(additional, Infallible) {
+            Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
+            Err(CollectionAllocErr::AllocErr) => unreachable!(),
+            Ok(()) => { /* yay */ }
+        }
+    }
+
+    /// Tries to reserve capacity for at least `additional` more elements to be inserted
+    /// in the given `HashMap<K,V>`. The collection may reserve more space to avoid
+    /// frequent reallocations.
+    ///
+    /// # Errors
+    ///
+    /// If the capacity overflows, or the allocator reports a failure, then an error
+    /// is returned.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(try_reserve)]
+    /// use std::collections::HashMap;
+    /// let mut map: HashMap<&str, isize> = HashMap::new();
+    /// map.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?");
+    /// ```
+    #[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
+    pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
+        self.reserve_internal(additional, Fallible)
+    }
+
+    fn reserve_internal(&mut self, additional: usize, fallibility: Fallibility)
+        -> Result<(), CollectionAllocErr> {
+
         let remaining = self.capacity() - self.len(); // this can't overflow
         if remaining < additional {
-            let min_cap = self.len().checked_add(additional).expect("reserve overflow");
-            let raw_cap = self.resize_policy.raw_capacity(min_cap);
-            self.resize(raw_cap);
+            let min_cap = self.len()
+                .checked_add(additional)
+                .ok_or(CollectionAllocErr::CapacityOverflow)?;
+            let raw_cap = self.resize_policy.try_raw_capacity(min_cap)?;
+            self.try_resize(raw_cap, fallibility)?;
         } else if self.table.tag() && remaining <= self.len() {
             // Probe sequence is too long and table is half full,
             // resize early to reduce probing length.
             let new_capacity = self.table.capacity() * 2;
-            self.resize(new_capacity);
+            self.try_resize(new_capacity, fallibility)?;
         }
+        Ok(())
     }
 
     /// Resizes the internal vectors to a new capacity. It's your
@@ -770,15 +854,25 @@ impl<K, V, S> HashMap<K, V, S>
     ///   2) Ensure `new_raw_cap` is a power of two or zero.
     #[inline(never)]
     #[cold]
-    fn resize(&mut self, new_raw_cap: usize) {
+    fn try_resize(
+        &mut self,
+        new_raw_cap: usize,
+        fallibility: Fallibility,
+    ) -> Result<(), CollectionAllocErr> {
         assert!(self.table.size() <= new_raw_cap);
         assert!(new_raw_cap.is_power_of_two() || new_raw_cap == 0);
 
-        let mut old_table = replace(&mut self.table, RawTable::new(new_raw_cap));
+        let mut old_table = replace(
+            &mut self.table,
+            match fallibility {
+                Infallible => RawTable::new(new_raw_cap),
+                Fallible => RawTable::try_new(new_raw_cap)?,
+            }
+        );
         let old_size = old_table.size();
 
         if old_table.size() == 0 {
-            return;
+            return Ok(());
         }
 
         let mut bucket = Bucket::head_bucket(&mut old_table);
@@ -813,6 +907,7 @@ impl<K, V, S> HashMap<K, V, S>
         }
 
         assert_eq!(self.table.size(), old_size);
+        Ok(())
     }
 
     /// Shrinks the capacity of the map as much as possible. It will drop
@@ -824,7 +919,7 @@ impl<K, V, S> HashMap<K, V, S>
     /// ```
     /// use std::collections::HashMap;
     ///
-    /// let mut map: HashMap<isize, isize> = HashMap::with_capacity(100);
+    /// let mut map: HashMap<i32, i32> = HashMap::with_capacity(100);
     /// map.insert(1, 2);
     /// map.insert(3, 4);
     /// assert!(map.capacity() >= 100);
@@ -847,6 +942,46 @@ impl<K, V, S> HashMap<K, V, S>
         }
     }
 
+    /// Shrinks the capacity of the map with a lower limit. It will drop
+    /// down no lower than the supplied limit while maintaining the internal rules
+    /// and possibly leaving some space in accordance with the resize policy.
+    ///
+    /// Panics if the current capacity is smaller than the supplied
+    /// minimum capacity.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(shrink_to)]
+    /// use std::collections::HashMap;
+    ///
+    /// let mut map: HashMap<i32, i32> = HashMap::with_capacity(100);
+    /// map.insert(1, 2);
+    /// map.insert(3, 4);
+    /// assert!(map.capacity() >= 100);
+    /// map.shrink_to(10);
+    /// assert!(map.capacity() >= 10);
+    /// map.shrink_to(0);
+    /// assert!(map.capacity() >= 2);
+    /// ```
+    #[unstable(feature = "shrink_to", reason = "new API", issue="0")]
+    pub fn shrink_to(&mut self, min_capacity: usize) {
+        assert!(self.capacity() >= min_capacity, "Tried to shrink to a larger capacity");
+
+        let new_raw_cap = self.resize_policy.raw_capacity(max(self.len(), min_capacity));
+        if self.raw_capacity() != new_raw_cap {
+            let old_table = replace(&mut self.table, RawTable::new(new_raw_cap));
+            let old_size = old_table.size();
+
+            // Shrink the table. Naive algorithm for resizing:
+            for (h, k, v) in old_table.into_iter() {
+                self.insert_hashed_nocheck(h, k, v);
+            }
+
+            debug_assert_eq!(self.table.size(), old_size);
+        }
+    }
+
     /// Insert a pre-hashed key-value pair, without first checking
     /// that there's enough room in the buckets. Returns a reference to the
     /// newly insert value.
@@ -1118,7 +1253,35 @@ impl<K, V, S> HashMap<K, V, S>
         where K: Borrow<Q>,
               Q: Hash + Eq
     {
-        self.search(k).into_occupied_bucket().map(|bucket| bucket.into_refs().1)
+        self.search(k).map(|bucket| bucket.into_refs().1)
+    }
+
+    /// Returns the key-value pair corresponding to the supplied key.
+    ///
+    /// The supplied key may be any borrowed form of the map's key type, but
+    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
+    /// the key type.
+    ///
+    /// [`Eq`]: ../../std/cmp/trait.Eq.html
+    /// [`Hash`]: ../../std/hash/trait.Hash.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(map_get_key_value)]
+    /// use std::collections::HashMap;
+    ///
+    /// let mut map = HashMap::new();
+    /// map.insert(1, "a");
+    /// assert_eq!(map.get_key_value(&1), Some((&1, &"a")));
+    /// assert_eq!(map.get_key_value(&2), None);
+    /// ```
+    #[unstable(feature = "map_get_key_value", issue = "49347")]
+    pub fn get_key_value<Q: ?Sized>(&self, k: &Q) -> Option<(&K, &V)>
+        where K: Borrow<Q>,
+              Q: Hash + Eq
+    {
+        self.search(k).map(|bucket| bucket.into_refs())
     }
 
     /// Returns true if the map contains a value for the specified key.
@@ -1145,7 +1308,7 @@ impl<K, V, S> HashMap<K, V, S>
         where K: Borrow<Q>,
               Q: Hash + Eq
     {
-        self.search(k).into_occupied_bucket().is_some()
+        self.search(k).is_some()
     }
 
     /// Returns a mutable reference to the value corresponding to the key.
@@ -1174,7 +1337,7 @@ impl<K, V, S> HashMap<K, V, S>
         where K: Borrow<Q>,
               Q: Hash + Eq
     {
-        self.search_mut(k).into_occupied_bucket().map(|bucket| bucket.into_mut_refs().1)
+        self.search_mut(k).map(|bucket| bucket.into_mut_refs().1)
     }
 
     /// Inserts a key-value pair into the map.
@@ -1234,11 +1397,7 @@ impl<K, V, S> HashMap<K, V, S>
         where K: Borrow<Q>,
               Q: Hash + Eq
     {
-        if self.table.size() == 0 {
-            return None;
-        }
-
-        self.search_mut(k).into_occupied_bucket().map(|bucket| pop_internal(bucket).1)
+        self.search_mut(k).map(|bucket| pop_internal(bucket).1)
     }
 
     /// Removes a key from the map, returning the stored key and value if the
@@ -1254,7 +1413,6 @@ impl<K, V, S> HashMap<K, V, S>
     /// # Examples
     ///
     /// ```
-    /// #![feature(hash_map_remove_entry)]
     /// use std::collections::HashMap;
     ///
     /// # fn main() {
@@ -1264,17 +1422,12 @@ impl<K, V, S> HashMap<K, V, S>
     /// assert_eq!(map.remove(&1), None);
     /// # }
     /// ```
-    #[unstable(feature = "hash_map_remove_entry", issue = "46344")]
+    #[stable(feature = "hash_map_remove_entry", since = "1.27.0")]
     pub fn remove_entry<Q: ?Sized>(&mut self, k: &Q) -> Option<(K, V)>
         where K: Borrow<Q>,
               Q: Hash + Eq
     {
-        if self.table.size() == 0 {
-            return None;
-        }
-
         self.search_mut(k)
-            .into_occupied_bucket()
             .map(|bucket| {
                 let (k, v, _) = pop_internal(bucket);
                 (k, v)
@@ -1290,7 +1443,7 @@ impl<K, V, S> HashMap<K, V, S>
     /// ```
     /// use std::collections::HashMap;
     ///
-    /// let mut map: HashMap<isize, isize> = (0..8).map(|x|(x, x*10)).collect();
+    /// let mut map: HashMap<i32, i32> = (0..8).map(|x|(x, x*10)).collect();
     /// map.retain(|&k, _| k % 2 == 0);
     /// assert_eq!(map.len(), 4);
     /// ```
@@ -1384,9 +1537,14 @@ impl<'a, K, Q: ?Sized, V, S> Index<&'a Q> for HashMap<K, V, S>
 {
     type Output = V;
 
+    /// Returns a reference to the value corresponding to the supplied key.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the key is not present in the `HashMap`.
     #[inline]
-    fn index(&self, index: &Q) -> &V {
-        self.get(index).expect("no entry found for key")
+    fn index(&self, key: &Q) -> &V {
+        self.get(key).expect("no entry found for key")
     }
 }
 
@@ -1701,7 +1859,7 @@ impl<K, V, S> IntoIterator for HashMap<K, V, S>
     /// map.insert("c", 3);
     ///
     /// // Not possible with .iter()
-    /// let vec: Vec<(&str, isize)> = map.into_iter().collect();
+    /// let vec: Vec<(&str, i32)> = map.into_iter().collect();
     /// ```
     fn into_iter(self) -> IntoIter<K, V> {
         IntoIter { inner: self.table.into_iter() }
@@ -1729,7 +1887,7 @@ impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
     }
 }
 
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
 impl<'a, K, V> FusedIterator for Iter<'a, K, V> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1752,7 +1910,7 @@ impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
         self.inner.len()
     }
 }
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
 impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {}
 
 #[stable(feature = "std_debug", since = "1.16.0")]
@@ -1787,7 +1945,7 @@ impl<K, V> ExactSizeIterator for IntoIter<K, V> {
         self.inner.len()
     }
 }
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
 impl<K, V> FusedIterator for IntoIter<K, V> {}
 
 #[stable(feature = "std_debug", since = "1.16.0")]
@@ -1819,7 +1977,7 @@ impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> {
         self.inner.len()
     }
 }
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
 impl<'a, K, V> FusedIterator for Keys<'a, K, V> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1842,7 +2000,7 @@ impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {
         self.inner.len()
     }
 }
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
 impl<'a, K, V> FusedIterator for Values<'a, K, V> {}
 
 #[stable(feature = "map_values_mut", since = "1.10.0")]
@@ -1865,7 +2023,7 @@ impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> {
         self.inner.len()
     }
 }
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
 impl<'a, K, V> FusedIterator for ValuesMut<'a, K, V> {}
 
 #[stable(feature = "std_debug", since = "1.16.0")]
@@ -1900,7 +2058,7 @@ impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
         self.inner.len()
     }
 }
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
 impl<'a, K, V> FusedIterator for Drain<'a, K, V> {}
 
 #[stable(feature = "std_debug", since = "1.16.0")]
@@ -1915,80 +2073,6 @@ impl<'a, K, V> fmt::Debug for Drain<'a, K, V>
     }
 }
 
-/// A place for insertion to a `Entry`.
-///
-/// See [`HashMap::entry`](struct.HashMap.html#method.entry) for details.
-#[must_use = "places do nothing unless written to with `<-` syntax"]
-#[unstable(feature = "collection_placement",
-           reason = "struct name and placement protocol is subject to change",
-           issue = "30172")]
-pub struct EntryPlace<'a, K: 'a, V: 'a> {
-    bucket: FullBucketMut<'a, K, V>,
-}
-
-#[unstable(feature = "collection_placement",
-           reason = "struct name and placement protocol is subject to change",
-           issue = "30172")]
-impl<'a, K: 'a + Debug, V: 'a + Debug> Debug for EntryPlace<'a, K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("EntryPlace")
-            .field("key", self.bucket.read().0)
-            .field("value", self.bucket.read().1)
-            .finish()
-    }
-}
-
-#[unstable(feature = "collection_placement",
-           reason = "struct name and placement protocol is subject to change",
-           issue = "30172")]
-impl<'a, K, V> Drop for EntryPlace<'a, K, V> {
-    fn drop(&mut self) {
-        // Inplacement insertion failed. Only key need to drop.
-        // The value is failed to insert into map.
-        unsafe { self.bucket.remove_key() };
-    }
-}
-
-#[unstable(feature = "collection_placement",
-           reason = "placement protocol is subject to change",
-           issue = "30172")]
-impl<'a, K, V> Placer<V> for Entry<'a, K, V> {
-    type Place = EntryPlace<'a, K, V>;
-
-    fn make_place(self) -> EntryPlace<'a, K, V> {
-        let b = match self {
-            Occupied(mut o) => {
-                unsafe { ptr::drop_in_place(o.elem.read_mut().1); }
-                o.elem
-            }
-            Vacant(v) => {
-                unsafe { v.insert_key() }
-            }
-        };
-        EntryPlace { bucket: b }
-    }
-}
-
-#[unstable(feature = "collection_placement",
-           reason = "placement protocol is subject to change",
-           issue = "30172")]
-impl<'a, K, V> Place<V> for EntryPlace<'a, K, V> {
-    fn pointer(&mut self) -> *mut V {
-        self.bucket.read_mut().1
-    }
-}
-
-#[unstable(feature = "collection_placement",
-           reason = "placement protocol is subject to change",
-           issue = "30172")]
-impl<'a, K, V> InPlace<V> for EntryPlace<'a, K, V> {
-    type Owner = ();
-
-    unsafe fn finalize(self) {
-        mem::forget(self);
-    }
-}
-
 impl<'a, K, V> Entry<'a, K, V> {
     #[stable(feature = "rust1", since = "1.0.0")]
     /// Ensures a value is in the entry by inserting the default if empty, and returns
@@ -2061,7 +2145,6 @@ impl<'a, K, V> Entry<'a, K, V> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(entry_and_modify)]
     /// use std::collections::HashMap;
     ///
     /// let mut map: HashMap<&str, u32> = HashMap::new();
@@ -2076,9 +2159,9 @@ impl<'a, K, V> Entry<'a, K, V> {
     ///    .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)
+    #[stable(feature = "entry_and_modify", since = "1.26.0")]
+    pub fn and_modify<F>(self, f: F) -> Self
+        where F: FnOnce(&mut V)
     {
         match self {
             Occupied(mut entry) => {
@@ -2092,14 +2175,13 @@ impl<'a, K, V> Entry<'a, K, V> {
 }
 
 impl<'a, K, V: Default> Entry<'a, K, V> {
-    #[unstable(feature = "entry_or_default", issue = "44324")]
+    #[stable(feature = "entry_or_default", since = "1.28.0")]
     /// Ensures a value is in the entry by inserting the default value if empty,
     /// and returns a mutable reference to the value in the entry.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(entry_or_default)]
     /// # fn main() {
     /// use std::collections::HashMap;
     ///
@@ -2115,7 +2197,6 @@ impl<'a, K, V: Default> Entry<'a, K, V> {
             Vacant(entry) => entry.insert(Default::default()),
         }
     }
-
 }
 
 impl<'a, K, V> OccupiedEntry<'a, K, V> {
@@ -2181,6 +2262,11 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
 
     /// Gets a mutable reference to the value in the entry.
     ///
+    /// If you need a reference to the `OccupiedEntry` which may outlive the
+    /// destruction of the `Entry` value, see [`into_mut`].
+    ///
+    /// [`into_mut`]: #method.into_mut
+    ///
     /// # Examples
     ///
     /// ```
@@ -2192,10 +2278,14 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     ///
     /// assert_eq!(map["poneyland"], 12);
     /// if let Entry::Occupied(mut o) = map.entry("poneyland") {
-    ///      *o.get_mut() += 10;
+    ///     *o.get_mut() += 10;
+    ///     assert_eq!(*o.get(), 22);
+    ///
+    ///     // We can use the same Entry multiple times.
+    ///     *o.get_mut() += 2;
     /// }
     ///
-    /// assert_eq!(map["poneyland"], 22);
+    /// assert_eq!(map["poneyland"], 24);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_mut(&mut self) -> &mut V {
@@ -2205,6 +2295,10 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     /// Converts the OccupiedEntry into a mutable reference to the value in the entry
     /// with a lifetime bound to the map itself.
     ///
+    /// If you need multiple references to the `OccupiedEntry`, see [`get_mut`].
+    ///
+    /// [`get_mut`]: #method.get_mut
+    ///
     /// # Examples
     ///
     /// ```
@@ -2412,26 +2506,6 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
         };
         b.into_mut_refs().1
     }
-
-    // Only used for InPlacement insert. Avoid unnecessary value copy.
-    // The value remains uninitialized.
-    unsafe fn insert_key(self) -> FullBucketMut<'a, K, V> {
-        match self.elem {
-            NeqElem(mut bucket, disp) => {
-                if disp >= DISPLACEMENT_THRESHOLD {
-                    bucket.table_mut().set_tag(true);
-                }
-                let uninit = mem::uninitialized();
-                robin_hood(bucket, disp, self.hash, self.key, uninit)
-            },
-            NoElem(mut bucket, disp) => {
-                if disp >= DISPLACEMENT_THRESHOLD {
-                    bucket.table_mut().set_tag(true);
-                }
-                bucket.put_key(self.hash, self.key)
-            },
-        }
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2627,15 +2701,11 @@ impl<K, S, Q: ?Sized> super::Recover<Q> for HashMap<K, (), S>
 
     #[inline]
     fn get(&self, key: &Q) -> Option<&K> {
-        self.search(key).into_occupied_bucket().map(|bucket| bucket.into_refs().0)
+        self.search(key).map(|bucket| bucket.into_refs().0)
     }
 
     fn take(&mut self, key: &Q) -> Option<K> {
-        if self.table.size() == 0 {
-            return None;
-        }
-
-        self.search_mut(key).into_occupied_bucket().map(|bucket| pop_internal(bucket).0)
+        self.search_mut(key).map(|bucket| pop_internal(bucket).0)
     }
 
     #[inline]
@@ -2700,7 +2770,9 @@ mod test_map {
     use super::RandomState;
     use cell::RefCell;
     use rand::{thread_rng, Rng};
-    use panic;
+    use realstd::collections::CollectionAllocErr::*;
+    use realstd::mem::size_of;
+    use realstd::usize;
 
     #[test]
     fn test_zero_capacities() {
@@ -2770,24 +2842,24 @@ mod test_map {
         assert_eq!(m2.len(), 2);
     }
 
-    thread_local! { static DROP_VECTOR: RefCell<Vec<isize>> = RefCell::new(Vec::new()) }
+    thread_local! { static DROP_VECTOR: RefCell<Vec<i32>> = RefCell::new(Vec::new()) }
 
     #[derive(Hash, PartialEq, Eq)]
-    struct Dropable {
+    struct Droppable {
         k: usize,
     }
 
-    impl Dropable {
-        fn new(k: usize) -> Dropable {
+    impl Droppable {
+        fn new(k: usize) -> Droppable {
             DROP_VECTOR.with(|slot| {
                 slot.borrow_mut()[k] += 1;
             });
 
-            Dropable { k: k }
+            Droppable { k: k }
         }
     }
 
-    impl Drop for Dropable {
+    impl Drop for Droppable {
         fn drop(&mut self) {
             DROP_VECTOR.with(|slot| {
                 slot.borrow_mut()[self.k] -= 1;
@@ -2795,9 +2867,9 @@ mod test_map {
         }
     }
 
-    impl Clone for Dropable {
-        fn clone(&self) -> Dropable {
-            Dropable::new(self.k)
+    impl Clone for Droppable {
+        fn clone(&self) -> Droppable {
+            Droppable::new(self.k)
         }
     }
 
@@ -2817,8 +2889,8 @@ mod test_map {
             });
 
             for i in 0..100 {
-                let d1 = Dropable::new(i);
-                let d2 = Dropable::new(i + 100);
+                let d1 = Droppable::new(i);
+                let d2 = Droppable::new(i + 100);
                 m.insert(d1, d2);
             }
 
@@ -2829,7 +2901,7 @@ mod test_map {
             });
 
             for i in 0..50 {
-                let k = Dropable::new(i);
+                let k = Droppable::new(i);
                 let v = m.remove(&k);
 
                 assert!(v.is_some());
@@ -2876,8 +2948,8 @@ mod test_map {
             });
 
             for i in 0..100 {
-                let d1 = Dropable::new(i);
-                let d2 = Dropable::new(i + 100);
+                let d1 = Droppable::new(i);
+                let d2 = Droppable::new(i + 100);
                 hm.insert(d1, d2);
             }
 
@@ -2927,13 +2999,13 @@ mod test_map {
 
     #[test]
     fn test_empty_remove() {
-        let mut m: HashMap<isize, bool> = HashMap::new();
+        let mut m: HashMap<i32, bool> = HashMap::new();
         assert_eq!(m.remove(&0), None);
     }
 
     #[test]
     fn test_empty_entry() {
-        let mut m: HashMap<isize, bool> = HashMap::new();
+        let mut m: HashMap<i32, bool> = HashMap::new();
         match m.entry(0) {
             Occupied(_) => panic!(),
             Vacant(_) => {}
@@ -2944,7 +3016,7 @@ mod test_map {
 
     #[test]
     fn test_empty_iter() {
-        let mut m: HashMap<isize, bool> = HashMap::new();
+        let mut m: HashMap<i32, bool> = HashMap::new();
         assert_eq!(m.drain().next(), None);
         assert_eq!(m.keys().next(), None);
         assert_eq!(m.values().next(), None);
@@ -3445,7 +3517,7 @@ mod test_map {
     fn test_entry_take_doesnt_corrupt() {
         #![allow(deprecated)] //rand
         // Test for #19292
-        fn check(m: &HashMap<isize, ()>) {
+        fn check(m: &HashMap<i32, ()>) {
             for k in m.keys() {
                 assert!(m.contains_key(k),
                         "{} is in keys() but not in the map?", k);
@@ -3554,7 +3626,7 @@ mod test_map {
 
     #[test]
     fn test_retain() {
-        let mut map: HashMap<isize, isize> = (0..100).map(|x|(x, x*10)).collect();
+        let mut map: HashMap<i32, i32> = (0..100).map(|x|(x, x*10)).collect();
 
         map.retain(|&k, _| k % 2 == 0);
         assert_eq!(map.len(), 50);
@@ -3584,55 +3656,31 @@ mod test_map {
     }
 
     #[test]
-    fn test_placement_in() {
-        let mut map = HashMap::new();
-        map.extend((0..10).map(|i| (i, i)));
-
-        map.entry(100) <- 100;
-        assert_eq!(map[&100], 100);
-
-        map.entry(0) <- 10;
-        assert_eq!(map[&0], 10);
-
-        assert_eq!(map.len(), 11);
-    }
+    fn test_try_reserve() {
 
-    #[test]
-    fn test_placement_panic() {
-        let mut map = HashMap::new();
-        map.extend((0..10).map(|i| (i, i)));
+        let mut empty_bytes: HashMap<u8,u8> = HashMap::new();
 
-        fn mkpanic() -> usize { panic!() }
+        const MAX_USIZE: usize = usize::MAX;
 
-        // modify existing key
-        // when panic happens, previous key is removed.
-        let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { map.entry(0) <- mkpanic(); }));
-        assert_eq!(map.len(), 9);
-        assert!(!map.contains_key(&0));
+        // HashMap and RawTables use complicated size calculations
+        // hashes_size is sizeof(HashUint) * capacity;
+        // pairs_size is sizeof((K. V)) * capacity;
+        // alignment_hashes_size is 8
+        // alignment_pairs size is 4
+        let size_of_multiplier = (size_of::<usize>() + size_of::<(u8, u8)>()).next_power_of_two();
+        // The following formula is used to calculate the new capacity
+        let max_no_ovf = ((MAX_USIZE / 11) * 10) / size_of_multiplier - 1;
 
-        // add new key
-        let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { map.entry(100) <- mkpanic(); }));
-        assert_eq!(map.len(), 9);
-        assert!(!map.contains_key(&100));
-    }
+        if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) {
+        } else { panic!("usize::MAX should trigger an overflow!"); }
 
-    #[test]
-    fn test_placement_drop() {
-        // correctly drop
-        struct TestV<'a>(&'a mut bool);
-        impl<'a> Drop for TestV<'a> {
-            fn drop(&mut self) {
-                if !*self.0 { panic!("value double drop!"); } // no double drop
-                *self.0 = false;
-            }
+        if size_of::<usize>() < 8 {
+            if let Err(CapacityOverflow) = empty_bytes.try_reserve(max_no_ovf) {
+            } else { panic!("isize::MAX + 1 should trigger a CapacityOverflow!") }
+        } else {
+            if let Err(AllocErr) = empty_bytes.try_reserve(max_no_ovf) {
+            } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
-
-        fn makepanic<'a>() -> TestV<'a> { panic!() }
-
-        let mut can_drop = true;
-        let mut hm = HashMap::new();
-        hm.insert(0, TestV(&mut can_drop));
-        let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { hm.entry(0) <- makepanic(); }));
-        assert_eq!(hm.len(), 0);
     }
+
 }
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index e9427fb40a0..5ac3e8f9cf7 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -49,14 +49,14 @@ use super::map::{self, HashMap, Keys, RandomState};
 /// ```
 /// use std::collections::HashSet;
 /// // Type inference lets us omit an explicit type signature (which
-/// // would be `HashSet<&str>` in this example).
+/// // would be `HashSet<String>` in this example).
 /// let mut books = HashSet::new();
 ///
 /// // Add some books.
-/// books.insert("A Dance With Dragons");
-/// books.insert("To Kill a Mockingbird");
-/// books.insert("The Odyssey");
-/// books.insert("The Great Gatsby");
+/// books.insert("A Dance With Dragons".to_string());
+/// books.insert("To Kill a Mockingbird".to_string());
+/// books.insert("The Odyssey".to_string());
+/// books.insert("The Great Gatsby".to_string());
 ///
 /// // Check for a specific one.
 /// if !books.contains("The Winds of Winter") {
@@ -80,17 +80,17 @@ use super::map::{self, HashMap, Keys, RandomState};
 /// ```
 /// use std::collections::HashSet;
 /// #[derive(Hash, Eq, PartialEq, Debug)]
-/// struct Viking<'a> {
-///     name: &'a str,
+/// struct Viking {
+///     name: String,
 ///     power: usize,
 /// }
 ///
 /// let mut vikings = HashSet::new();
 ///
-/// vikings.insert(Viking { name: "Einar", power: 9 });
-/// vikings.insert(Viking { name: "Einar", power: 9 });
-/// vikings.insert(Viking { name: "Olaf", power: 4 });
-/// vikings.insert(Viking { name: "Harald", power: 8 });
+/// vikings.insert(Viking { name: "Einar".to_string(), power: 9 });
+/// vikings.insert(Viking { name: "Einar".to_string(), power: 9 });
+/// vikings.insert(Viking { name: "Olaf".to_string(), power: 4 });
+/// vikings.insert(Viking { name: "Harald".to_string(), power: 8 });
 ///
 /// // Use derived implementation to print the vikings.
 /// for x in &vikings {
@@ -104,7 +104,7 @@ use super::map::{self, HashMap, Keys, RandomState};
 /// use std::collections::HashSet;
 ///
 /// fn main() {
-///     let viking_names: HashSet<&str> =
+///     let viking_names: HashSet<&'static str> =
 ///         [ "Einar", "Olaf", "Harald" ].iter().cloned().collect();
 ///     // use the values stored in the set
 /// }
@@ -292,6 +292,34 @@ impl<T, S> HashSet<T, S>
         self.map.shrink_to_fit()
     }
 
+    /// Shrinks the capacity of the set with a lower limit. It will drop
+    /// down no lower than the supplied limit while maintaining the internal rules
+    /// and possibly leaving some space in accordance with the resize policy.
+    ///
+    /// Panics if the current capacity is smaller than the supplied
+    /// minimum capacity.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(shrink_to)]
+    /// use std::collections::HashSet;
+    ///
+    /// let mut set = HashSet::with_capacity(100);
+    /// set.insert(1);
+    /// set.insert(2);
+    /// assert!(set.capacity() >= 100);
+    /// set.shrink_to(10);
+    /// assert!(set.capacity() >= 10);
+    /// set.shrink_to(0);
+    /// assert!(set.capacity() >= 2);
+    /// ```
+    #[inline]
+    #[unstable(feature = "shrink_to", reason = "new API", issue="0")]
+    pub fn shrink_to(&mut self, min_capacity: usize) {
+        self.map.shrink_to(min_capacity)
+    }
+
     /// An iterator visiting all elements in arbitrary order.
     /// The iterator element type is `&'a T`.
     ///
@@ -724,7 +752,7 @@ impl<T, S> HashSet<T, S>
     /// use std::collections::HashSet;
     ///
     /// let xs = [1,2,3,4,5,6];
-    /// let mut set: HashSet<isize> = xs.iter().cloned().collect();
+    /// let mut set: HashSet<i32> = xs.iter().cloned().collect();
     /// set.retain(|&k| k % 2 == 0);
     /// assert_eq!(set.len(), 3);
     /// ```
@@ -1097,7 +1125,7 @@ impl<'a, K> ExactSizeIterator for Iter<'a, K> {
         self.iter.len()
     }
 }
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
 impl<'a, K> FusedIterator for Iter<'a, K> {}
 
 #[stable(feature = "std_debug", since = "1.16.0")]
@@ -1124,7 +1152,7 @@ impl<K> ExactSizeIterator for IntoIter<K> {
         self.iter.len()
     }
 }
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
 impl<K> FusedIterator for IntoIter<K> {}
 
 #[stable(feature = "std_debug", since = "1.16.0")]
@@ -1155,7 +1183,7 @@ impl<'a, K> ExactSizeIterator for Drain<'a, K> {
         self.iter.len()
     }
 }
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
 impl<'a, K> FusedIterator for Drain<'a, K> {}
 
 #[stable(feature = "std_debug", since = "1.16.0")]
@@ -1208,7 +1236,7 @@ impl<'a, T, S> fmt::Debug for Intersection<'a, T, S>
     }
 }
 
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
 impl<'a, T, S> FusedIterator for Intersection<'a, T, S>
     where T: Eq + Hash,
           S: BuildHasher
@@ -1244,7 +1272,7 @@ impl<'a, T, S> Iterator for Difference<'a, T, S>
     }
 }
 
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
 impl<'a, T, S> FusedIterator for Difference<'a, T, S>
     where T: Eq + Hash,
           S: BuildHasher
@@ -1283,7 +1311,7 @@ impl<'a, T, S> Iterator for SymmetricDifference<'a, T, S>
     }
 }
 
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
 impl<'a, T, S> FusedIterator for SymmetricDifference<'a, T, S>
     where T: Eq + Hash,
           S: BuildHasher
@@ -1307,7 +1335,7 @@ impl<'a, T, S> Clone for Union<'a, T, S> {
     }
 }
 
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
 impl<'a, T, S> FusedIterator for Union<'a, T, S>
     where T: Eq + Hash,
           S: BuildHasher
@@ -1745,7 +1773,7 @@ mod test_set {
     #[test]
     fn test_retain() {
         let xs = [1, 2, 3, 4, 5, 6];
-        let mut set: HashSet<isize> = xs.iter().cloned().collect();
+        let mut set: HashSet<i32> = xs.iter().cloned().collect();
         set.retain(|&k| k % 2 == 0);
         assert_eq!(set.len(), 3);
         assert!(set.contains(&2));
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index 96f98efe4aa..2b319186a8d 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use alloc::heap::{Heap, Alloc, Layout};
-
-use cmp;
+use alloc::{Global, Alloc, Layout, LayoutErr, handle_alloc_error};
+use collections::CollectionAllocErr;
 use hash::{BuildHasher, Hash, Hasher};
 use marker;
-use mem::{align_of, size_of, needs_drop};
+use mem::{size_of, needs_drop};
 use mem;
 use ops::{Deref, DerefMut};
-use ptr::{self, Unique, Shared};
+use ptr::{self, Unique, NonNull};
+use hint;
 
 use self::BucketState::*;
 
@@ -80,7 +80,7 @@ impl TaggedHashUintPtr {
 ///
 /// Essential invariants of this structure:
 ///
-///   - if t.hashes[i] == EMPTY_BUCKET, then `Bucket::at_index(&t, i).raw`
+///   - if `t.hashes[i] == EMPTY_BUCKET`, then `Bucket::at_index(&t, i).raw`
 ///     points to 'undefined' contents. Don't read from it. This invariant is
 ///     enforced outside this module with the `EmptyBucket`, `FullBucket`,
 ///     and `SafeHash` types.
@@ -484,21 +484,6 @@ impl<K, V, M> EmptyBucket<K, V, M>
             table: self.table,
         }
     }
-
-    /// Puts given key, remain value uninitialized.
-    /// It is only used for inplacement insertion.
-    pub unsafe fn put_key(mut self, hash: SafeHash, key: K) -> FullBucket<K, V, M> {
-        *self.raw.hash() = hash.inspect();
-        let pair_ptr = self.raw.pair();
-        ptr::write(&mut (*pair_ptr).0, key);
-
-        self.table.borrow_table_mut().size += 1;
-
-        FullBucket {
-            raw: self.raw,
-            table: self.table,
-        }
-    }
 }
 
 impl<K, V, M: Deref<Target = RawTable<K, V>>> FullBucket<K, V, M> {
@@ -574,17 +559,6 @@ impl<'t, K, V> FullBucket<K, V, &'t mut RawTable<K, V>> {
             v)
         }
     }
-
-    /// Remove this bucket's `key` from the hashtable.
-    /// Only used for inplacement insertion.
-    /// NOTE: `Value` is uninitialized when this function is called, don't try to drop the `Value`.
-    pub unsafe fn remove_key(&mut self) {
-        self.table.size -= 1;
-
-        *self.raw.hash() = EMPTY_BUCKET;
-        let pair_ptr = self.raw.pair();
-        ptr::drop_in_place(&mut (*pair_ptr).0); // only drop key
-    }
 }
 
 // This use of `Put` is misleading and restrictive, but safe and sufficient for our use cases
@@ -678,144 +652,114 @@ impl<K, V, M> GapThenFull<K, V, M>
     }
 }
 
-
-/// Rounds up to a multiple of a power of two. Returns the closest multiple
-/// of `target_alignment` that is higher or equal to `unrounded`.
-///
-/// # Panics
-///
-/// Panics if `target_alignment` is not a power of two.
-#[inline]
-fn round_up_to_next(unrounded: usize, target_alignment: usize) -> usize {
-    assert!(target_alignment.is_power_of_two());
-    (unrounded + target_alignment - 1) & !(target_alignment - 1)
-}
-
-#[test]
-fn test_rounding() {
-    assert_eq!(round_up_to_next(0, 4), 0);
-    assert_eq!(round_up_to_next(1, 4), 4);
-    assert_eq!(round_up_to_next(2, 4), 4);
-    assert_eq!(round_up_to_next(3, 4), 4);
-    assert_eq!(round_up_to_next(4, 4), 4);
-    assert_eq!(round_up_to_next(5, 4), 8);
-}
-
-// Returns a tuple of (pairs_offset, end_of_pairs_offset),
-// from the start of a mallocated array.
-#[inline]
-fn calculate_offsets(hashes_size: usize,
-                     pairs_size: usize,
-                     pairs_align: usize)
-                     -> (usize, usize, bool) {
-    let pairs_offset = round_up_to_next(hashes_size, pairs_align);
-    let (end_of_pairs, oflo) = pairs_offset.overflowing_add(pairs_size);
-
-    (pairs_offset, end_of_pairs, oflo)
+// Returns a Layout which describes the allocation required for a hash table,
+// and the offset of the array of (key, value) pairs in the allocation.
+fn calculate_layout<K, V>(capacity: usize) -> Result<(Layout, usize), LayoutErr> {
+    let hashes = Layout::array::<HashUint>(capacity)?;
+    let pairs = Layout::array::<(K, V)>(capacity)?;
+    hashes.extend(pairs).map(|(layout, _)| {
+        // LLVM seems to have trouble properly const-propagating pairs.align(),
+        // possibly due to the use of NonZeroUsize. This little hack allows it
+        // to generate optimal code.
+        //
+        // See https://github.com/rust-lang/rust/issues/51346 for more details.
+        (
+            layout,
+            hashes.size() + hashes.padding_needed_for(mem::align_of::<(K, V)>()),
+        )
+    })
 }
 
-// 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, bool) {
-    let (_, end_of_pairs, oflo) = calculate_offsets(hash_size, pairs_size, pairs_align);
-
-    let align = cmp::max(hash_align, pairs_align);
-
-    (align, end_of_pairs, oflo)
+pub(crate) enum Fallibility {
+    Fallible,
+    Infallible,
 }
 
-#[test]
-fn test_offset_calculation() {
-    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));
-}
+use self::Fallibility::*;
 
 impl<K, V> RawTable<K, V> {
     /// Does not initialize the buckets. The caller should ensure they,
     /// at the very least, set every hash to EMPTY_BUCKET.
-    unsafe fn new_uninitialized(capacity: usize) -> RawTable<K, V> {
+    /// Returns an error if it cannot allocate or capacity overflows.
+    unsafe fn new_uninitialized_internal(
+        capacity: usize,
+        fallibility: Fallibility,
+    ) -> Result<RawTable<K, V>, CollectionAllocErr> {
         if capacity == 0 {
-            return RawTable {
+            return Ok(RawTable {
                 size: 0,
                 capacity_mask: capacity.wrapping_sub(1),
                 hashes: TaggedHashUintPtr::new(EMPTY as *mut HashUint),
                 marker: marker::PhantomData,
-            };
+            });
         }
 
-        // No need for `checked_mul` before a more restrictive check performed
-        // later in this method.
-        let hashes_size = capacity.wrapping_mul(size_of::<HashUint>());
-        let pairs_size = capacity.wrapping_mul(size_of::<(K, V)>());
-
         // Allocating hashmaps is a little tricky. We need to allocate two
         // arrays, but since we know their sizes and alignments up front,
         // we just allocate a single array, and then have the subarrays
         // point into it.
-        //
-        // 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, size, oflo) = calculate_allocation(hashes_size,
-                                                           align_of::<HashUint>(),
-                                                           pairs_size,
-                                                           align_of::<(K, V)>());
-        assert!(!oflo, "capacity overflow");
-
-        // One check for overflow that covers calculation and rounding of size.
-        let size_of_bucket = size_of::<HashUint>().checked_add(size_of::<(K, V)>()).unwrap();
-        assert!(size >=
-                capacity.checked_mul(size_of_bucket)
-                    .expect("capacity overflow"),
-                "capacity overflow");
-
-        let buffer = Heap.alloc(Layout::from_size_align(size, alignment).unwrap())
-            .unwrap_or_else(|e| Heap.oom(e));
-
-        let hashes = buffer as *mut HashUint;
-
-        RawTable {
+        let (layout, _) = calculate_layout::<K, V>(capacity)?;
+        let buffer = Global.alloc(layout).map_err(|e| match fallibility {
+            Infallible => handle_alloc_error(layout),
+            Fallible => e,
+        })?;
+
+        Ok(RawTable {
             capacity_mask: capacity.wrapping_sub(1),
             size: 0,
-            hashes: TaggedHashUintPtr::new(hashes),
+            hashes: TaggedHashUintPtr::new(buffer.cast().as_ptr()),
             marker: marker::PhantomData,
+        })
+    }
+
+    /// Does not initialize the buckets. The caller should ensure they,
+    /// at the very least, set every hash to EMPTY_BUCKET.
+    unsafe fn new_uninitialized(capacity: usize) -> RawTable<K, V> {
+        match Self::new_uninitialized_internal(capacity, Infallible) {
+            Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
+            Err(CollectionAllocErr::AllocErr) => unreachable!(),
+            Ok(table) => { table }
         }
     }
 
     fn raw_bucket_at(&self, index: usize) -> RawBucket<K, V> {
-        let hashes_size = self.capacity() * size_of::<HashUint>();
-        let pairs_size = self.capacity() * size_of::<(K, V)>();
-
-        let (pairs_offset, _, oflo) =
-            calculate_offsets(hashes_size, pairs_size, align_of::<(K, V)>());
-        debug_assert!(!oflo, "capacity overflow");
-
+        let (_, pairs_offset) = calculate_layout::<K, V>(self.capacity())
+            .unwrap_or_else(|_| unsafe { hint::unreachable_unchecked() });
         let buffer = self.hashes.ptr() as *mut u8;
         unsafe {
             RawBucket {
                 hash_start: buffer as *mut HashUint,
-                pair_start: buffer.offset(pairs_offset as isize) as *const (K, V),
+                pair_start: buffer.add(pairs_offset) as *const (K, V),
                 idx: index,
                 _marker: marker::PhantomData,
             }
         }
     }
 
+    fn new_internal(
+        capacity: usize,
+        fallibility: Fallibility,
+    ) -> Result<RawTable<K, V>, CollectionAllocErr> {
+        unsafe {
+            let ret = RawTable::new_uninitialized_internal(capacity, fallibility)?;
+            ptr::write_bytes(ret.hashes.ptr(), 0, capacity);
+            Ok(ret)
+        }
+    }
+
+    /// Tries to create a new raw table from a given capacity. If it cannot allocate,
+    /// it returns with AllocErr.
+    pub fn try_new(capacity: usize) -> Result<RawTable<K, V>, CollectionAllocErr> {
+        Self::new_internal(capacity, Fallible)
+    }
+
     /// Creates a new raw table from a given capacity. All buckets are
     /// initially empty.
     pub fn new(capacity: usize) -> RawTable<K, V> {
-        unsafe {
-            let ret = RawTable::new_uninitialized(capacity);
-            ptr::write_bytes(ret.hashes.ptr(), 0, capacity);
-            ret
+        match Self::new_internal(capacity, Infallible) {
+            Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
+            Err(CollectionAllocErr::AllocErr) => unreachable!(),
+            Ok(table) => { table }
         }
     }
 
@@ -873,7 +817,7 @@ impl<K, V> RawTable<K, V> {
                 elems_left,
                 marker: marker::PhantomData,
             },
-            table: Shared::from(self),
+            table: NonNull::from(self),
             marker: marker::PhantomData,
         }
     }
@@ -1020,7 +964,7 @@ impl<K, V> IntoIter<K, V> {
 
 /// Iterator over the entries in a table, clearing the table.
 pub struct Drain<'a, K: 'a, V: 'a> {
-    table: Shared<RawTable<K, V>>,
+    table: NonNull<RawTable<K, V>>,
     iter: RawBuckets<'static, K, V>,
     marker: marker::PhantomData<&'a RawTable<K, V>>,
 }
@@ -1129,7 +1073,7 @@ impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
 
 impl<'a, K: 'a, V: 'a> Drop for Drain<'a, K, V> {
     fn drop(&mut self) {
-        for _ in self {}
+        self.for_each(drop);
     }
 }
 
@@ -1178,18 +1122,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)>());
-
-        debug_assert!(!oflo, "should be impossible");
-
+        let (layout, _) = calculate_layout::<K, V>(self.capacity())
+            .unwrap_or_else(|_| unsafe { hint::unreachable_unchecked() });
         unsafe {
-            Heap.dealloc(self.hashes.ptr() as *mut u8,
-                         Layout::from_size_align(size, align).unwrap());
+            Global.dealloc(NonNull::new_unchecked(self.hashes.ptr()).cast(), layout);
             // Remember how everything was allocated out of one buffer
             // during initialization? We only need one call to free here.
         }
diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs
index b8a6a66eaa6..8d2c82bc0aa 100644
--- a/src/libstd/collections/mod.rs
+++ b/src/libstd/collections/mod.rs
@@ -64,11 +64,11 @@
 //! * You want a map, with no extra functionality.
 //!
 //! ### Use a `BTreeMap` when:
+//! * You want a map sorted by its keys.
+//! * You want to be able to get a range of entries on-demand.
 //! * You're interested in what the smallest or largest key-value pair is.
 //! * You want to find the largest or smallest key that is smaller or larger
 //!   than something.
-//! * You want to be able to get all of the entries in order on-demand.
-//! * You want a map sorted by its keys.
 //!
 //! ### Use the `Set` variant of any of these `Map`s when:
 //! * You just want to remember which keys you've seen.
@@ -420,23 +420,25 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::Bound;
+#[rustc_deprecated(reason = "moved to `std::ops::Bound`", since = "1.26.0")]
+#[doc(hidden)]
+pub use ops::Bound;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::{BinaryHeap, BTreeMap, BTreeSet};
+pub use alloc_crate::collections::{BinaryHeap, BTreeMap, BTreeSet};
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::{LinkedList, VecDeque};
+pub use alloc_crate::collections::{LinkedList, VecDeque};
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::{binary_heap, btree_map, btree_set};
+pub use alloc_crate::collections::{binary_heap, btree_map, btree_set};
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::{linked_list, vec_deque};
+pub use alloc_crate::collections::{linked_list, vec_deque};
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::hash_map::HashMap;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::hash_set::HashSet;
 
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::range;
+#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
+pub use alloc_crate::collections::CollectionAllocErr;
 
 mod hash;
 
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index 27bf326631f..9066c0b7694 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -49,9 +49,11 @@ use sys::os as os_imp;
 /// ```
 /// use std::env;
 ///
-/// // We assume that we are in a valid directory.
-/// let path = env::current_dir().unwrap();
-/// println!("The current directory is {}", path.display());
+/// fn main() -> std::io::Result<()> {
+///     let path = env::current_dir()?;
+///     println!("The current directory is {}", path.display());
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "env", since = "1.0.0")]
 pub fn current_dir() -> io::Result<PathBuf> {
@@ -441,15 +443,18 @@ pub struct JoinPathsError {
 /// Joining paths on a Unix-like platform:
 ///
 /// ```
-/// # if cfg!(unix) {
 /// use std::env;
 /// use std::ffi::OsString;
 /// use std::path::Path;
 ///
-/// let paths = [Path::new("/bin"), Path::new("/usr/bin")];
-/// let path_os_string = env::join_paths(paths.iter()).unwrap();
-/// assert_eq!(path_os_string, OsString::from("/bin:/usr/bin"));
+/// fn main() -> Result<(), env::JoinPathsError> {
+/// # if cfg!(unix) {
+///     let paths = [Path::new("/bin"), Path::new("/usr/bin")];
+///     let path_os_string = env::join_paths(paths.iter())?;
+///     assert_eq!(path_os_string, OsString::from("/bin:/usr/bin"));
 /// # }
+///     Ok(())
+/// }
 /// ```
 ///
 /// Joining a path containing a colon on a Unix-like platform results in an error:
@@ -471,11 +476,15 @@ pub struct JoinPathsError {
 /// use std::env;
 /// use std::path::PathBuf;
 ///
-/// if let Some(path) = env::var_os("PATH") {
-///     let mut paths = env::split_paths(&path).collect::<Vec<_>>();
-///     paths.push(PathBuf::from("/home/xyz/bin"));
-///     let new_path = env::join_paths(paths).unwrap();
-///     env::set_var("PATH", &new_path);
+/// fn main() -> Result<(), env::JoinPathsError> {
+///     if let Some(path) = env::var_os("PATH") {
+///         let mut paths = env::split_paths(&path).collect::<Vec<_>>();
+///         paths.push(PathBuf::from("/home/xyz/bin"));
+///         let new_path = env::join_paths(paths)?;
+///         env::set_var("PATH", &new_path);
+///     }
+///
+///     Ok(())
 /// }
 /// ```
 #[stable(feature = "env", since = "1.0.0")]
@@ -503,18 +512,20 @@ impl Error for JoinPathsError {
 ///
 /// # Unix
 ///
-/// Returns the value of the 'HOME' environment variable if it is set
-/// and not equal to the empty string. Otherwise, it tries to determine the
-/// home directory by invoking the `getpwuid_r` function on the UID of the
-/// current user.
+/// - Returns the value of the 'HOME' environment variable if it is set
+///   (including to an empty string).
+/// - Otherwise, it tries to determine the home directory by invoking the `getpwuid_r` function
+///   using the UID of the current user. An empty home directory field returned from the
+///   `getpwuid_r` function is considered to be a valid value.
+/// - Returns `None` if the current user has no entry in the /etc/passwd file.
 ///
 /// # Windows
 ///
-/// Returns the value of the 'HOME' environment variable if it is
-/// set and not equal to the empty string. Otherwise, returns the value of the
-/// 'USERPROFILE' environment variable if it is set and not equal to the empty
-/// string. If both do not exist, [`GetUserProfileDirectory`][msdn] is used to
-/// return the appropriate path.
+/// - Returns the value of the 'HOME' environment variable if it is set
+///   (including to an empty string).
+/// - Otherwise, returns the value of the 'USERPROFILE' environment variable if it is set
+///   (including to an empty string).
+/// - If both do not exist, [`GetUserProfileDirectory`][msdn] is used to return the path.
 ///
 /// [msdn]: https://msdn.microsoft.com/en-us/library/windows/desktop/bb762280(v=vs.85).aspx
 ///
@@ -524,10 +535,13 @@ impl Error for JoinPathsError {
 /// use std::env;
 ///
 /// match env::home_dir() {
-///     Some(path) => println!("{}", path.display()),
+///     Some(path) => println!("Your home directory, probably: {}", path.display()),
 ///     None => println!("Impossible to get your home dir!"),
 /// }
 /// ```
+#[rustc_deprecated(since = "1.29.0",
+    reason = "This function's behavior is unexpected and probably not what you want. \
+              Consider using the home_dir function from https://crates.io/crates/dirs instead.")]
 #[stable(feature = "env", since = "1.0.0")]
 pub fn home_dir() -> Option<PathBuf> {
     os_imp::home_dir()
@@ -552,17 +566,17 @@ pub fn home_dir() -> Option<PathBuf> {
 ///
 /// [msdn]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364992(v=vs.85).aspx
 ///
-/// ```
+/// ```no_run
 /// use std::env;
 /// use std::fs::File;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// let mut dir = env::temp_dir();
-/// dir.push("foo.txt");
+/// fn main() -> std::io::Result<()> {
+///     let mut dir = env::temp_dir();
+///     dir.push("foo.txt");
 ///
-/// let f = File::create(dir)?;
-/// # Ok(())
-/// # }
+///     let f = File::create(dir)?;
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "env", since = "1.0.0")]
 pub fn temp_dir() -> PathBuf {
@@ -723,6 +737,12 @@ pub fn args_os() -> ArgsOs {
     ArgsOs { inner: sys::args::args() }
 }
 
+#[stable(feature = "env_unimpl_send_sync", since = "1.26.0")]
+impl !Send for Args {}
+
+#[stable(feature = "env_unimpl_send_sync", since = "1.26.0")]
+impl !Sync for Args {}
+
 #[stable(feature = "env", since = "1.0.0")]
 impl Iterator for Args {
     type Item = String;
@@ -754,6 +774,12 @@ impl fmt::Debug for Args {
     }
 }
 
+#[stable(feature = "env_unimpl_send_sync", since = "1.26.0")]
+impl !Send for ArgsOs {}
+
+#[stable(feature = "env_unimpl_send_sync", since = "1.26.0")]
+impl !Sync for ArgsOs {}
+
 #[stable(feature = "env", since = "1.0.0")]
 impl Iterator for ArgsOs {
     type Item = OsString;
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index eb5022ad577..29534696abc 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -9,34 +9,6 @@
 // except according to those terms.
 
 //! Traits for working with Errors.
-//!
-//! # The `Error` trait
-//!
-//! `Error` is a trait representing the basic expectations for error values,
-//! i.e. values of type `E` in [`Result<T, E>`]. At a minimum, errors must provide
-//! a description, but they may optionally provide additional detail (via
-//! [`Display`]) and cause chain information:
-//!
-//! ```
-//! use std::fmt::Display;
-//!
-//! trait Error: Display {
-//!     fn description(&self) -> &str;
-//!
-//!     fn cause(&self) -> Option<&Error> { None }
-//! }
-//! ```
-//!
-//! The [`cause`] method is generally used when errors cross "abstraction
-//! boundaries", i.e.  when a one module must report an error that is "caused"
-//! by an error from a lower-level module. This setup makes it possible for the
-//! high-level module to provide its own errors that do not commit to any
-//! particular implementation, but also reveal some of its implementation for
-//! debugging via [`cause`] chains.
-//!
-//! [`Result<T, E>`]: ../result/enum.Result.html
-//! [`Display`]: ../fmt/trait.Display.html
-//! [`cause`]: trait.Error.html#method.cause
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -51,12 +23,11 @@
 // coherence challenge (e.g., specialization, neg impls, etc) we can
 // reconsider what crate these items belong in.
 
-use alloc::allocator;
+use alloc::{AllocErr, LayoutErr, CannotReallocInPlace};
 use any::TypeId;
 use borrow::Cow;
 use cell;
 use char;
-use convert;
 use core::array;
 use fmt::{self, Debug, Display};
 use mem::transmute;
@@ -64,33 +35,49 @@ use num;
 use str;
 use string;
 
-/// Base functionality for all errors in Rust.
+/// `Error` is a trait representing the basic expectations for error values,
+/// i.e. values of type `E` in [`Result<T, E>`]. Errors must describe
+/// themselves through the [`Display`] and [`Debug`] traits, and may provide
+/// cause chain information:
+///
+/// The [`cause`] method is generally used when errors cross "abstraction
+/// boundaries", i.e.  when a one module must report an error that is "caused"
+/// by an error from a lower-level module. This setup makes it possible for the
+/// high-level module to provide its own errors that do not commit to any
+/// particular implementation, but also reveal some of its implementation for
+/// debugging via [`cause`] chains.
+///
+/// [`Result<T, E>`]: ../result/enum.Result.html
+/// [`Display`]: ../fmt/trait.Display.html
+/// [`Debug`]: ../fmt/trait.Debug.html
+/// [`cause`]: trait.Error.html#method.cause
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Error: Debug + Display {
-    /// A short description of the error.
+    /// **This method is soft-deprecated.**
     ///
-    /// The description should only be used for a simple message.
-    /// It should not contain newlines or sentence-ending punctuation,
-    /// to facilitate embedding in larger user-facing strings.
-    /// For showing formatted error messages with more information see
-    /// [`Display`].
+    /// Although using it won’t cause compilation warning,
+    /// new code should use [`Display`] instead
+    /// and new `impl`s can omit it.
+    ///
+    /// To obtain error description as a string, use `to_string()`.
     ///
     /// [`Display`]: ../fmt/trait.Display.html
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::error::Error;
-    ///
     /// match "xc".parse::<u32>() {
     ///     Err(e) => {
-    ///         println!("Error: {}", e.description());
+    ///         // Print `e` itself, not `e.description()`.
+    ///         println!("Error: {}", e);
     ///     }
     ///     _ => println!("No error"),
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn description(&self) -> &str;
+    fn description(&self) -> &str {
+        "description() is deprecated; use Display"
+    }
 
     /// The lower-level cause of this error, if any.
     ///
@@ -151,7 +138,7 @@ pub trait Error: Debug + Display {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn cause(&self) -> Option<&Error> { None }
+    fn cause(&self) -> Option<&dyn Error> { None }
 
     /// Get the `TypeId` of `self`
     #[doc(hidden)]
@@ -164,22 +151,22 @@ pub trait Error: Debug + Display {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, E: Error + 'a> From<E> for Box<Error + 'a> {
-    fn from(err: E) -> Box<Error + 'a> {
+impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
+    fn from(err: E) -> Box<dyn Error + 'a> {
         Box::new(err)
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<Error + Send + Sync + 'a> {
-    fn from(err: E) -> Box<Error + Send + Sync + 'a> {
+impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> {
+    fn from(err: E) -> Box<dyn Error + Send + Sync + 'a> {
         Box::new(err)
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl From<String> for Box<Error + Send + Sync> {
-    fn from(err: String) -> Box<Error + Send + Sync> {
+impl From<String> for Box<dyn Error + Send + Sync> {
+    fn from(err: String) -> Box<dyn Error + Send + Sync> {
         #[derive(Debug)]
         struct StringError(String);
 
@@ -198,38 +185,38 @@ impl From<String> for Box<Error + Send + Sync> {
 }
 
 #[stable(feature = "string_box_error", since = "1.6.0")]
-impl From<String> for Box<Error> {
-    fn from(str_err: String) -> Box<Error> {
-        let err1: Box<Error + Send + Sync> = From::from(str_err);
-        let err2: Box<Error> = err1;
+impl From<String> for Box<dyn Error> {
+    fn from(str_err: String) -> Box<dyn Error> {
+        let err1: Box<dyn Error + Send + Sync> = From::from(str_err);
+        let err2: Box<dyn Error> = err1;
         err2
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b> From<&'b str> for Box<Error + Send + Sync + 'a> {
-    fn from(err: &'b str) -> Box<Error + Send + Sync + 'a> {
+impl<'a, 'b> From<&'b str> for Box<dyn Error + Send + Sync + 'a> {
+    fn from(err: &'b str) -> Box<dyn Error + Send + Sync + 'a> {
         From::from(String::from(err))
     }
 }
 
 #[stable(feature = "string_box_error", since = "1.6.0")]
-impl<'a> From<&'a str> for Box<Error> {
-    fn from(err: &'a str) -> Box<Error> {
+impl<'a> From<&'a str> for Box<dyn Error> {
+    fn from(err: &'a str) -> Box<dyn Error> {
         From::from(String::from(err))
     }
 }
 
 #[stable(feature = "cow_box_error", since = "1.22.0")]
-impl<'a, 'b> From<Cow<'b, str>> for Box<Error + Send + Sync + 'a> {
-    fn from(err: Cow<'b, str>) -> Box<Error + Send + Sync + 'a> {
+impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
+    fn from(err: Cow<'b, str>) -> Box<dyn Error + Send + Sync + 'a> {
         From::from(String::from(err))
     }
 }
 
 #[stable(feature = "cow_box_error", since = "1.22.0")]
-impl<'a> From<Cow<'a, str>> for Box<Error> {
-    fn from(err: Cow<'a, str>) -> Box<Error> {
+impl<'a> From<Cow<'a, str>> for Box<dyn Error> {
+    fn from(err: Cow<'a, str>) -> Box<dyn Error> {
         From::from(String::from(err))
     }
 }
@@ -242,18 +229,27 @@ impl Error for ! {
 #[unstable(feature = "allocator_api",
            reason = "the precise API and guarantees it provides may be tweaked.",
            issue = "32838")]
-impl Error for allocator::AllocErr {
+impl Error for AllocErr {
+    fn description(&self) -> &str {
+        "memory allocation failed"
+    }
+}
+
+#[unstable(feature = "allocator_api",
+           reason = "the precise API and guarantees it provides may be tweaked.",
+           issue = "32838")]
+impl Error for LayoutErr {
     fn description(&self) -> &str {
-        allocator::AllocErr::description(self)
+        "invalid parameters to Layout::from_size_align"
     }
 }
 
 #[unstable(feature = "allocator_api",
            reason = "the precise API and guarantees it provides may be tweaked.",
            issue = "32838")]
-impl Error for allocator::CannotReallocInPlace {
+impl Error for CannotReallocInPlace {
     fn description(&self) -> &str {
-        allocator::CannotReallocInPlace::description(self)
+        CannotReallocInPlace::description(self)
     }
 }
 
@@ -331,7 +327,7 @@ impl<T: Error> Error for Box<T> {
         Error::description(&**self)
     }
 
-    fn cause(&self) -> Option<&Error> {
+    fn cause(&self) -> Option<&dyn Error> {
         Error::cause(&**self)
     }
 }
@@ -371,16 +367,8 @@ 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 {
+impl dyn Error + 'static {
     /// Returns true if the boxed type is the same as `T`
     #[stable(feature = "error_downcast", since = "1.3.0")]
     #[inline]
@@ -402,7 +390,7 @@ impl Error + 'static {
     pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
         if self.is::<T>() {
             unsafe {
-                Some(&*(self as *const Error as *const T))
+                Some(&*(self as *const dyn Error as *const T))
             }
         } else {
             None
@@ -416,7 +404,7 @@ impl Error + 'static {
     pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
         if self.is::<T>() {
             unsafe {
-                Some(&mut *(self as *mut Error as *mut T))
+                Some(&mut *(self as *mut dyn Error as *mut T))
             }
         } else {
             None
@@ -424,60 +412,60 @@ impl Error + 'static {
     }
 }
 
-impl Error + 'static + Send {
+impl dyn Error + 'static + Send {
     /// Forwards to the method defined on the type `Any`.
     #[stable(feature = "error_downcast", since = "1.3.0")]
     #[inline]
     pub fn is<T: Error + 'static>(&self) -> bool {
-        <Error + 'static>::is::<T>(self)
+        <dyn Error + 'static>::is::<T>(self)
     }
 
     /// Forwards to the method defined on the type `Any`.
     #[stable(feature = "error_downcast", since = "1.3.0")]
     #[inline]
     pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
-        <Error + 'static>::downcast_ref::<T>(self)
+        <dyn Error + 'static>::downcast_ref::<T>(self)
     }
 
     /// Forwards to the method defined on the type `Any`.
     #[stable(feature = "error_downcast", since = "1.3.0")]
     #[inline]
     pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
-        <Error + 'static>::downcast_mut::<T>(self)
+        <dyn Error + 'static>::downcast_mut::<T>(self)
     }
 }
 
-impl Error + 'static + Send + Sync {
+impl dyn Error + 'static + Send + Sync {
     /// Forwards to the method defined on the type `Any`.
     #[stable(feature = "error_downcast", since = "1.3.0")]
     #[inline]
     pub fn is<T: Error + 'static>(&self) -> bool {
-        <Error + 'static>::is::<T>(self)
+        <dyn Error + 'static>::is::<T>(self)
     }
 
     /// Forwards to the method defined on the type `Any`.
     #[stable(feature = "error_downcast", since = "1.3.0")]
     #[inline]
     pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
-        <Error + 'static>::downcast_ref::<T>(self)
+        <dyn Error + 'static>::downcast_ref::<T>(self)
     }
 
     /// Forwards to the method defined on the type `Any`.
     #[stable(feature = "error_downcast", since = "1.3.0")]
     #[inline]
     pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
-        <Error + 'static>::downcast_mut::<T>(self)
+        <dyn Error + 'static>::downcast_mut::<T>(self)
     }
 }
 
-impl Error {
+impl dyn Error {
     #[inline]
     #[stable(feature = "error_downcast", since = "1.3.0")]
     /// Attempt to downcast the box to a concrete type.
-    pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Error>> {
+    pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error>> {
         if self.is::<T>() {
             unsafe {
-                let raw: *mut Error = Box::into_raw(self);
+                let raw: *mut dyn Error = Box::into_raw(self);
                 Ok(Box::from_raw(raw as *mut T))
             }
         } else {
@@ -486,30 +474,30 @@ impl Error {
     }
 }
 
-impl Error + Send {
+impl dyn Error + Send {
     #[inline]
     #[stable(feature = "error_downcast", since = "1.3.0")]
     /// Attempt to downcast the box to a concrete type.
     pub fn downcast<T: Error + 'static>(self: Box<Self>)
-                                        -> Result<Box<T>, Box<Error + Send>> {
-        let err: Box<Error> = self;
-        <Error>::downcast(err).map_err(|s| unsafe {
+                                        -> Result<Box<T>, Box<dyn Error + Send>> {
+        let err: Box<dyn Error> = self;
+        <dyn Error>::downcast(err).map_err(|s| unsafe {
             // reapply the Send marker
-            transmute::<Box<Error>, Box<Error + Send>>(s)
+            transmute::<Box<dyn Error>, Box<dyn Error + Send>>(s)
         })
     }
 }
 
-impl Error + Send + Sync {
+impl dyn Error + Send + Sync {
     #[inline]
     #[stable(feature = "error_downcast", since = "1.3.0")]
     /// Attempt to downcast the box to a concrete type.
     pub fn downcast<T: Error + 'static>(self: Box<Self>)
                                         -> Result<Box<T>, Box<Self>> {
-        let err: Box<Error> = self;
-        <Error>::downcast(err).map_err(|s| unsafe {
+        let err: Box<dyn Error> = self;
+        <dyn Error>::downcast(err).map_err(|s| unsafe {
             // reapply the Send+Sync marker
-            transmute::<Box<Error>, Box<Error + Send + Sync>>(s)
+            transmute::<Box<dyn Error>, Box<dyn Error + Send + Sync>>(s)
         })
     }
 }
@@ -545,13 +533,13 @@ mod tests {
     #[test]
     fn downcasting() {
         let mut a = A;
-        let a = &mut a as &mut (Error + 'static);
+        let a = &mut a as &mut (dyn Error + 'static);
         assert_eq!(a.downcast_ref::<A>(), Some(&A));
         assert_eq!(a.downcast_ref::<B>(), None);
         assert_eq!(a.downcast_mut::<A>(), Some(&mut A));
         assert_eq!(a.downcast_mut::<B>(), None);
 
-        let a: Box<Error> = Box::new(A);
+        let a: Box<dyn Error> = Box::new(A);
         match a.downcast::<B>() {
             Ok(..) => panic!("expected error"),
             Err(e) => assert_eq!(*e.downcast::<A>().unwrap(), A),
diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index 5e5695f15ac..8e8340b3ed9 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -11,20 +11,16 @@
 //! 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.
-//!
 //! *[See also the `f32` primitive type](../../std/primitive.f32.html).*
+//!
+//! Mathematically significant numbers are provided in the `consts` sub-module.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![allow(missing_docs)]
 
 #[cfg(not(test))]
-use core::num;
-#[cfg(not(test))]
 use intrinsics;
 #[cfg(not(test))]
-use num::FpCategory;
-#[cfg(not(test))]
 use sys::cmath;
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -39,109 +35,12 @@ pub use core::f32::{MIN, MIN_POSITIVE, MAX};
 pub use core::f32::consts;
 
 #[cfg(not(test))]
-#[lang = "f32"]
+#[lang = "f32_runtime"]
 impl f32 {
-    /// Returns `true` if this value is `NaN` and false otherwise.
-    ///
-    /// ```
-    /// use std::f32;
-    ///
-    /// let nan = f32::NAN;
-    /// let f = 7.0_f32;
-    ///
-    /// assert!(nan.is_nan());
-    /// assert!(!f.is_nan());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_nan(self) -> bool { num::Float::is_nan(self) }
-
-    /// Returns `true` if this value is positive infinity or negative infinity and
-    /// false otherwise.
-    ///
-    /// ```
-    /// use std::f32;
-    ///
-    /// let f = 7.0f32;
-    /// let inf = f32::INFINITY;
-    /// let neg_inf = f32::NEG_INFINITY;
-    /// let nan = f32::NAN;
-    ///
-    /// assert!(!f.is_infinite());
-    /// assert!(!nan.is_infinite());
-    ///
-    /// assert!(inf.is_infinite());
-    /// assert!(neg_inf.is_infinite());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_infinite(self) -> bool { num::Float::is_infinite(self) }
-
-    /// Returns `true` if this number is neither infinite nor `NaN`.
-    ///
-    /// ```
-    /// use std::f32;
-    ///
-    /// let f = 7.0f32;
-    /// let inf = f32::INFINITY;
-    /// let neg_inf = f32::NEG_INFINITY;
-    /// let nan = f32::NAN;
-    ///
-    /// assert!(f.is_finite());
-    ///
-    /// assert!(!nan.is_finite());
-    /// assert!(!inf.is_finite());
-    /// assert!(!neg_inf.is_finite());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_finite(self) -> bool { num::Float::is_finite(self) }
-
-    /// Returns `true` if the number is neither zero, infinite,
-    /// [subnormal][subnormal], or `NaN`.
-    ///
-    /// ```
-    /// use std::f32;
-    ///
-    /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32
-    /// let max = f32::MAX;
-    /// let lower_than_min = 1.0e-40_f32;
-    /// let zero = 0.0_f32;
-    ///
-    /// assert!(min.is_normal());
-    /// assert!(max.is_normal());
-    ///
-    /// assert!(!zero.is_normal());
-    /// assert!(!f32::NAN.is_normal());
-    /// assert!(!f32::INFINITY.is_normal());
-    /// // Values between `0` and `min` are Subnormal.
-    /// assert!(!lower_than_min.is_normal());
-    /// ```
-    /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_normal(self) -> bool { num::Float::is_normal(self) }
-
-    /// Returns the floating point category of the number. If only one property
-    /// is going to be tested, it is generally faster to use the specific
-    /// predicate instead.
-    ///
-    /// ```
-    /// use std::num::FpCategory;
-    /// use std::f32;
-    ///
-    /// let num = 12.4_f32;
-    /// let inf = f32::INFINITY;
-    ///
-    /// assert_eq!(num.classify(), FpCategory::Normal);
-    /// assert_eq!(inf.classify(), FpCategory::Infinite);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn classify(self) -> FpCategory { num::Float::classify(self) }
-
     /// Returns the largest integer less than or equal to a number.
     ///
+    /// # Examples
+    ///
     /// ```
     /// let f = 3.99_f32;
     /// let g = 3.0_f32;
@@ -173,6 +72,8 @@ impl f32 {
 
     /// Returns the smallest integer greater than or equal to a number.
     ///
+    /// # Examples
+    ///
     /// ```
     /// let f = 3.01_f32;
     /// let g = 4.0_f32;
@@ -193,6 +94,8 @@ impl f32 {
     /// Returns the nearest integer to a number. Round half-way cases away from
     /// `0.0`.
     ///
+    /// # Examples
+    ///
     /// ```
     /// let f = 3.3_f32;
     /// let g = -3.3_f32;
@@ -208,6 +111,8 @@ impl f32 {
 
     /// Returns the integer part of a number.
     ///
+    /// # Examples
+    ///
     /// ```
     /// let f = 3.3_f32;
     /// let g = -3.7_f32;
@@ -223,6 +128,8 @@ impl f32 {
 
     /// Returns the fractional part of a number.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -241,6 +148,8 @@ impl f32 {
     /// Computes the absolute value of `self`. Returns `NAN` if the
     /// number is `NAN`.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -257,7 +166,9 @@ impl f32 {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn abs(self) -> f32 { num::Float::abs(self) }
+    pub fn abs(self) -> f32 {
+        unsafe { intrinsics::fabsf32(self) }
+    }
 
     /// Returns a number that represents the sign of `self`.
     ///
@@ -265,6 +176,8 @@ impl f32 {
     /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
     /// - `NAN` if the number is `NAN`
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -277,39 +190,21 @@ impl f32 {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn signum(self) -> f32 { num::Float::signum(self) }
-
-    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
-    /// positive sign bit and positive infinity.
-    ///
-    /// ```
-    /// let f = 7.0_f32;
-    /// let g = -7.0_f32;
-    ///
-    /// assert!(f.is_sign_positive());
-    /// assert!(!g.is_sign_positive());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) }
+    pub fn signum(self) -> f32 {
+        if self.is_nan() {
+            NAN
+        } else {
+            unsafe { intrinsics::copysignf32(1.0, self) }
+        }
+    }
 
-    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
-    /// negative sign bit and negative infinity.
+    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
+    /// error, yielding a more accurate result than an unfused multiply-add.
     ///
-    /// ```
-    /// let f = 7.0f32;
-    /// let g = -7.0f32;
+    /// Using `mul_add` can be more performant than an unfused multiply-add if
+    /// the target architecture has a dedicated `fma` CPU instruction.
     ///
-    /// assert!(!f.is_sign_negative());
-    /// assert!(g.is_sign_negative());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_sign_negative(self) -> bool { num::Float::is_sign_negative(self) }
-
-    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
-    /// error. This produces a more accurate result with better performance than
-    /// a separate multiplication operation followed by an add.
+    /// # Examples
     ///
     /// ```
     /// use std::f32;
@@ -329,24 +224,76 @@ impl f32 {
         unsafe { intrinsics::fmaf32(self, a, b) }
     }
 
-    /// Takes the reciprocal (inverse) of a number, `1/x`.
+    /// Calculates Euclidean division, the matching method for `mod_euc`.
+    ///
+    /// This computes the integer `n` such that
+    /// `self = n * rhs + self.mod_euc(rhs)`.
+    /// In other words, the result is `self / rhs` rounded to the integer `n`
+    /// such that `self >= n * rhs`.
+    ///
+    /// # Examples
     ///
     /// ```
-    /// use std::f32;
+    /// #![feature(euclidean_division)]
+    /// let a: f32 = 7.0;
+    /// let b = 4.0;
+    /// assert_eq!(a.div_euc(b), 1.0); // 7.0 > 4.0 * 1.0
+    /// assert_eq!((-a).div_euc(b), -2.0); // -7.0 >= 4.0 * -2.0
+    /// assert_eq!(a.div_euc(-b), -1.0); // 7.0 >= -4.0 * -1.0
+    /// assert_eq!((-a).div_euc(-b), 2.0); // -7.0 >= -4.0 * 2.0
+    /// ```
+    #[inline]
+    #[unstable(feature = "euclidean_division", issue = "49048")]
+    pub fn div_euc(self, rhs: f32) -> f32 {
+        let q = (self / rhs).trunc();
+        if self % rhs < 0.0 {
+            return if rhs > 0.0 { q - 1.0 } else { q + 1.0 }
+        }
+        q
+    }
+
+    /// Calculates the Euclidean modulo (self mod rhs), which is never negative.
     ///
-    /// let x = 2.0_f32;
-    /// let abs_difference = (x.recip() - (1.0/x)).abs();
+    /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
+    /// most cases. However, due to a floating point round-off error it can
+    /// result in `r == rhs.abs()`, violating the mathematical definition, if
+    /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
+    /// This result is not an element of the function's codomain, but it is the
+    /// closest floating point number in the real numbers and thus fulfills the
+    /// property `self == self.div_euc(rhs) * rhs + self.mod_euc(rhs)`
+    /// approximatively.
+    ///
+    /// # Examples
     ///
-    /// assert!(abs_difference <= f32::EPSILON);
     /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
+    /// #![feature(euclidean_division)]
+    /// let a: f32 = 7.0;
+    /// let b = 4.0;
+    /// assert_eq!(a.mod_euc(b), 3.0);
+    /// assert_eq!((-a).mod_euc(b), 1.0);
+    /// assert_eq!(a.mod_euc(-b), 3.0);
+    /// assert_eq!((-a).mod_euc(-b), 1.0);
+    /// // limitation due to round-off error
+    /// assert!((-std::f32::EPSILON).mod_euc(3.0) != 0.0);
+    /// ```
     #[inline]
-    pub fn recip(self) -> f32 { num::Float::recip(self) }
+    #[unstable(feature = "euclidean_division", issue = "49048")]
+    pub fn mod_euc(self, rhs: f32) -> f32 {
+        let r = self % rhs;
+        if r < 0.0 {
+            r + rhs.abs()
+        } else {
+            r
+        }
+    }
+
 
     /// Raises a number to an integer power.
     ///
     /// Using this function is generally faster than using `powf`
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -357,10 +304,14 @@ impl f32 {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn powi(self, n: i32) -> f32 { num::Float::powi(self, n) }
+    pub fn powi(self, n: i32) -> f32 {
+        unsafe { intrinsics::powif32(self, n) }
+    }
 
     /// Raises a number to a floating point power.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -383,6 +334,8 @@ impl f32 {
     ///
     /// Returns NaN if `self` is a negative number.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -406,6 +359,8 @@ impl f32 {
 
     /// Returns `e^(self)`, (the exponential function).
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -430,6 +385,8 @@ impl f32 {
 
     /// Returns `2^(self)`.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -448,6 +405,8 @@ impl f32 {
 
     /// Returns the natural logarithm of the number.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -476,6 +435,8 @@ impl f32 {
     /// `self.log2()` can produce more accurate results for base 2, and
     /// `self.log10()` can produce more accurate results for base 10.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -492,6 +453,8 @@ impl f32 {
 
     /// Returns the base 2 logarithm of the number.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -513,6 +476,8 @@ impl f32 {
 
     /// Returns the base 10 logarithm of the number.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -533,73 +498,13 @@ impl f32 {
         return unsafe { intrinsics::log10f32(self) };
     }
 
-    /// Converts radians to degrees.
-    ///
-    /// ```
-    /// use std::f32::{self, consts};
-    ///
-    /// let angle = consts::PI;
-    ///
-    /// let abs_difference = (angle.to_degrees() - 180.0).abs();
-    ///
-    /// assert!(abs_difference <= f32::EPSILON);
-    /// ```
-    #[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
-    #[inline]
-    pub fn to_degrees(self) -> f32 { num::Float::to_degrees(self) }
-
-    /// Converts degrees to radians.
-    ///
-    /// ```
-    /// use std::f32::{self, consts};
-    ///
-    /// let angle = 180.0f32;
-    ///
-    /// let abs_difference = (angle.to_radians() - consts::PI).abs();
-    ///
-    /// assert!(abs_difference <= f32::EPSILON);
-    /// ```
-    #[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
-    #[inline]
-    pub fn to_radians(self) -> f32 { num::Float::to_radians(self) }
-
-    /// Returns the maximum of the two numbers.
-    ///
-    /// ```
-    /// let x = 1.0f32;
-    /// let y = 2.0f32;
-    ///
-    /// assert_eq!(x.max(y), y);
-    /// ```
-    ///
-    /// If one of the arguments is NaN, then the other argument is returned.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn max(self, other: f32) -> f32 {
-        num::Float::max(self, other)
-    }
-
-    /// Returns the minimum of the two numbers.
-    ///
-    /// ```
-    /// let x = 1.0f32;
-    /// let y = 2.0f32;
-    ///
-    /// assert_eq!(x.min(y), x);
-    /// ```
-    ///
-    /// If one of the arguments is NaN, then the other argument is returned.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn min(self, other: f32) -> f32 {
-        num::Float::min(self, other)
-    }
-
     /// The positive difference of two numbers.
     ///
     /// * If `self <= other`: `0:0`
     /// * Else: `self - other`
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -627,6 +532,8 @@ impl f32 {
 
     /// Takes the cubic root of a number.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -646,6 +553,8 @@ impl f32 {
     /// Calculates the length of the hypotenuse of a right-angle triangle given
     /// legs of length `x` and `y`.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -665,6 +574,8 @@ impl f32 {
 
     /// Computes the sine of a number (in radians).
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -686,6 +597,8 @@ impl f32 {
 
     /// Computes the cosine of a number (in radians).
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -707,6 +620,8 @@ impl f32 {
 
     /// Computes the tangent of a number (in radians).
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -725,6 +640,8 @@ impl f32 {
     /// the range [-pi/2, pi/2] or NaN if the number is outside the range
     /// [-1, 1].
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -745,6 +662,8 @@ impl f32 {
     /// the range [0, pi] or NaN if the number is outside the range
     /// [-1, 1].
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -764,6 +683,8 @@ impl f32 {
     /// Computes the arctangent of a number. Return value is in radians in the
     /// range [-pi/2, pi/2];
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -780,23 +701,26 @@ impl f32 {
         unsafe { cmath::atanf(self) }
     }
 
-    /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`).
+    /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians.
     ///
     /// * `x = 0`, `y = 0`: `0`
     /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
     /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
     /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
     /// let pi = f32::consts::PI;
-    /// // All angles from horizontal right (+x)
-    /// // 45 deg counter-clockwise
+    /// // Positive angles measured counter-clockwise
+    /// // from positive x axis
+    /// // -pi/4 radians (45 deg clockwise)
     /// let x1 = 3.0f32;
     /// let y1 = -3.0f32;
     ///
-    /// // 135 deg clockwise
+    /// // 3pi/4 radians (135 deg counter-clockwise)
     /// let x2 = -3.0f32;
     /// let y2 = 3.0f32;
     ///
@@ -815,6 +739,8 @@ impl f32 {
     /// Simultaneously computes the sine and cosine of the number, `x`. Returns
     /// `(sin(x), cos(x))`.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -836,6 +762,8 @@ impl f32 {
     /// Returns `e^(self) - 1` in a way that is accurate even if the
     /// number is close to zero.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -855,6 +783,8 @@ impl f32 {
     /// Returns `ln(1+n)` (natural logarithm) more accurately than if
     /// the operations were performed separately.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -873,6 +803,8 @@ impl f32 {
 
     /// Hyperbolic sine function.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -894,6 +826,8 @@ impl f32 {
 
     /// Hyperbolic cosine function.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -915,6 +849,8 @@ impl f32 {
 
     /// Hyperbolic tangent function.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -936,6 +872,8 @@ impl f32 {
 
     /// Inverse hyperbolic sine function.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -958,6 +896,8 @@ impl f32 {
 
     /// Inverse hyperbolic cosine function.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -979,6 +919,8 @@ impl f32 {
 
     /// Inverse hyperbolic tangent function.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f32;
     ///
@@ -994,74 +936,6 @@ impl f32 {
     pub fn atanh(self) -> f32 {
         0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
     }
-
-    /// Raw transmutation to `u32`.
-    ///
-    /// 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 `as` casting, which attempts to
-    /// preserve the *numeric* value, and not the bitwise value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// assert_ne!((1f32).to_bits(), 1f32 as u32); // to_bits() is not casting!
-    /// assert_eq!((12.5f32).to_bits(), 0x41480000);
-    ///
-    /// ```
-    #[stable(feature = "float_bits_conv", since = "1.20.0")]
-    #[inline]
-    pub fn to_bits(self) -> u32 {
-        unsafe { ::mem::transmute(self) }
-    }
-
-    /// Raw transmutation from `u32`.
-    ///
-    /// 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.
-    ///
-    /// 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
-    ///
-    /// ```
-    /// use std::f32;
-    /// let v = f32::from_bits(0x41480000);
-    /// let difference = (v - 12.5).abs();
-    /// assert!(difference <= 1e-5);
-    /// ```
-    #[stable(feature = "float_bits_conv", since = "1.20.0")]
-    #[inline]
-    pub fn from_bits(v: u32) -> Self {
-        // It turns out the safety issues with sNaN were overblown! Hooray!
-        unsafe { ::mem::transmute(v) }
-    }
 }
 
 #[cfg(test)]
@@ -1532,6 +1406,7 @@ mod tests {
         assert!(nan.to_degrees().is_nan());
         assert_eq!(inf.to_degrees(), inf);
         assert_eq!(neg_inf.to_degrees(), neg_inf);
+        assert_eq!(1_f32.to_degrees(), 57.2957795130823208767981548141051703);
     }
 
     #[test]
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index e4eea745bb7..6880294afca 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -11,20 +11,16 @@
 //! 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.
-//!
 //! *[See also the `f64` primitive type](../../std/primitive.f64.html).*
+//!
+//! Mathematically significant numbers are provided in the `consts` sub-module.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![allow(missing_docs)]
 
 #[cfg(not(test))]
-use core::num;
-#[cfg(not(test))]
 use intrinsics;
 #[cfg(not(test))]
-use num::FpCategory;
-#[cfg(not(test))]
 use sys::cmath;
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -39,109 +35,12 @@ pub use core::f64::{MIN, MIN_POSITIVE, MAX};
 pub use core::f64::consts;
 
 #[cfg(not(test))]
-#[lang = "f64"]
+#[lang = "f64_runtime"]
 impl f64 {
-    /// Returns `true` if this value is `NaN` and false otherwise.
-    ///
-    /// ```
-    /// use std::f64;
-    ///
-    /// let nan = f64::NAN;
-    /// let f = 7.0_f64;
-    ///
-    /// assert!(nan.is_nan());
-    /// assert!(!f.is_nan());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_nan(self) -> bool { num::Float::is_nan(self) }
-
-    /// Returns `true` if this value is positive infinity or negative infinity and
-    /// false otherwise.
-    ///
-    /// ```
-    /// use std::f64;
-    ///
-    /// let f = 7.0f64;
-    /// let inf = f64::INFINITY;
-    /// let neg_inf = f64::NEG_INFINITY;
-    /// let nan = f64::NAN;
-    ///
-    /// assert!(!f.is_infinite());
-    /// assert!(!nan.is_infinite());
-    ///
-    /// assert!(inf.is_infinite());
-    /// assert!(neg_inf.is_infinite());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_infinite(self) -> bool { num::Float::is_infinite(self) }
-
-    /// Returns `true` if this number is neither infinite nor `NaN`.
-    ///
-    /// ```
-    /// use std::f64;
-    ///
-    /// let f = 7.0f64;
-    /// let inf: f64 = f64::INFINITY;
-    /// let neg_inf: f64 = f64::NEG_INFINITY;
-    /// let nan: f64 = f64::NAN;
-    ///
-    /// assert!(f.is_finite());
-    ///
-    /// assert!(!nan.is_finite());
-    /// assert!(!inf.is_finite());
-    /// assert!(!neg_inf.is_finite());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_finite(self) -> bool { num::Float::is_finite(self) }
-
-    /// Returns `true` if the number is neither zero, infinite,
-    /// [subnormal][subnormal], or `NaN`.
-    ///
-    /// ```
-    /// use std::f64;
-    ///
-    /// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308f64
-    /// let max = f64::MAX;
-    /// let lower_than_min = 1.0e-308_f64;
-    /// let zero = 0.0f64;
-    ///
-    /// assert!(min.is_normal());
-    /// assert!(max.is_normal());
-    ///
-    /// assert!(!zero.is_normal());
-    /// assert!(!f64::NAN.is_normal());
-    /// assert!(!f64::INFINITY.is_normal());
-    /// // Values between `0` and `min` are Subnormal.
-    /// assert!(!lower_than_min.is_normal());
-    /// ```
-    /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_normal(self) -> bool { num::Float::is_normal(self) }
-
-    /// Returns the floating point category of the number. If only one property
-    /// is going to be tested, it is generally faster to use the specific
-    /// predicate instead.
-    ///
-    /// ```
-    /// use std::num::FpCategory;
-    /// use std::f64;
-    ///
-    /// let num = 12.4_f64;
-    /// let inf = f64::INFINITY;
-    ///
-    /// assert_eq!(num.classify(), FpCategory::Normal);
-    /// assert_eq!(inf.classify(), FpCategory::Infinite);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn classify(self) -> FpCategory { num::Float::classify(self) }
-
     /// Returns the largest integer less than or equal to a number.
     ///
+    /// # Examples
+    ///
     /// ```
     /// let f = 3.99_f64;
     /// let g = 3.0_f64;
@@ -157,6 +56,8 @@ impl f64 {
 
     /// Returns the smallest integer greater than or equal to a number.
     ///
+    /// # Examples
+    ///
     /// ```
     /// let f = 3.01_f64;
     /// let g = 4.0_f64;
@@ -173,6 +74,8 @@ impl f64 {
     /// Returns the nearest integer to a number. Round half-way cases away from
     /// `0.0`.
     ///
+    /// # Examples
+    ///
     /// ```
     /// let f = 3.3_f64;
     /// let g = -3.3_f64;
@@ -188,6 +91,8 @@ impl f64 {
 
     /// Returns the integer part of a number.
     ///
+    /// # Examples
+    ///
     /// ```
     /// let f = 3.3_f64;
     /// let g = -3.7_f64;
@@ -203,6 +108,8 @@ impl f64 {
 
     /// Returns the fractional part of a number.
     ///
+    /// # Examples
+    ///
     /// ```
     /// let x = 3.5_f64;
     /// let y = -3.5_f64;
@@ -219,6 +126,8 @@ impl f64 {
     /// Computes the absolute value of `self`. Returns `NAN` if the
     /// number is `NAN`.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f64;
     ///
@@ -235,7 +144,9 @@ impl f64 {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn abs(self) -> f64 { num::Float::abs(self) }
+    pub fn abs(self) -> f64 {
+        unsafe { intrinsics::fabsf64(self) }
+    }
 
     /// Returns a number that represents the sign of `self`.
     ///
@@ -243,6 +154,8 @@ impl f64 {
     /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
     /// - `NAN` if the number is `NAN`
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f64;
     ///
@@ -255,49 +168,21 @@ impl f64 {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn signum(self) -> f64 { num::Float::signum(self) }
-
-    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
-    /// positive sign bit and positive infinity.
-    ///
-    /// ```
-    /// let f = 7.0_f64;
-    /// let g = -7.0_f64;
-    ///
-    /// assert!(f.is_sign_positive());
-    /// assert!(!g.is_sign_positive());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) }
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_positive")]
-    #[inline]
-    pub fn is_positive(self) -> bool { num::Float::is_sign_positive(self) }
+    pub fn signum(self) -> f64 {
+        if self.is_nan() {
+            NAN
+        } else {
+            unsafe { intrinsics::copysignf64(1.0, self) }
+        }
+    }
 
-    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
-    /// negative sign bit and negative infinity.
+    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
+    /// error, yielding a more accurate result than an unfused multiply-add.
     ///
-    /// ```
-    /// let f = 7.0_f64;
-    /// let g = -7.0_f64;
+    /// Using `mul_add` can be more performant than an unfused multiply-add if
+    /// the target architecture has a dedicated `fma` CPU instruction.
     ///
-    /// assert!(!f.is_sign_negative());
-    /// assert!(g.is_sign_negative());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_sign_negative(self) -> bool { num::Float::is_sign_negative(self) }
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_negative")]
-    #[inline]
-    pub fn is_negative(self) -> bool { num::Float::is_sign_negative(self) }
-
-    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
-    /// error. This produces a more accurate result with better performance than
-    /// a separate multiplication operation followed by an add.
+    /// # Examples
     ///
     /// ```
     /// let m = 10.0_f64;
@@ -315,22 +200,75 @@ impl f64 {
         unsafe { intrinsics::fmaf64(self, a, b) }
     }
 
-    /// Takes the reciprocal (inverse) of a number, `1/x`.
+    /// Calculates Euclidean division, the matching method for `mod_euc`.
+    ///
+    /// This computes the integer `n` such that
+    /// `self = n * rhs + self.mod_euc(rhs)`.
+    /// In other words, the result is `self / rhs` rounded to the integer `n`
+    /// such that `self >= n * rhs`.
+    ///
+    /// # Examples
     ///
     /// ```
-    /// let x = 2.0_f64;
-    /// let abs_difference = (x.recip() - (1.0/x)).abs();
+    /// #![feature(euclidean_division)]
+    /// let a: f64 = 7.0;
+    /// let b = 4.0;
+    /// assert_eq!(a.div_euc(b), 1.0); // 7.0 > 4.0 * 1.0
+    /// assert_eq!((-a).div_euc(b), -2.0); // -7.0 >= 4.0 * -2.0
+    /// assert_eq!(a.div_euc(-b), -1.0); // 7.0 >= -4.0 * -1.0
+    /// assert_eq!((-a).div_euc(-b), 2.0); // -7.0 >= -4.0 * 2.0
+    /// ```
+    #[inline]
+    #[unstable(feature = "euclidean_division", issue = "49048")]
+    pub fn div_euc(self, rhs: f64) -> f64 {
+        let q = (self / rhs).trunc();
+        if self % rhs < 0.0 {
+            return if rhs > 0.0 { q - 1.0 } else { q + 1.0 }
+        }
+        q
+    }
+
+    /// Calculates the Euclidean modulo (self mod rhs), which is never negative.
+    ///
+    /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
+    /// most cases.  However, due to a floating point round-off error it can
+    /// result in `r == rhs.abs()`, violating the mathematical definition, if
+    /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
+    /// This result is not an element of the function's codomain, but it is the
+    /// closest floating point number in the real numbers and thus fulfills the
+    /// property `self == self.div_euc(rhs) * rhs + self.mod_euc(rhs)`
+    /// approximatively.
+    ///
+    /// # Examples
     ///
-    /// assert!(abs_difference < 1e-10);
     /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
+    /// #![feature(euclidean_division)]
+    /// let a: f64 = 7.0;
+    /// let b = 4.0;
+    /// assert_eq!(a.mod_euc(b), 3.0);
+    /// assert_eq!((-a).mod_euc(b), 1.0);
+    /// assert_eq!(a.mod_euc(-b), 3.0);
+    /// assert_eq!((-a).mod_euc(-b), 1.0);
+    /// // limitation due to round-off error
+    /// assert!((-std::f64::EPSILON).mod_euc(3.0) != 0.0);
+    /// ```
     #[inline]
-    pub fn recip(self) -> f64 { num::Float::recip(self) }
+    #[unstable(feature = "euclidean_division", issue = "49048")]
+    pub fn mod_euc(self, rhs: f64) -> f64 {
+        let r = self % rhs;
+        if r < 0.0 {
+            r + rhs.abs()
+        } else {
+            r
+        }
+    }
 
     /// Raises a number to an integer power.
     ///
     /// Using this function is generally faster than using `powf`
     ///
+    /// # Examples
+    ///
     /// ```
     /// let x = 2.0_f64;
     /// let abs_difference = (x.powi(2) - x*x).abs();
@@ -339,10 +277,14 @@ impl f64 {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn powi(self, n: i32) -> f64 { num::Float::powi(self, n) }
+    pub fn powi(self, n: i32) -> f64 {
+        unsafe { intrinsics::powif64(self, n) }
+    }
 
     /// Raises a number to a floating point power.
     ///
+    /// # Examples
+    ///
     /// ```
     /// let x = 2.0_f64;
     /// let abs_difference = (x.powf(2.0) - x*x).abs();
@@ -359,6 +301,8 @@ impl f64 {
     ///
     /// Returns NaN if `self` is a negative number.
     ///
+    /// # Examples
+    ///
     /// ```
     /// let positive = 4.0_f64;
     /// let negative = -4.0_f64;
@@ -380,6 +324,8 @@ impl f64 {
 
     /// Returns `e^(self)`, (the exponential function).
     ///
+    /// # Examples
+    ///
     /// ```
     /// let one = 1.0_f64;
     /// // e^1
@@ -398,6 +344,8 @@ impl f64 {
 
     /// Returns `2^(self)`.
     ///
+    /// # Examples
+    ///
     /// ```
     /// let f = 2.0_f64;
     ///
@@ -414,6 +362,8 @@ impl f64 {
 
     /// Returns the natural logarithm of the number.
     ///
+    /// # Examples
+    ///
     /// ```
     /// let one = 1.0_f64;
     /// // e^1
@@ -436,6 +386,8 @@ impl f64 {
     /// `self.log2()` can produce more accurate results for base 2, and
     /// `self.log10()` can produce more accurate results for base 10.
     ///
+    /// # Examples
+    ///
     /// ```
     /// let five = 5.0_f64;
     ///
@@ -450,6 +402,8 @@ impl f64 {
 
     /// Returns the base 2 logarithm of the number.
     ///
+    /// # Examples
+    ///
     /// ```
     /// let two = 2.0_f64;
     ///
@@ -471,6 +425,8 @@ impl f64 {
 
     /// Returns the base 10 logarithm of the number.
     ///
+    /// # Examples
+    ///
     /// ```
     /// let ten = 10.0_f64;
     ///
@@ -485,73 +441,13 @@ impl f64 {
         self.log_wrapper(|n| { unsafe { intrinsics::log10f64(n) } })
     }
 
-    /// Converts radians to degrees.
-    ///
-    /// ```
-    /// use std::f64::consts;
-    ///
-    /// let angle = consts::PI;
-    ///
-    /// let abs_difference = (angle.to_degrees() - 180.0).abs();
-    ///
-    /// assert!(abs_difference < 1e-10);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn to_degrees(self) -> f64 { num::Float::to_degrees(self) }
-
-    /// Converts degrees to radians.
-    ///
-    /// ```
-    /// use std::f64::consts;
-    ///
-    /// let angle = 180.0_f64;
-    ///
-    /// let abs_difference = (angle.to_radians() - consts::PI).abs();
-    ///
-    /// assert!(abs_difference < 1e-10);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn to_radians(self) -> f64 { num::Float::to_radians(self) }
-
-    /// Returns the maximum of the two numbers.
-    ///
-    /// ```
-    /// let x = 1.0_f64;
-    /// let y = 2.0_f64;
-    ///
-    /// assert_eq!(x.max(y), y);
-    /// ```
-    ///
-    /// If one of the arguments is NaN, then the other argument is returned.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn max(self, other: f64) -> f64 {
-        num::Float::max(self, other)
-    }
-
-    /// Returns the minimum of the two numbers.
-    ///
-    /// ```
-    /// let x = 1.0_f64;
-    /// let y = 2.0_f64;
-    ///
-    /// assert_eq!(x.min(y), x);
-    /// ```
-    ///
-    /// If one of the arguments is NaN, then the other argument is returned.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn min(self, other: f64) -> f64 {
-        num::Float::min(self, other)
-    }
-
     /// The positive difference of two numbers.
     ///
     /// * If `self <= other`: `0:0`
     /// * Else: `self - other`
     ///
+    /// # Examples
+    ///
     /// ```
     /// let x = 3.0_f64;
     /// let y = -3.0_f64;
@@ -577,6 +473,8 @@ impl f64 {
 
     /// Takes the cubic root of a number.
     ///
+    /// # Examples
+    ///
     /// ```
     /// let x = 8.0_f64;
     ///
@@ -594,6 +492,8 @@ impl f64 {
     /// Calculates the length of the hypotenuse of a right-angle triangle given
     /// legs of length `x` and `y`.
     ///
+    /// # Examples
+    ///
     /// ```
     /// let x = 2.0_f64;
     /// let y = 3.0_f64;
@@ -611,6 +511,8 @@ impl f64 {
 
     /// Computes the sine of a number (in radians).
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f64;
     ///
@@ -628,6 +530,8 @@ impl f64 {
 
     /// Computes the cosine of a number (in radians).
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f64;
     ///
@@ -645,6 +549,8 @@ impl f64 {
 
     /// Computes the tangent of a number (in radians).
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f64;
     ///
@@ -663,6 +569,8 @@ impl f64 {
     /// the range [-pi/2, pi/2] or NaN if the number is outside the range
     /// [-1, 1].
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f64;
     ///
@@ -683,6 +591,8 @@ impl f64 {
     /// the range [0, pi] or NaN if the number is outside the range
     /// [-1, 1].
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f64;
     ///
@@ -702,6 +612,8 @@ impl f64 {
     /// Computes the arctangent of a number. Return value is in radians in the
     /// range [-pi/2, pi/2];
     ///
+    /// # Examples
+    ///
     /// ```
     /// let f = 1.0_f64;
     ///
@@ -716,23 +628,26 @@ impl f64 {
         unsafe { cmath::atan(self) }
     }
 
-    /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`).
+    /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians.
     ///
     /// * `x = 0`, `y = 0`: `0`
     /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
     /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
     /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f64;
     ///
     /// let pi = f64::consts::PI;
-    /// // All angles from horizontal right (+x)
-    /// // 45 deg counter-clockwise
+    /// // Positive angles measured counter-clockwise
+    /// // from positive x axis
+    /// // -pi/4 radians (45 deg clockwise)
     /// let x1 = 3.0_f64;
     /// let y1 = -3.0_f64;
     ///
-    /// // 135 deg clockwise
+    /// // 3pi/4 radians (135 deg counter-clockwise)
     /// let x2 = -3.0_f64;
     /// let y2 = 3.0_f64;
     ///
@@ -751,6 +666,8 @@ impl f64 {
     /// Simultaneously computes the sine and cosine of the number, `x`. Returns
     /// `(sin(x), cos(x))`.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f64;
     ///
@@ -772,6 +689,8 @@ impl f64 {
     /// Returns `e^(self) - 1` in a way that is accurate even if the
     /// number is close to zero.
     ///
+    /// # Examples
+    ///
     /// ```
     /// let x = 7.0_f64;
     ///
@@ -789,6 +708,8 @@ impl f64 {
     /// Returns `ln(1+n)` (natural logarithm) more accurately than if
     /// the operations were performed separately.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f64;
     ///
@@ -807,6 +728,8 @@ impl f64 {
 
     /// Hyperbolic sine function.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f64;
     ///
@@ -828,6 +751,8 @@ impl f64 {
 
     /// Hyperbolic cosine function.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f64;
     ///
@@ -849,6 +774,8 @@ impl f64 {
 
     /// Hyperbolic tangent function.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f64;
     ///
@@ -870,6 +797,8 @@ impl f64 {
 
     /// Inverse hyperbolic sine function.
     ///
+    /// # Examples
+    ///
     /// ```
     /// let x = 1.0_f64;
     /// let f = x.sinh().asinh();
@@ -890,6 +819,8 @@ impl f64 {
 
     /// Inverse hyperbolic cosine function.
     ///
+    /// # Examples
+    ///
     /// ```
     /// let x = 1.0_f64;
     /// let f = x.cosh().acosh();
@@ -909,6 +840,8 @@ impl f64 {
 
     /// Inverse hyperbolic tangent function.
     ///
+    /// # Examples
+    ///
     /// ```
     /// use std::f64;
     ///
@@ -949,74 +882,6 @@ impl f64 {
             }
         }
     }
-
-    /// Raw transmutation to `u64`.
-    ///
-    /// 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 `as` casting, which attempts to
-    /// preserve the *numeric* value, and not the bitwise value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// assert!((1f64).to_bits() != 1f64 as u64); // to_bits() is not casting!
-    /// assert_eq!((12.5f64).to_bits(), 0x4029000000000000);
-    ///
-    /// ```
-    #[stable(feature = "float_bits_conv", since = "1.20.0")]
-    #[inline]
-    pub fn to_bits(self) -> u64 {
-        unsafe { ::mem::transmute(self) }
-    }
-
-    /// Raw transmutation from `u64`.
-    ///
-    /// 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.
-    ///
-    /// 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.
-    ///
-    /// 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
-    ///
-    /// ```
-    /// use std::f64;
-    /// let v = f64::from_bits(0x4029000000000000);
-    /// let difference = (v - 12.5).abs();
-    /// assert!(difference <= 1e-5);
-    /// ```
-    #[stable(feature = "float_bits_conv", since = "1.20.0")]
-    #[inline]
-    pub fn from_bits(v: u64) -> Self {
-        // It turns out the safety issues with sNaN were overblown! Hooray!
-        unsafe { ::mem::transmute(v) }
-    }
 }
 
 #[cfg(test)]
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index a19fe825f21..2b87094926c 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -91,7 +91,7 @@ use sys;
 ///
 /// # Examples
 ///
-/// ```no_run
+/// ```ignore (extern-declaration)
 /// # fn main() {
 /// use std::ffi::CString;
 /// use std::os::raw::c_char;
@@ -150,7 +150,7 @@ pub struct CString {
 ///
 /// Inspecting a foreign C string:
 ///
-/// ```no_run
+/// ```ignore (extern-declaration)
 /// use std::ffi::CStr;
 /// use std::os::raw::c_char;
 ///
@@ -164,7 +164,7 @@ pub struct CString {
 ///
 /// Passing a Rust-originating C string:
 ///
-/// ```no_run
+/// ```ignore (extern-declaration)
 /// use std::ffi::{CString, CStr};
 /// use std::os::raw::c_char;
 ///
@@ -180,7 +180,7 @@ pub struct CString {
 ///
 /// Converting a foreign C string into a Rust [`String`]:
 ///
-/// ```no_run
+/// ```ignore (extern-declaration)
 /// use std::ffi::CStr;
 /// use std::os::raw::c_char;
 ///
@@ -307,7 +307,7 @@ impl CString {
     ///
     /// # Examples
     ///
-    /// ```no_run
+    /// ```ignore (extern-declaration)
     /// use std::ffi::CString;
     /// use std::os::raw::c_char;
     ///
@@ -389,7 +389,7 @@ impl CString {
     /// Create a `CString`, pass ownership to an `extern` function (via raw pointer), then retake
     /// ownership with `from_raw`:
     ///
-    /// ```no_run
+    /// ```ignore (extern-declaration)
     /// use std::ffi::CString;
     /// use std::os::raw::c_char;
     ///
@@ -642,6 +642,12 @@ impl fmt::Debug for CString {
 
 #[stable(feature = "cstring_into", since = "1.7.0")]
 impl From<CString> for Vec<u8> {
+    /// Converts a [`CString`] into a [`Vec`]`<u8>`.
+    ///
+    /// The conversion consumes the [`CString`], and removes the terminating NUL byte.
+    ///
+    /// [`Vec`]: ../vec/struct.Vec.html
+    /// [`CString`]: ../ffi/struct.CString.html
     #[inline]
     fn from(s: CString) -> Vec<u8> {
         s.into_bytes()
@@ -682,6 +688,14 @@ impl Borrow<CStr> for CString {
     fn borrow(&self) -> &CStr { self }
 }
 
+#[stable(feature = "cstring_from_cow_cstr", since = "1.28.0")]
+impl<'a> From<Cow<'a, CStr>> for CString {
+    #[inline]
+    fn from(s: Cow<'a, CStr>) -> Self {
+        s.into_owned()
+    }
+}
+
 #[stable(feature = "box_from_c_str", since = "1.17.0")]
 impl<'a> From<&'a CStr> for Box<CStr> {
     fn from(s: &'a CStr) -> Box<CStr> {
@@ -692,22 +706,66 @@ impl<'a> From<&'a CStr> for Box<CStr> {
 
 #[stable(feature = "c_string_from_box", since = "1.18.0")]
 impl From<Box<CStr>> for CString {
+    /// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating.
+    ///
+    /// [`Box`]: ../boxed/struct.Box.html
+    /// [`CString`]: ../ffi/struct.CString.html
     #[inline]
     fn from(s: Box<CStr>) -> CString {
         s.into_c_string()
     }
 }
 
+#[stable(feature = "more_box_slice_clone", since = "1.29.0")]
+impl Clone for Box<CStr> {
+    #[inline]
+    fn clone(&self) -> Self {
+        (**self).into()
+    }
+}
+
 #[stable(feature = "box_from_c_string", since = "1.20.0")]
 impl From<CString> for Box<CStr> {
+    /// Converts a [`CString`] into a [`Box`]`<CStr>` without copying or allocating.
+    ///
+    /// [`CString`]: ../ffi/struct.CString.html
+    /// [`Box`]: ../boxed/struct.Box.html
     #[inline]
     fn from(s: CString) -> Box<CStr> {
         s.into_boxed_c_str()
     }
 }
 
+#[stable(feature = "cow_from_cstr", since = "1.28.0")]
+impl<'a> From<CString> for Cow<'a, CStr> {
+    #[inline]
+    fn from(s: CString) -> Cow<'a, CStr> {
+        Cow::Owned(s)
+    }
+}
+
+#[stable(feature = "cow_from_cstr", since = "1.28.0")]
+impl<'a> From<&'a CStr> for Cow<'a, CStr> {
+    #[inline]
+    fn from(s: &'a CStr) -> Cow<'a, CStr> {
+        Cow::Borrowed(s)
+    }
+}
+
+#[stable(feature = "cow_from_cstr", since = "1.28.0")]
+impl<'a> From<&'a CString> for Cow<'a, CStr> {
+    #[inline]
+    fn from(s: &'a CString) -> Cow<'a, CStr> {
+        Cow::Borrowed(s.as_c_str())
+    }
+}
+
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<CString> for Arc<CStr> {
+    /// Converts a [`CString`] into a [`Arc`]`<CStr>` without copying or allocating.
+    ///
+    /// [`CString`]: ../ffi/struct.CString.html
+    /// [`Arc`]: ../sync/struct.Arc.html
     #[inline]
     fn from(s: CString) -> Arc<CStr> {
         let arc: Arc<[u8]> = Arc::from(s.into_inner());
@@ -726,6 +784,10 @@ impl<'a> From<&'a CStr> for Arc<CStr> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<CString> for Rc<CStr> {
+    /// Converts a [`CString`] into a [`Rc`]`<CStr>` without copying or allocating.
+    ///
+    /// [`CString`]: ../ffi/struct.CString.html
+    /// [`Rc`]: ../rc/struct.Rc.html
     #[inline]
     fn from(s: CString) -> Rc<CStr> {
         let rc: Rc<[u8]> = Rc::from(s.into_inner());
@@ -799,6 +861,10 @@ impl fmt::Display for NulError {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl From<NulError> for io::Error {
+    /// Converts a [`NulError`] into a [`io::Error`].
+    ///
+    /// [`NulError`]: ../ffi/struct.NulError.html
+    /// [`io::Error`]: ../io/struct.Error.html
     fn from(_: NulError) -> io::Error {
         io::Error::new(io::ErrorKind::InvalidInput,
                        "data provided contains a nul byte")
@@ -851,7 +917,7 @@ impl Error for IntoStringError {
         "C string contained non-utf8 bytes"
     }
 
-    fn cause(&self) -> Option<&Error> {
+    fn cause(&self) -> Option<&dyn Error> {
         Some(&self.error)
     }
 }
@@ -875,6 +941,8 @@ impl CStr {
     ///   `ptr`.
     /// * There is no guarantee that the memory pointed to by `ptr` contains a
     ///   valid nul terminator byte at the end of the string.
+    /// * It is not guaranteed that the memory pointed by `ptr` won't change
+    ///   before the `CStr` has been destroyed.
     ///
     /// > **Note**: This operation is intended to be a 0-cost cast but it is
     /// > currently implemented with an up-front calculation of the length of
@@ -882,7 +950,7 @@ impl CStr {
     ///
     /// # Examples
     ///
-    /// ```no_run
+    /// ```ignore (extern-declaration)
     /// # fn main() {
     /// use std::ffi::CStr;
     /// use std::os::raw::c_char;
@@ -986,6 +1054,7 @@ impl CStr {
     /// behavior when `ptr` is used inside the `unsafe` block:
     ///
     /// ```no_run
+    /// # #![allow(unused_must_use)]
     /// use std::ffi::{CString};
     ///
     /// let ptr = CString::new("Hello").unwrap().as_ptr();
@@ -1001,6 +1070,7 @@ impl CStr {
     /// To fix the problem, bind the `CString` to a local variable:
     ///
     /// ```no_run
+    /// # #![allow(unused_must_use)]
     /// use std::ffi::{CString};
     ///
     /// let hello = CString::new("Hello").unwrap();
@@ -1026,9 +1096,9 @@ impl CStr {
     /// 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
-    /// > it is planned to alter its definition in the future to perform the
-    /// > length calculation whenever this method is called.
+    /// > **Note**: This method is currently implemented as a constant-time
+    /// > cast, but it is planned to alter its definition in the future to
+    /// > perform the length calculation whenever this method is called.
     ///
     /// # Examples
     ///
@@ -1077,9 +1147,9 @@ impl CStr {
     /// 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
-    /// > future to perform the length calculation in addition to the UTF-8
-    /// > check whenever this method is called.
+    /// > after a constant-time cast, but it is planned to alter its definition
+    /// > in the future to perform the length calculation in addition to the
+    /// > UTF-8 check whenever this method is called.
     ///
     /// [`&str`]: ../primitive.str.html
     ///
@@ -1105,19 +1175,21 @@ impl CStr {
     /// 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.
+    /// replace any invalid UTF-8 sequences with
+    /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] 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
-    /// > future to perform the length calculation in addition to the UTF-8
-    /// > check whenever this method is called.
+    /// > after a constant-time cast, but it is planned to alter its definition
+    /// > in the future to perform the length calculation in addition to the
+    /// > UTF-8 check whenever this method is called.
     ///
     /// [`Cow`]: ../borrow/enum.Cow.html
     /// [`Borrowed`]: ../borrow/enum.Cow.html#variant.Borrowed
+    /// [`Owned`]: ../borrow/enum.Cow.html#variant.Owned
     /// [`str`]: ../primitive.str.html
     /// [`String`]: ../string/struct.String.html
+    /// [U+FFFD]: ../char/constant.REPLACEMENT_CHARACTER.html
     ///
     /// # Examples
     ///
diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs
index 3959e8533be..6bcd62dbd59 100644
--- a/src/libstd/ffi/os_str.rs
+++ b/src/libstd/ffi/os_str.rs
@@ -61,7 +61,7 @@ use sys_common::{AsInner, IntoInner, FromInner};
 /// # 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.
+/// the traits which `OsString` implements for [conversions] from/to native representations.
 ///
 /// [`OsStr`]: struct.OsStr.html
 /// [`&OsStr`]: struct.OsStr.html
@@ -74,6 +74,7 @@ use sys_common::{AsInner, IntoInner, FromInner};
 /// [`new`]: #method.new
 /// [`push`]: #method.push
 /// [`as_os_str`]: #method.as_os_str
+/// [conversions]: index.html#conversions
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct OsString {
@@ -89,7 +90,7 @@ pub struct OsString {
 /// 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.
+/// the traits which `OsStr` implements for [conversions] from/to native representations.
 ///
 /// [`OsString`]: struct.OsString.html
 /// [`&str`]: ../primitive.str.html
@@ -295,6 +296,36 @@ impl OsString {
         self.inner.shrink_to_fit()
     }
 
+    /// Shrinks the capacity of the `OsString` with a lower bound.
+    ///
+    /// The capacity will remain at least as large as both the length
+    /// and the supplied value.
+    ///
+    /// Panics if the current capacity is smaller than the supplied
+    /// minimum capacity.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(shrink_to)]
+    /// use std::ffi::OsString;
+    ///
+    /// let mut s = OsString::from("foo");
+    ///
+    /// s.reserve(100);
+    /// assert!(s.capacity() >= 100);
+    ///
+    /// s.shrink_to(10);
+    /// assert!(s.capacity() >= 10);
+    /// s.shrink_to(0);
+    /// assert!(s.capacity() >= 3);
+    /// ```
+    #[inline]
+    #[unstable(feature = "shrink_to", reason = "new API", issue="0")]
+    pub fn shrink_to(&mut self, min_capacity: usize) {
+        self.inner.shrink_to(min_capacity)
+    }
+
     /// Converts this `OsString` into a boxed [`OsStr`].
     ///
     /// [`OsStr`]: struct.OsStr.html
@@ -317,6 +348,12 @@ impl OsString {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl From<String> for OsString {
+    /// Converts a [`String`] into a [`OsString`].
+    ///
+    /// The conversion copies the data, and includes an allocation on the heap.
+    ///
+    /// [`String`]: ../string/struct.String.html
+    /// [`OsString`]: struct.OsString.html
     fn from(s: String) -> OsString {
         OsString { inner: Buf::from_string(s) }
     }
@@ -386,6 +423,20 @@ impl PartialEq<OsString> for str {
     }
 }
 
+#[stable(feature = "os_str_str_ref_eq", since = "1.28.0")]
+impl<'a> PartialEq<&'a str> for OsString {
+    fn eq(&self, other: &&'a str) -> bool {
+        **self == **other
+    }
+}
+
+#[stable(feature = "os_str_str_ref_eq", since = "1.28.0")]
+impl<'a> PartialEq<OsString> for &'a str {
+    fn eq(&self, other: &OsString) -> bool {
+        **other == **self
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Eq for OsString {}
 
@@ -469,10 +520,12 @@ impl OsStr {
 
     /// Converts an `OsStr` to a [`Cow`]`<`[`str`]`>`.
     ///
-    /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
+    /// Any non-Unicode sequences are replaced with
+    /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
     ///
     /// [`Cow`]: ../../std/borrow/enum.Cow.html
     /// [`str`]: ../../std/primitive.str.html
+    /// [U+FFFD]: ../../std/char/constant.REPLACEMENT_CHARACTER.html
     ///
     /// # Examples
     ///
@@ -585,6 +638,10 @@ impl<'a> From<&'a OsStr> for Box<OsStr> {
 
 #[stable(feature = "os_string_from_box", since = "1.18.0")]
 impl From<Box<OsStr>> for OsString {
+    /// Converts a `Box<OsStr>` into a `OsString` without copying or allocating.
+    ///
+    /// [`Box`]: ../boxed/struct.Box.html
+    /// [`OsString`]: ../ffi/struct.OsString.html
     fn from(boxed: Box<OsStr>) -> OsString {
         boxed.into_os_string()
     }
@@ -592,13 +649,29 @@ impl From<Box<OsStr>> for OsString {
 
 #[stable(feature = "box_from_os_string", since = "1.20.0")]
 impl From<OsString> for Box<OsStr> {
+    /// Converts a [`OsString`] into a [`Box`]`<OsStr>` without copying or allocating.
+    ///
+    /// [`Box`]: ../boxed/struct.Box.html
+    /// [`OsString`]: ../ffi/struct.OsString.html
     fn from(s: OsString) -> Box<OsStr> {
         s.into_boxed_os_str()
     }
 }
 
+#[stable(feature = "more_box_slice_clone", since = "1.29.0")]
+impl Clone for Box<OsStr> {
+    #[inline]
+    fn clone(&self) -> Self {
+        self.to_os_string().into_boxed_os_str()
+    }
+}
+
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<OsString> for Arc<OsStr> {
+    /// Converts a [`OsString`] into a [`Arc`]`<OsStr>` without copying or allocating.
+    ///
+    /// [`Arc`]: ../sync/struct.Arc.html
+    /// [`OsString`]: ../ffi/struct.OsString.html
     #[inline]
     fn from(s: OsString) -> Arc<OsStr> {
         let arc = s.inner.into_arc();
@@ -617,6 +690,10 @@ impl<'a> From<&'a OsStr> for Arc<OsStr> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<OsString> for Rc<OsStr> {
+    /// Converts a [`OsString`] into a [`Rc`]`<OsStr>` without copying or allocating.
+    ///
+    /// [`Rc`]: ../rc/struct.Rc.html
+    /// [`OsString`]: ../ffi/struct.OsString.html
     #[inline]
     fn from(s: OsString) -> Rc<OsStr> {
         let rc = s.inner.into_rc();
@@ -633,6 +710,38 @@ impl<'a> From<&'a OsStr> for Rc<OsStr> {
     }
 }
 
+#[stable(feature = "cow_from_osstr", since = "1.28.0")]
+impl<'a> From<OsString> for Cow<'a, OsStr> {
+    #[inline]
+    fn from(s: OsString) -> Cow<'a, OsStr> {
+        Cow::Owned(s)
+    }
+}
+
+#[stable(feature = "cow_from_osstr", since = "1.28.0")]
+impl<'a> From<&'a OsStr> for Cow<'a, OsStr> {
+    #[inline]
+    fn from(s: &'a OsStr) -> Cow<'a, OsStr> {
+        Cow::Borrowed(s)
+    }
+}
+
+#[stable(feature = "cow_from_osstr", since = "1.28.0")]
+impl<'a> From<&'a OsString> for Cow<'a, OsStr> {
+    #[inline]
+    fn from(s: &'a OsString) -> Cow<'a, OsStr> {
+        Cow::Borrowed(s.as_os_str())
+    }
+}
+
+#[stable(feature = "osstring_from_cow_osstr", since = "1.28.0")]
+impl<'a> From<Cow<'a, OsStr>> for OsString {
+    #[inline]
+    fn from(s: Cow<'a, OsStr>) -> Self {
+        s.into_owned()
+    }
+}
+
 #[stable(feature = "box_default_extra", since = "1.17.0")]
 impl Default for Box<OsStr> {
     fn default() -> Box<OsStr> {
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index 4e0ff450cab..7632fbc41f5 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -41,11 +41,11 @@ use time::SystemTime;
 /// use std::fs::File;
 /// use std::io::prelude::*;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// let mut file = File::create("foo.txt")?;
-/// file.write_all(b"Hello, world!")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     let mut file = File::create("foo.txt")?;
+///     file.write_all(b"Hello, world!")?;
+///     Ok(())
+/// }
 /// ```
 ///
 /// Read the contents of a file into a [`String`]:
@@ -54,13 +54,13 @@ use time::SystemTime;
 /// use std::fs::File;
 /// use std::io::prelude::*;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// let mut file = File::open("foo.txt")?;
-/// let mut contents = String::new();
-/// file.read_to_string(&mut contents)?;
-/// assert_eq!(contents, "Hello, world!");
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     let mut file = File::open("foo.txt")?;
+///     let mut contents = String::new();
+///     file.read_to_string(&mut contents)?;
+///     assert_eq!(contents, "Hello, world!");
+///     Ok(())
+/// }
 /// ```
 ///
 /// It can be more efficient to read the contents of a file with a buffered
@@ -71,19 +71,28 @@ use time::SystemTime;
 /// use std::io::BufReader;
 /// use std::io::prelude::*;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// let file = File::open("foo.txt")?;
-/// let mut buf_reader = BufReader::new(file);
-/// let mut contents = String::new();
-/// buf_reader.read_to_string(&mut contents)?;
-/// assert_eq!(contents, "Hello, world!");
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     let file = File::open("foo.txt")?;
+///     let mut buf_reader = BufReader::new(file);
+///     let mut contents = String::new();
+///     buf_reader.read_to_string(&mut contents)?;
+///     assert_eq!(contents, "Hello, world!");
+///     Ok(())
+/// }
 /// ```
 ///
+/// Note that, although read and write methods require a `&mut File`, because
+/// of the interfaces for [`Read`] and [`Write`], the holder of a `&File` can
+/// still modify the file, either through methods that take `&File` or by
+/// retrieving the underlying OS object and modifying the file that way.
+/// Additionally, many operating systems allow concurrent modification of files
+/// by different processes. Avoid assuming that holding a `&File` means that the
+/// file will not change.
+///
 /// [`Seek`]: ../io/trait.Seek.html
 /// [`String`]: ../string/struct.String.html
 /// [`Read`]: ../io/trait.Read.html
+/// [`Write`]: ../io/trait.Write.html
 /// [`BufReader<R>`]: ../io/struct.BufReader.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct File {
@@ -211,18 +220,20 @@ pub struct DirBuilder {
     recursive: bool,
 }
 
-/// How large a buffer to pre-allocate before reading the entire file at `path`.
-fn initial_buffer_size<P: AsRef<Path>>(path: P) -> usize {
+/// How large a buffer to pre-allocate before reading the entire file.
+fn initial_buffer_size(file: &File) -> usize {
     // Allocate one extra byte so the buffer doesn't need to grow before the
     // final `read` call at the end of the file.  Don't worry about `usize`
     // overflow because reading will fail regardless in that case.
-    metadata(path).map(|m| m.len() as usize + 1).unwrap_or(0)
+    file.metadata().map(|m| m.len() as usize + 1).unwrap_or(0)
 }
 
 /// Read the entire contents of a file into a bytes vector.
 ///
 /// This is a convenience function for using [`File::open`] and [`read_to_end`]
-/// with fewer imports and without an intermediate variable.
+/// with fewer imports and without an intermediate variable.  It pre-allocates a
+/// buffer based on the file size when available, so it is generally faster than
+/// reading into a vector created with `Vec::new()`.
 ///
 /// [`File::open`]: struct.File.html#method.open
 /// [`read_to_end`]: ../io/trait.Read.html#method.read_to_end
@@ -242,27 +253,28 @@ fn initial_buffer_size<P: AsRef<Path>>(path: P) -> usize {
 /// # Examples
 ///
 /// ```no_run
-/// #![feature(fs_read_write)]
-///
 /// use std::fs;
 /// use std::net::SocketAddr;
 ///
-/// # fn foo() -> Result<(), Box<std::error::Error + 'static>> {
-/// let foo: SocketAddr = String::from_utf8_lossy(&fs::read("address.txt")?).parse()?;
-/// # Ok(())
-/// # }
+/// fn main() -> Result<(), Box<std::error::Error + 'static>> {
+///     let foo: SocketAddr = String::from_utf8_lossy(&fs::read("address.txt")?).parse()?;
+///     Ok(())
+/// }
 /// ```
-#[unstable(feature = "fs_read_write", issue = "46588")]
+#[stable(feature = "fs_read_write_bytes", since = "1.26.0")]
 pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
-    let mut bytes = Vec::with_capacity(initial_buffer_size(&path));
-    File::open(path)?.read_to_end(&mut bytes)?;
+    let mut file = File::open(path)?;
+    let mut bytes = Vec::with_capacity(initial_buffer_size(&file));
+    file.read_to_end(&mut bytes)?;
     Ok(bytes)
 }
 
 /// Read the entire contents of a file into a string.
 ///
 /// This is a convenience function for using [`File::open`] and [`read_to_string`]
-/// with fewer imports and without an intermediate variable.
+/// with fewer imports and without an intermediate variable.  It pre-allocates a
+/// buffer based on the file size when available, so it is generally faster than
+/// reading into a string created with `String::new()`.
 ///
 /// [`File::open`]: struct.File.html#method.open
 /// [`read_to_string`]: ../io/trait.Read.html#method.read_to_string
@@ -283,20 +295,19 @@ pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
 /// # Examples
 ///
 /// ```no_run
-/// #![feature(fs_read_write)]
-///
 /// use std::fs;
 /// use std::net::SocketAddr;
 ///
-/// # fn foo() -> Result<(), Box<std::error::Error + 'static>> {
-/// let foo: SocketAddr = fs::read_string("address.txt")?.parse()?;
-/// # Ok(())
-/// # }
+/// fn main() -> Result<(), Box<std::error::Error + 'static>> {
+///     let foo: SocketAddr = fs::read_to_string("address.txt")?.parse()?;
+///     Ok(())
+/// }
 /// ```
-#[unstable(feature = "fs_read_write", issue = "46588")]
-pub fn read_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
-    let mut string = String::with_capacity(initial_buffer_size(&path));
-    File::open(path)?.read_to_string(&mut string)?;
+#[stable(feature = "fs_read_write", since = "1.26.0")]
+pub fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
+    let mut file = File::open(path)?;
+    let mut string = String::with_capacity(initial_buffer_size(&file));
+    file.read_to_string(&mut string)?;
     Ok(string)
 }
 
@@ -314,16 +325,15 @@ pub fn read_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
 /// # Examples
 ///
 /// ```no_run
-/// #![feature(fs_read_write)]
-///
 /// use std::fs;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::write("foo.txt", b"Lorem ipsum")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     fs::write("foo.txt", b"Lorem ipsum")?;
+///     fs::write("bar.txt", "dolor sit")?;
+///     Ok(())
+/// }
 /// ```
-#[unstable(feature = "fs_read_write", issue = "46588")]
+#[stable(feature = "fs_read_write_bytes", since = "1.26.0")]
 pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> {
     File::create(path)?.write_all(contents.as_ref())
 }
@@ -345,10 +355,10 @@ impl File {
     /// ```no_run
     /// use std::fs::File;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let mut f = File::open("foo.txt")?;
-    /// # Ok(())
-    /// # }
+    /// fn main() -> std::io::Result<()> {
+    ///     let mut f = File::open("foo.txt")?;
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {
@@ -369,10 +379,10 @@ impl File {
     /// ```no_run
     /// use std::fs::File;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let mut f = File::create("foo.txt")?;
-    /// # Ok(())
-    /// # }
+    /// fn main() -> std::io::Result<()> {
+    ///     let mut f = File::create("foo.txt")?;
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn create<P: AsRef<Path>>(path: P) -> io::Result<File> {
@@ -390,13 +400,13 @@ impl File {
     /// use std::fs::File;
     /// use std::io::prelude::*;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let mut f = File::create("foo.txt")?;
-    /// f.write_all(b"Hello, world!")?;
+    /// fn main() -> std::io::Result<()> {
+    ///     let mut f = File::create("foo.txt")?;
+    ///     f.write_all(b"Hello, world!")?;
     ///
-    /// f.sync_all()?;
-    /// # Ok(())
-    /// # }
+    ///     f.sync_all()?;
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn sync_all(&self) -> io::Result<()> {
@@ -421,13 +431,13 @@ impl File {
     /// use std::fs::File;
     /// use std::io::prelude::*;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let mut f = File::create("foo.txt")?;
-    /// f.write_all(b"Hello, world!")?;
+    /// fn main() -> std::io::Result<()> {
+    ///     let mut f = File::create("foo.txt")?;
+    ///     f.write_all(b"Hello, world!")?;
     ///
-    /// f.sync_data()?;
-    /// # Ok(())
-    /// # }
+    ///     f.sync_data()?;
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn sync_data(&self) -> io::Result<()> {
@@ -442,6 +452,10 @@ impl File {
     /// will be extended to `size` and have all of the intermediate data filled
     /// in with 0s.
     ///
+    /// The file's cursor isn't changed. In particular, if the cursor was at the
+    /// end and the file is shrunk using this operation, the cursor will now be
+    /// past the end.
+    ///
     /// # Errors
     ///
     /// This function will return an error if the file is not opened for writing.
@@ -451,12 +465,15 @@ impl File {
     /// ```no_run
     /// use std::fs::File;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let mut f = File::create("foo.txt")?;
-    /// f.set_len(10)?;
-    /// # Ok(())
-    /// # }
+    /// fn main() -> std::io::Result<()> {
+    ///     let mut f = File::create("foo.txt")?;
+    ///     f.set_len(10)?;
+    ///     Ok(())
+    /// }
     /// ```
+    ///
+    /// Note that this method alters the content of the underlying file, even
+    /// though it takes `&self` rather than `&mut self`.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn set_len(&self, size: u64) -> io::Result<()> {
         self.inner.truncate(size)
@@ -469,33 +486,55 @@ impl File {
     /// ```no_run
     /// use std::fs::File;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let mut f = File::open("foo.txt")?;
-    /// let metadata = f.metadata()?;
-    /// # Ok(())
-    /// # }
+    /// fn main() -> std::io::Result<()> {
+    ///     let mut f = File::open("foo.txt")?;
+    ///     let metadata = f.metadata()?;
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn metadata(&self) -> io::Result<Metadata> {
         self.inner.file_attr().map(Metadata)
     }
 
-    /// Creates a new independently owned handle to the underlying file.
-    ///
-    /// The returned `File` is a reference to the same state that this object
-    /// references. Both handles will read and write with the same cursor
-    /// position.
+    /// Create a new `File` instance that shares the same underlying file handle
+    /// as the existing `File` instance. Reads, writes, and seeks will affect
+    /// both `File` instances simultaneously.
     ///
     /// # Examples
     ///
+    /// Create two handles for a file named `foo.txt`:
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let mut file = File::open("foo.txt")?;
+    ///     let file_copy = file.try_clone()?;
+    ///     Ok(())
+    /// }
+    /// ```
+    ///
+    /// Assuming there’s a file named `foo.txt` with contents `abcdef\n`, create
+    /// two handles, seek one of them, and read the remaining bytes from the
+    /// other handle:
+    ///
     /// ```no_run
     /// use std::fs::File;
+    /// use std::io::SeekFrom;
+    /// use std::io::prelude::*;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let mut file = File::open("foo.txt")?;
+    ///     let mut file_copy = file.try_clone()?;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let mut f = File::open("foo.txt")?;
-    /// let file_copy = f.try_clone()?;
-    /// # Ok(())
-    /// # }
+    ///     file.seek(SeekFrom::Start(3))?;
+    ///
+    ///     let mut contents = vec![];
+    ///     file_copy.read_to_end(&mut contents)?;
+    ///     assert_eq!(contents, b"def\n");
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "file_try_clone", since = "1.9.0")]
     pub fn try_clone(&self) -> io::Result<File> {
@@ -522,17 +561,20 @@ impl File {
     ///
     /// # Examples
     ///
+    /// ```no_run
+    /// fn main() -> std::io::Result<()> {
+    ///     use std::fs::File;
+    ///
+    ///     let file = File::open("foo.txt")?;
+    ///     let mut perms = file.metadata()?.permissions();
+    ///     perms.set_readonly(true);
+    ///     file.set_permissions(perms)?;
+    ///     Ok(())
+    /// }
     /// ```
-    /// # fn foo() -> std::io::Result<()> {
-    /// use std::fs::File;
     ///
-    /// let file = File::open("foo.txt")?;
-    /// let mut perms = file.metadata()?.permissions();
-    /// perms.set_readonly(true);
-    /// file.set_permissions(perms)?;
-    /// # Ok(())
-    /// # }
-    /// ```
+    /// Note that this method alters the permissions of the underlying file,
+    /// even though it takes `&self` rather than `&mut self`.
     #[stable(feature = "set_permissions_atomic", since = "1.16.0")]
     pub fn set_permissions(&self, perm: Permissions) -> io::Result<()> {
         self.inner.set_permissions(perm.0)
@@ -848,51 +890,63 @@ impl Metadata {
     ///
     /// # Examples
     ///
-    /// ```
-    /// # fn foo() -> std::io::Result<()> {
-    /// use std::fs;
+    /// ```no_run
+    /// fn main() -> std::io::Result<()> {
+    ///     use std::fs;
     ///
-    /// let metadata = fs::metadata("foo.txt")?;
+    ///     let metadata = fs::metadata("foo.txt")?;
     ///
-    /// println!("{:?}", metadata.file_type());
-    /// # Ok(())
-    /// # }
+    ///     println!("{:?}", metadata.file_type());
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "file_type", since = "1.1.0")]
     pub fn file_type(&self) -> FileType {
         FileType(self.0.file_type())
     }
 
-    /// Returns whether this metadata is for a directory.
+    /// Returns whether this metadata is for a directory. The
+    /// result is mutually exclusive to the result of
+    /// [`is_file`], and will be false for symlink metadata
+    /// obtained from [`symlink_metadata`].
+    ///
+    /// [`is_file`]: struct.Metadata.html#method.is_file
+    /// [`symlink_metadata`]: fn.symlink_metadata.html
     ///
     /// # Examples
     ///
-    /// ```
-    /// # fn foo() -> std::io::Result<()> {
-    /// use std::fs;
+    /// ```no_run
+    /// fn main() -> std::io::Result<()> {
+    ///     use std::fs;
     ///
-    /// let metadata = fs::metadata("foo.txt")?;
+    ///     let metadata = fs::metadata("foo.txt")?;
     ///
-    /// assert!(!metadata.is_dir());
-    /// # Ok(())
-    /// # }
+    ///     assert!(!metadata.is_dir());
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_dir(&self) -> bool { self.file_type().is_dir() }
 
-    /// Returns whether this metadata is for a regular file.
+    /// Returns whether this metadata is for a regular file. The
+    /// result is mutually exclusive to the result of
+    /// [`is_dir`], and will be false for symlink metadata
+    /// obtained from [`symlink_metadata`].
+    ///
+    /// [`is_dir`]: struct.Metadata.html#method.is_dir
+    /// [`symlink_metadata`]: fn.symlink_metadata.html
     ///
     /// # Examples
     ///
-    /// ```
-    /// # fn foo() -> std::io::Result<()> {
+    /// ```no_run
     /// use std::fs;
     ///
-    /// let metadata = fs::metadata("foo.txt")?;
+    /// fn main() -> std::io::Result<()> {
+    ///     let metadata = fs::metadata("foo.txt")?;
     ///
-    /// assert!(metadata.is_file());
-    /// # Ok(())
-    /// # }
+    ///     assert!(metadata.is_file());
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_file(&self) -> bool { self.file_type().is_file() }
@@ -901,15 +955,15 @@ impl Metadata {
     ///
     /// # Examples
     ///
-    /// ```
-    /// # fn foo() -> std::io::Result<()> {
+    /// ```no_run
     /// use std::fs;
     ///
-    /// let metadata = fs::metadata("foo.txt")?;
+    /// fn main() -> std::io::Result<()> {
+    ///     let metadata = fs::metadata("foo.txt")?;
     ///
-    /// assert_eq!(0, metadata.len());
-    /// # Ok(())
-    /// # }
+    ///     assert_eq!(0, metadata.len());
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> u64 { self.0.size() }
@@ -918,15 +972,15 @@ impl Metadata {
     ///
     /// # Examples
     ///
-    /// ```
-    /// # fn foo() -> std::io::Result<()> {
+    /// ```no_run
     /// use std::fs;
     ///
-    /// let metadata = fs::metadata("foo.txt")?;
+    /// fn main() -> std::io::Result<()> {
+    ///     let metadata = fs::metadata("foo.txt")?;
     ///
-    /// assert!(!metadata.permissions().readonly());
-    /// # Ok(())
-    /// # }
+    ///     assert!(!metadata.permissions().readonly());
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn permissions(&self) -> Permissions {
@@ -945,19 +999,19 @@ impl Metadata {
     ///
     /// # Examples
     ///
-    /// ```
-    /// # fn foo() -> std::io::Result<()> {
+    /// ```no_run
     /// use std::fs;
     ///
-    /// let metadata = fs::metadata("foo.txt")?;
+    /// fn main() -> std::io::Result<()> {
+    ///     let metadata = fs::metadata("foo.txt")?;
     ///
-    /// if let Ok(time) = metadata.modified() {
-    ///     println!("{:?}", time);
-    /// } else {
-    ///     println!("Not supported on this platform");
+    ///     if let Ok(time) = metadata.modified() {
+    ///         println!("{:?}", time);
+    ///     } else {
+    ///         println!("Not supported on this platform");
+    ///     }
+    ///     Ok(())
     /// }
-    /// # Ok(())
-    /// # }
     /// ```
     #[stable(feature = "fs_time", since = "1.10.0")]
     pub fn modified(&self) -> io::Result<SystemTime> {
@@ -980,26 +1034,26 @@ impl Metadata {
     ///
     /// # Examples
     ///
-    /// ```
-    /// # fn foo() -> std::io::Result<()> {
+    /// ```no_run
     /// use std::fs;
     ///
-    /// let metadata = fs::metadata("foo.txt")?;
+    /// fn main() -> std::io::Result<()> {
+    ///     let metadata = fs::metadata("foo.txt")?;
     ///
-    /// if let Ok(time) = metadata.accessed() {
-    ///     println!("{:?}", time);
-    /// } else {
-    ///     println!("Not supported on this platform");
+    ///     if let Ok(time) = metadata.accessed() {
+    ///         println!("{:?}", time);
+    ///     } else {
+    ///         println!("Not supported on this platform");
+    ///     }
+    ///     Ok(())
     /// }
-    /// # Ok(())
-    /// # }
     /// ```
     #[stable(feature = "fs_time", since = "1.10.0")]
     pub fn accessed(&self) -> io::Result<SystemTime> {
         self.0.accessed().map(FromInner::from_inner)
     }
 
-    /// Returns the creation time listed in the this metadata.
+    /// Returns the creation time listed in this metadata.
     ///
     /// The returned value corresponds to the `birthtime` field of `stat` on
     /// Unix platforms and the `ftCreationTime` field on Windows platforms.
@@ -1011,19 +1065,19 @@ impl Metadata {
     ///
     /// # Examples
     ///
-    /// ```
-    /// # fn foo() -> std::io::Result<()> {
+    /// ```no_run
     /// use std::fs;
     ///
-    /// let metadata = fs::metadata("foo.txt")?;
+    /// fn main() -> std::io::Result<()> {
+    ///     let metadata = fs::metadata("foo.txt")?;
     ///
-    /// if let Ok(time) = metadata.created() {
-    ///     println!("{:?}", time);
-    /// } else {
-    ///     println!("Not supported on this platform");
+    ///     if let Ok(time) = metadata.created() {
+    ///         println!("{:?}", time);
+    ///     } else {
+    ///         println!("Not supported on this platform");
+    ///     }
+    ///     Ok(())
     /// }
-    /// # Ok(())
-    /// # }
     /// ```
     #[stable(feature = "fs_time", since = "1.10.0")]
     pub fn created(&self) -> io::Result<SystemTime> {
@@ -1055,16 +1109,16 @@ impl Permissions {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs::File;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let mut f = File::create("foo.txt")?;
-    /// let metadata = f.metadata()?;
+    /// fn main() -> std::io::Result<()> {
+    ///     let mut f = File::create("foo.txt")?;
+    ///     let metadata = f.metadata()?;
     ///
-    /// assert_eq!(false, metadata.permissions().readonly());
-    /// # Ok(())
-    /// # }
+    ///     assert_eq!(false, metadata.permissions().readonly());
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn readonly(&self) -> bool { self.0.readonly() }
@@ -1080,23 +1134,23 @@ impl Permissions {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs::File;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let f = File::create("foo.txt")?;
-    /// let metadata = f.metadata()?;
-    /// let mut permissions = metadata.permissions();
+    /// fn main() -> std::io::Result<()> {
+    ///     let f = File::create("foo.txt")?;
+    ///     let metadata = f.metadata()?;
+    ///     let mut permissions = metadata.permissions();
     ///
-    /// permissions.set_readonly(true);
+    ///     permissions.set_readonly(true);
     ///
-    /// // filesystem doesn't change
-    /// assert_eq!(false, metadata.permissions().readonly());
+    ///     // filesystem doesn't change
+    ///     assert_eq!(false, metadata.permissions().readonly());
     ///
-    /// // just this particular `permissions`.
-    /// assert_eq!(true, permissions.readonly());
-    /// # Ok(())
-    /// # }
+    ///     // just this particular `permissions`.
+    ///     assert_eq!(true, permissions.readonly());
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn set_readonly(&mut self, readonly: bool) {
@@ -1105,43 +1159,58 @@ impl Permissions {
 }
 
 impl FileType {
-    /// Test whether this file type represents a directory.
+    /// Test whether this file type represents a directory. The
+    /// result is mutually exclusive to the results of
+    /// [`is_file`] and [`is_symlink`]; only zero or one of these
+    /// tests may pass.
+    ///
+    /// [`is_file`]: struct.FileType.html#method.is_file
+    /// [`is_symlink`]: struct.FileType.html#method.is_symlink
     ///
     /// # Examples
     ///
-    /// ```
-    /// # fn foo() -> std::io::Result<()> {
-    /// use std::fs;
+    /// ```no_run
+    /// fn main() -> std::io::Result<()> {
+    ///     use std::fs;
     ///
-    /// let metadata = fs::metadata("foo.txt")?;
-    /// let file_type = metadata.file_type();
+    ///     let metadata = fs::metadata("foo.txt")?;
+    ///     let file_type = metadata.file_type();
     ///
-    /// assert_eq!(file_type.is_dir(), false);
-    /// # Ok(())
-    /// # }
+    ///     assert_eq!(file_type.is_dir(), false);
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "file_type", since = "1.1.0")]
     pub fn is_dir(&self) -> bool { self.0.is_dir() }
 
     /// Test whether this file type represents a regular file.
+    /// The result is  mutually exclusive to the results of
+    /// [`is_dir`] and [`is_symlink`]; only zero or one of these
+    /// tests may pass.
+    ///
+    /// [`is_dir`]: struct.FileType.html#method.is_dir
+    /// [`is_symlink`]: struct.FileType.html#method.is_symlink
     ///
     /// # Examples
     ///
-    /// ```
-    /// # fn foo() -> std::io::Result<()> {
-    /// use std::fs;
+    /// ```no_run
+    /// fn main() -> std::io::Result<()> {
+    ///     use std::fs;
     ///
-    /// let metadata = fs::metadata("foo.txt")?;
-    /// let file_type = metadata.file_type();
+    ///     let metadata = fs::metadata("foo.txt")?;
+    ///     let file_type = metadata.file_type();
     ///
-    /// assert_eq!(file_type.is_file(), true);
-    /// # Ok(())
-    /// # }
+    ///     assert_eq!(file_type.is_file(), true);
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "file_type", since = "1.1.0")]
     pub fn is_file(&self) -> bool { self.0.is_file() }
 
     /// Test whether this file type represents a symbolic link.
+    /// The result is mutually exclusive to the results of
+    /// [`is_dir`] and [`is_file`]; only zero or one of these
+    /// tests may pass.
     ///
     /// The underlying [`Metadata`] struct needs to be retrieved
     /// with the [`fs::symlink_metadata`] function and not the
@@ -1152,20 +1221,22 @@ impl FileType {
     /// [`Metadata`]: struct.Metadata.html
     /// [`fs::metadata`]: fn.metadata.html
     /// [`fs::symlink_metadata`]: fn.symlink_metadata.html
+    /// [`is_dir`]: struct.FileType.html#method.is_dir
+    /// [`is_file`]: struct.FileType.html#method.is_file
     /// [`is_symlink`]: struct.FileType.html#method.is_symlink
     ///
     /// # Examples
     ///
-    /// ```
-    /// # fn foo() -> std::io::Result<()> {
+    /// ```no_run
     /// use std::fs;
     ///
-    /// let metadata = fs::symlink_metadata("foo.txt")?;
-    /// let file_type = metadata.file_type();
+    /// fn main() -> std::io::Result<()> {
+    ///     let metadata = fs::symlink_metadata("foo.txt")?;
+    ///     let file_type = metadata.file_type();
     ///
-    /// assert_eq!(file_type.is_symlink(), false);
-    /// # Ok(())
-    /// # }
+    ///     assert_eq!(file_type.is_symlink(), false);
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "file_type", since = "1.1.0")]
     pub fn is_symlink(&self) -> bool { self.0.is_symlink() }
@@ -1202,15 +1273,16 @@ impl DirEntry {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
-    /// # fn foo() -> std::io::Result<()> {
-    /// for entry in fs::read_dir(".")? {
-    ///     let dir = entry?;
-    ///     println!("{:?}", dir.path());
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     for entry in fs::read_dir(".")? {
+    ///         let dir = entry?;
+    ///         println!("{:?}", dir.path());
+    ///     }
+    ///     Ok(())
     /// }
-    /// # Ok(())
-    /// # }
     /// ```
     ///
     /// This prints output like:
@@ -1355,13 +1427,13 @@ impl AsInner<fs_imp::DirEntry> for DirEntry {
 ///
 /// # Examples
 ///
-/// ```
+/// ```no_run
 /// use std::fs;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::remove_file("a.txt")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     fs::remove_file("a.txt")?;
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
@@ -1392,14 +1464,14 @@ pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
 ///
 /// # Examples
 ///
-/// ```rust
-/// # fn foo() -> std::io::Result<()> {
+/// ```rust,no_run
 /// use std::fs;
 ///
-/// let attr = fs::metadata("/some/file/path.txt")?;
-/// // inspect attr ...
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     let attr = fs::metadata("/some/file/path.txt")?;
+///     // inspect attr ...
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
@@ -1426,14 +1498,14 @@ pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
 ///
 /// # Examples
 ///
-/// ```rust
-/// # fn foo() -> std::io::Result<()> {
+/// ```rust,no_run
 /// use std::fs;
 ///
-/// let attr = fs::symlink_metadata("/some/file/path.txt")?;
-/// // inspect attr ...
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     let attr = fs::symlink_metadata("/some/file/path.txt")?;
+///     // inspect attr ...
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "symlink_metadata", since = "1.1.0")]
 pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
@@ -1470,13 +1542,13 @@ pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
 ///
 /// # Examples
 ///
-/// ```
+/// ```no_run
 /// use std::fs;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::rename("a.txt", "b.txt")?; // Rename a.txt to b.txt
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     fs::rename("a.txt", "b.txt")?; // Rename a.txt to b.txt
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {
@@ -1521,9 +1593,10 @@ pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()>
 /// ```no_run
 /// use std::fs;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::copy("foo.txt", "bar.txt")?;  // Copy foo.txt to bar.txt
-/// # Ok(()) }
+/// fn main() -> std::io::Result<()> {
+///     fs::copy("foo.txt", "bar.txt")?;  // Copy foo.txt to bar.txt
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> {
@@ -1552,13 +1625,13 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> {
 ///
 /// # Examples
 ///
-/// ```
+/// ```no_run
 /// use std::fs;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::hard_link("a.txt", "b.txt")?; // Hard link a.txt to b.txt
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     fs::hard_link("a.txt", "b.txt")?; // Hard link a.txt to b.txt
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
@@ -1575,13 +1648,13 @@ pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<(
 ///
 /// # Examples
 ///
-/// ```
+/// ```no_run
 /// use std::fs;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::soft_link("a.txt", "b.txt")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     fs::soft_link("a.txt", "b.txt")?;
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_deprecated(since = "1.1.0",
@@ -1612,21 +1685,21 @@ pub fn soft_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<(
 ///
 /// # Examples
 ///
-/// ```
+/// ```no_run
 /// use std::fs;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// let path = fs::read_link("a.txt")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     let path = fs::read_link("a.txt")?;
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
     fs_imp::readlink(path.as_ref())
 }
 
-/// Returns the canonical form of a path with all intermediate components
-/// normalized and symbolic links resolved.
+/// Returns the canonical, absolute form of a path with all intermediate
+/// components normalized and symbolic links resolved.
 ///
 /// # Platform-specific behavior
 ///
@@ -1634,7 +1707,14 @@ pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
 /// and the `CreateFile` and `GetFinalPathNameByHandle` functions on Windows.
 /// Note that, this [may change in the future][changes].
 ///
+/// On Windows, this converts the path to use [extended length path][path]
+/// syntax, which allows your program to use longer path names, but means you
+/// can only join backslash-delimited paths to it, and it may be incompatible
+/// with other applications (if passed to the application on the command-line,
+/// or written to a file another application may read).
+///
 /// [changes]: ../io/index.html#platform-specific-behavior
+/// [path]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath
 ///
 /// # Errors
 ///
@@ -1646,13 +1726,13 @@ pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
 ///
 /// # Examples
 ///
-/// ```
+/// ```no_run
 /// use std::fs;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// let path = fs::canonicalize("../a/../foo.txt")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     let path = fs::canonicalize("../a/../foo.txt")?;
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "fs_canonicalize", since = "1.5.0")]
 pub fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
@@ -1679,13 +1759,13 @@ pub fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
 ///
 /// # Examples
 ///
-/// ```
+/// ```no_run
 /// use std::fs;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::create_dir("/some/dir")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     fs::create_dir("/some/dir")?;
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
@@ -1721,13 +1801,13 @@ pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
 ///
 /// # Examples
 ///
-/// ```
+/// ```no_run
 /// use std::fs;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::create_dir_all("/some/dir")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     fs::create_dir_all("/some/dir")?;
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
@@ -1754,13 +1834,13 @@ pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
 ///
 /// # Examples
 ///
-/// ```
+/// ```no_run
 /// use std::fs;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::remove_dir("/some/dir")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     fs::remove_dir("/some/dir")?;
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
@@ -1788,13 +1868,13 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
 ///
 /// # Examples
 ///
-/// ```
+/// ```no_run
 /// use std::fs;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::remove_dir_all("/some/dir")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     fs::remove_dir_all("/some/dir")?;
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
@@ -1874,15 +1954,15 @@ pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> {
 ///
 /// # Examples
 ///
-/// ```
-/// # fn foo() -> std::io::Result<()> {
+/// ```no_run
 /// use std::fs;
 ///
-/// let mut perms = fs::metadata("foo.txt")?.permissions();
-/// perms.set_readonly(true);
-/// fs::set_permissions("foo.txt", perms)?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     let mut perms = fs::metadata("foo.txt")?.permissions();
+///     perms.set_readonly(true);
+///     fs::set_permissions("foo.txt", perms)?;
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "set_permissions", since = "1.1.0")]
 pub fn set_permissions<P: AsRef<Path>>(path: P, perm: Permissions)
@@ -3052,12 +3132,12 @@ mod tests {
         assert!(v == &bytes[..]);
 
         check!(fs::write(&tmpdir.join("not-utf8"), &[0xFF]));
-        error_contains!(fs::read_string(&tmpdir.join("not-utf8")),
+        error_contains!(fs::read_to_string(&tmpdir.join("not-utf8")),
                         "stream did not contain valid UTF-8");
 
         let s = "𐁁𐀓𐀠𐀴𐀍";
         check!(fs::write(&tmpdir.join("utf8"), s.as_bytes()));
-        let string = check!(fs::read_string(&tmpdir.join("utf8")));
+        let string = check!(fs::read_to_string(&tmpdir.join("utf8")));
         assert_eq!(string, s);
     }
 
diff --git a/src/libstd/future.rs b/src/libstd/future.rs
new file mode 100644
index 00000000000..12ea1ea9f9d
--- /dev/null
+++ b/src/libstd/future.rs
@@ -0,0 +1,116 @@
+// Copyright 2018 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.
+
+//! Asynchronous values.
+
+use core::cell::Cell;
+use core::marker::Unpin;
+use core::mem::PinMut;
+use core::option::Option;
+use core::ptr::NonNull;
+use core::task::{self, Poll};
+use core::ops::{Drop, Generator, GeneratorState};
+
+#[doc(inline)]
+pub use core::future::*;
+
+/// Wrap a future in a generator.
+///
+/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
+/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
+#[unstable(feature = "gen_future", issue = "50547")]
+pub fn from_generator<T: Generator<Yield = ()>>(x: T) -> impl Future<Output = T::Return> {
+    GenFuture(x)
+}
+
+/// A wrapper around generators used to implement `Future` for `async`/`await` code.
+#[unstable(feature = "gen_future", issue = "50547")]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
+struct GenFuture<T: Generator<Yield = ()>>(T);
+
+// We rely on the fact that async/await futures are immovable in order to create
+// self-referential borrows in the underlying generator.
+impl<T: Generator<Yield = ()>> !Unpin for GenFuture<T> {}
+
+#[unstable(feature = "gen_future", issue = "50547")]
+impl<T: Generator<Yield = ()>> Future for GenFuture<T> {
+    type Output = T::Return;
+    fn poll(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
+        set_task_cx(cx, || match unsafe { PinMut::get_mut_unchecked(self).0.resume() } {
+            GeneratorState::Yielded(()) => Poll::Pending,
+            GeneratorState::Complete(x) => Poll::Ready(x),
+        })
+    }
+}
+
+thread_local! {
+    static TLS_CX: Cell<Option<NonNull<task::Context<'static>>>> = Cell::new(None);
+}
+
+struct SetOnDrop(Option<NonNull<task::Context<'static>>>);
+
+impl Drop for SetOnDrop {
+    fn drop(&mut self) {
+        TLS_CX.with(|tls_cx| {
+            tls_cx.set(self.0.take());
+        });
+    }
+}
+
+#[unstable(feature = "gen_future", issue = "50547")]
+/// Sets the thread-local task context used by async/await futures.
+pub fn set_task_cx<F, R>(cx: &mut task::Context, f: F) -> R
+where
+    F: FnOnce() -> R
+{
+    let old_cx = TLS_CX.with(|tls_cx| {
+        tls_cx.replace(NonNull::new(
+            cx
+                as *mut task::Context
+                as *mut ()
+                as *mut task::Context<'static>
+        ))
+    });
+    let _reset_cx = SetOnDrop(old_cx);
+    f()
+}
+
+#[unstable(feature = "gen_future", issue = "50547")]
+/// Retrieves the thread-local task context used by async/await futures.
+///
+/// This function acquires exclusive access to the task context.
+///
+/// Panics if no task has been set or if the task context has already been
+/// retrived by a surrounding call to get_task_cx.
+pub fn get_task_cx<F, R>(f: F) -> R
+where
+    F: FnOnce(&mut task::Context) -> R
+{
+    let cx_ptr = TLS_CX.with(|tls_cx| {
+        // Clear the entry so that nested `with_get_cx` calls
+        // will fail or set their own value.
+        tls_cx.replace(None)
+    });
+    let _reset_cx = SetOnDrop(cx_ptr);
+
+    let mut cx_ptr = cx_ptr.expect(
+        "TLS task::Context not set. This is a rustc bug. \
+        Please file an issue on https://github.com/rust-lang/rust.");
+    unsafe { f(cx_ptr.as_mut()) }
+}
+
+#[unstable(feature = "gen_future", issue = "50547")]
+/// Polls a future in the current thread-local task context.
+pub fn poll_in_task_cx<F>(f: PinMut<F>) -> Poll<F::Output>
+where
+    F: Future
+{
+    get_task_cx(|cx| f.poll(cx))
+}
diff --git a/src/libstd/heap.rs b/src/libstd/heap.rs
deleted file mode 100644
index 4d5e4df6f95..00000000000
--- a/src/libstd/heap.rs
+++ /dev/null
@@ -1,175 +0,0 @@
-// 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.
-
-//! dox
-
-#![unstable(issue = "32838", feature = "allocator_api")]
-
-pub use alloc::heap::{Heap, Alloc, Layout, Excess, CannotReallocInPlace, AllocErr};
-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;
-
-    // for symbol names src/librustc/middle/allocator.rs
-    // for signatures src/librustc_allocator/lib.rs
-
-    // linkage directives are provided as part of the current compiler allocator
-    // ABI
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rdl_alloc(size: usize,
-                                     align: usize,
-                                     err: *mut u8) -> *mut u8 {
-        let layout = Layout::from_size_align_unchecked(size, align);
-        match System.alloc(layout) {
-            Ok(p) => p,
-            Err(e) => {
-                ptr::write(err as *mut AllocErr, e);
-                0 as *mut u8
-            }
-        }
-    }
-
-    #[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) {
-        System.dealloc(ptr, Layout::from_size_align_unchecked(size, align))
-    }
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rdl_usable_size(layout: *const u8,
-                                           min: *mut usize,
-                                           max: *mut usize) {
-        let pair = System.usable_size(&*(layout as *const Layout));
-        *min = pair.0;
-        *max = pair.1;
-    }
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rdl_realloc(ptr: *mut u8,
-                                       old_size: usize,
-                                       old_align: usize,
-                                       new_size: usize,
-                                       new_align: usize,
-                                       err: *mut u8) -> *mut u8 {
-        let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
-        let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
-        match System.realloc(ptr, old_layout, new_layout) {
-            Ok(p) => p,
-            Err(e) => {
-                ptr::write(err as *mut AllocErr, e);
-                0 as *mut u8
-            }
-        }
-    }
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rdl_alloc_zeroed(size: usize,
-                                            align: usize,
-                                            err: *mut u8) -> *mut u8 {
-        let layout = Layout::from_size_align_unchecked(size, align);
-        match System.alloc_zeroed(layout) {
-            Ok(p) => p,
-            Err(e) => {
-                ptr::write(err as *mut AllocErr, e);
-                0 as *mut u8
-            }
-        }
-    }
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rdl_alloc_excess(size: usize,
-                                            align: usize,
-                                            excess: *mut usize,
-                                            err: *mut u8) -> *mut u8 {
-        let layout = Layout::from_size_align_unchecked(size, align);
-        match System.alloc_excess(layout) {
-            Ok(p) => {
-                *excess = p.1;
-                p.0
-            }
-            Err(e) => {
-                ptr::write(err as *mut AllocErr, e);
-                0 as *mut u8
-            }
-        }
-    }
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rdl_realloc_excess(ptr: *mut u8,
-                                              old_size: usize,
-                                              old_align: usize,
-                                              new_size: usize,
-                                              new_align: usize,
-                                              excess: *mut usize,
-                                              err: *mut u8) -> *mut u8 {
-        let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
-        let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
-        match System.realloc_excess(ptr, old_layout, new_layout) {
-            Ok(p) => {
-                *excess = p.1;
-                p.0
-            }
-            Err(e) => {
-                ptr::write(err as *mut AllocErr, e);
-                0 as *mut u8
-            }
-        }
-    }
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rdl_grow_in_place(ptr: *mut u8,
-                                             old_size: usize,
-                                             old_align: usize,
-                                             new_size: usize,
-                                             new_align: usize) -> u8 {
-        let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
-        let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
-        match System.grow_in_place(ptr, old_layout, new_layout) {
-            Ok(()) => 1,
-            Err(_) => 0,
-        }
-    }
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rdl_shrink_in_place(ptr: *mut u8,
-                                               old_size: usize,
-                                               old_align: usize,
-                                               new_size: usize,
-                                               new_align: usize) -> u8 {
-        let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
-        let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
-        match System.shrink_in_place(ptr, old_layout, new_layout) {
-            Ok(()) => 1,
-            Err(_) => 0,
-        }
-    }
-}
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index 4e7db5f0826..03c97de6ec1 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -25,26 +25,32 @@ use memchr;
 /// results in a system call. A `BufReader` performs large, infrequent reads on
 /// the underlying [`Read`] and maintains an in-memory buffer of the results.
 ///
+/// `BufReader` can improve the speed of programs that make *small* and
+/// *repeated* read calls to the same file or network socket.  It does not
+/// help when reading very large amounts at once, or reading just one or a few
+/// times.  It also provides no advantage when reading from a source that is
+/// already in memory, like a `Vec<u8>`.
+///
 /// [`Read`]: ../../std/io/trait.Read.html
 /// [`TcpStream::read`]: ../../std/net/struct.TcpStream.html#method.read
 /// [`TcpStream`]: ../../std/net/struct.TcpStream.html
 ///
 /// # Examples
 ///
-/// ```
+/// ```no_run
 /// use std::io::prelude::*;
 /// use std::io::BufReader;
 /// use std::fs::File;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// let f = File::open("log.txt")?;
-/// let mut reader = BufReader::new(f);
+/// fn main() -> std::io::Result<()> {
+///     let f = File::open("log.txt")?;
+///     let mut reader = BufReader::new(f);
 ///
-/// let mut line = String::new();
-/// let len = reader.read_line(&mut line)?;
-/// println!("First line is {} bytes long", len);
-/// # Ok(())
-/// # }
+///     let mut line = String::new();
+///     let len = reader.read_line(&mut line)?;
+///     println!("First line is {} bytes long", len);
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct BufReader<R> {
@@ -55,19 +61,20 @@ pub struct BufReader<R> {
 }
 
 impl<R: Read> BufReader<R> {
-    /// Creates a new `BufReader` with a default buffer capacity.
+    /// Creates a new `BufReader` with a default buffer capacity. The default is currently 8 KB,
+    /// but may change in the future.
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::io::BufReader;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let f = File::open("log.txt")?;
-    /// let reader = BufReader::new(f);
-    /// # Ok(())
-    /// # }
+    /// fn main() -> std::io::Result<()> {
+    ///     let f = File::open("log.txt")?;
+    ///     let reader = BufReader::new(f);
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(inner: R) -> BufReader<R> {
@@ -80,15 +87,15 @@ impl<R: Read> BufReader<R> {
     ///
     /// Creating a buffer with ten bytes of capacity:
     ///
-    /// ```
+    /// ```no_run
     /// use std::io::BufReader;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let f = File::open("log.txt")?;
-    /// let reader = BufReader::with_capacity(10, f);
-    /// # Ok(())
-    /// # }
+    /// fn main() -> std::io::Result<()> {
+    ///     let f = File::open("log.txt")?;
+    ///     let reader = BufReader::with_capacity(10, f);
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(cap: usize, inner: R) -> BufReader<R> {
@@ -111,17 +118,17 @@ impl<R: Read> BufReader<R> {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::io::BufReader;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let f1 = File::open("log.txt")?;
-    /// let reader = BufReader::new(f1);
+    /// fn main() -> std::io::Result<()> {
+    ///     let f1 = File::open("log.txt")?;
+    ///     let reader = BufReader::new(f1);
     ///
-    /// let f2 = reader.get_ref();
-    /// # Ok(())
-    /// # }
+    ///     let f2 = reader.get_ref();
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_ref(&self) -> &R { &self.inner }
@@ -132,44 +139,46 @@ impl<R: Read> BufReader<R> {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::io::BufReader;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let f1 = File::open("log.txt")?;
-    /// let mut reader = BufReader::new(f1);
+    /// fn main() -> std::io::Result<()> {
+    ///     let f1 = File::open("log.txt")?;
+    ///     let mut reader = BufReader::new(f1);
     ///
-    /// let f2 = reader.get_mut();
-    /// # Ok(())
-    /// # }
+    ///     let f2 = reader.get_mut();
+    ///     Ok(())
+    /// }
     /// ```
     #[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.
+    /// Returns a reference to the internally buffered data.
+    ///
+    /// Unlike `fill_buf`, this will not attempt to fill the buffer if it is empty.
     ///
     /// # Examples
-    /// ```
-    /// # #![feature(bufreader_is_empty)]
-    /// use std::io::BufReader;
-    /// use std::io::BufRead;
+    ///
+    /// ```no_run
+    /// # #![feature(bufreader_buffer)]
+    /// use std::io::{BufReader, 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());
+    /// fn main() -> std::io::Result<()> {
+    ///     let f = File::open("log.txt")?;
+    ///     let mut reader = BufReader::new(f);
+    ///     assert!(reader.buffer().is_empty());
     ///
-    /// if reader.fill_buf()?.len() > 0 {
-    ///     assert!(!reader.is_empty());
+    ///     if reader.fill_buf()?.len() > 0 {
+    ///         assert!(!reader.buffer().is_empty());
+    ///     }
+    ///     Ok(())
     /// }
-    /// # Ok(())
-    /// # }
     /// ```
-    #[unstable(feature = "bufreader_is_empty", issue = "45323", reason = "recently added")]
-    pub fn is_empty(&self) -> bool {
-        self.pos == self.cap
+    #[unstable(feature = "bufreader_buffer", issue = "45323")]
+    pub fn buffer(&self) -> &[u8] {
+        &self.buf[self.pos..self.cap]
     }
 
     /// Unwraps this `BufReader`, returning the underlying reader.
@@ -178,17 +187,17 @@ impl<R: Read> BufReader<R> {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::io::BufReader;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let f1 = File::open("log.txt")?;
-    /// let reader = BufReader::new(f1);
+    /// fn main() -> std::io::Result<()> {
+    ///     let f1 = File::open("log.txt")?;
+    ///     let reader = BufReader::new(f1);
     ///
-    /// let f2 = reader.into_inner();
-    /// # Ok(())
-    /// # }
+    ///     let f2 = reader.into_inner();
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_inner(self) -> R { self.inner }
@@ -293,7 +302,7 @@ impl<R: Seek> Seek for BufReader<R> {
     /// where `n` minus the internal buffer length overflows an `i64`, two
     /// seeks will be performed instead of one. If the second seek returns
     /// `Err`, the underlying reader will be left at the same position it would
-    /// have if you seeked to `SeekFrom::Current(0)`.
+    /// have if you called `seek` with `SeekFrom::Current(0)`.
     ///
     /// [`seek_relative`]: #method.seek_relative
     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
@@ -330,6 +339,12 @@ impl<R: Seek> Seek for BufReader<R> {
 /// `BufWriter` keeps an in-memory buffer of data and writes it to an underlying
 /// writer in large, infrequent batches.
 ///
+/// `BufWriter` can improve the speed of programs that make *small* and
+/// *repeated* write calls to the same file or network socket.  It does not
+/// help when writing very large amounts at once, or writing just one or a few
+/// times.  It also provides no advantage when writing to a destination that is
+/// in memory, like a `Vec<u8>`.
+///
 /// When the `BufWriter` is dropped, the contents of its buffer will be written
 /// out. However, any errors that happen in the process of flushing the buffer
 /// when the writer is dropped will be ignored. Code that wishes to handle such
@@ -413,7 +428,8 @@ pub struct BufWriter<W: Write> {
 pub struct IntoInnerError<W>(W, Error);
 
 impl<W: Write> BufWriter<W> {
-    /// Creates a new `BufWriter` with a default buffer capacity.
+    /// Creates a new `BufWriter` with a default buffer capacity. The default is currently 8 KB,
+    /// but may change in the future.
     ///
     /// # Examples
     ///
@@ -696,34 +712,47 @@ impl<W> fmt::Display for IntoInnerError<W> {
 /// We can use `LineWriter` to write one line at a time, significantly
 /// reducing the number of actual writes to the file.
 ///
-/// ```
-/// use std::fs::File;
+/// ```no_run
+/// use std::fs::{self, File};
 /// use std::io::prelude::*;
 /// use std::io::LineWriter;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// let road_not_taken = b"I shall be telling this with a sigh
+/// fn main() -> std::io::Result<()> {
+///     let road_not_taken = b"I shall be telling this with a sigh
 /// Somewhere ages and ages hence:
 /// Two roads diverged in a wood, and I -
 /// I took the one less traveled by,
 /// And that has made all the difference.";
 ///
-/// let file = File::create("poem.txt")?;
-/// let mut file = LineWriter::new(file);
+///     let file = File::create("poem.txt")?;
+///     let mut file = LineWriter::new(file);
 ///
-/// for &byte in road_not_taken.iter() {
-///    file.write(&[byte]).unwrap();
-/// }
+///     file.write_all(b"I shall be telling this with a sigh")?;
+///
+///     // No bytes are written until a newline is encountered (or
+///     // the internal buffer is filled).
+///     assert_eq!(fs::read_to_string("poem.txt")?, "");
+///     file.write_all(b"\n")?;
+///     assert_eq!(
+///         fs::read_to_string("poem.txt")?,
+///         "I shall be telling this with a sigh\n",
+///     );
 ///
-/// // let's check we did the right thing.
-/// let mut file = File::open("poem.txt")?;
-/// let mut contents = String::new();
+///     // Write the rest of the poem.
+///     file.write_all(b"Somewhere ages and ages hence:
+/// Two roads diverged in a wood, and I -
+/// I took the one less traveled by,
+/// And that has made all the difference.")?;
 ///
-/// file.read_to_string(&mut contents)?;
+///     // The last line of the poem doesn't end in a newline, so
+///     // we have to flush or drop the `LineWriter` to finish
+///     // writing.
+///     file.flush()?;
 ///
-/// assert_eq!(contents.as_bytes(), &road_not_taken[..]);
-/// # Ok(())
-/// # }
+///     // Confirm the whole poem was written.
+///     assert_eq!(fs::read("poem.txt")?, &road_not_taken[..]);
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct LineWriter<W: Write> {
@@ -736,15 +765,15 @@ impl<W: Write> LineWriter<W> {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs::File;
     /// use std::io::LineWriter;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let file = File::create("poem.txt")?;
-    /// let file = LineWriter::new(file);
-    /// # Ok(())
-    /// # }
+    /// fn main() -> std::io::Result<()> {
+    ///     let file = File::create("poem.txt")?;
+    ///     let file = LineWriter::new(file);
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(inner: W) -> LineWriter<W> {
@@ -757,15 +786,15 @@ impl<W: Write> LineWriter<W> {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs::File;
     /// use std::io::LineWriter;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let file = File::create("poem.txt")?;
-    /// let file = LineWriter::with_capacity(100, file);
-    /// # Ok(())
-    /// # }
+    /// fn main() -> std::io::Result<()> {
+    ///     let file = File::create("poem.txt")?;
+    ///     let file = LineWriter::with_capacity(100, file);
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(cap: usize, inner: W) -> LineWriter<W> {
@@ -779,17 +808,17 @@ impl<W: Write> LineWriter<W> {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs::File;
     /// use std::io::LineWriter;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let file = File::create("poem.txt")?;
-    /// let file = LineWriter::new(file);
+    /// fn main() -> std::io::Result<()> {
+    ///     let file = File::create("poem.txt")?;
+    ///     let file = LineWriter::new(file);
     ///
-    /// let reference = file.get_ref();
-    /// # Ok(())
-    /// # }
+    ///     let reference = file.get_ref();
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_ref(&self) -> &W { self.inner.get_ref() }
@@ -801,18 +830,18 @@ impl<W: Write> LineWriter<W> {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs::File;
     /// use std::io::LineWriter;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let file = File::create("poem.txt")?;
-    /// let mut file = LineWriter::new(file);
+    /// fn main() -> std::io::Result<()> {
+    ///     let file = File::create("poem.txt")?;
+    ///     let mut file = LineWriter::new(file);
     ///
-    /// // we can use reference just like file
-    /// let reference = file.get_mut();
-    /// # Ok(())
-    /// # }
+    ///     // we can use reference just like file
+    ///     let reference = file.get_mut();
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() }
@@ -821,24 +850,24 @@ impl<W: Write> LineWriter<W> {
     ///
     /// The internal buffer is written out before returning the writer.
     ///
-    // # Errors
+    /// # Errors
     ///
     /// An `Err` will be returned if an error occurs while flushing the buffer.
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs::File;
     /// use std::io::LineWriter;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let file = File::create("poem.txt")?;
+    /// fn main() -> std::io::Result<()> {
+    ///     let file = File::create("poem.txt")?;
     ///
-    /// let writer: LineWriter<File> = LineWriter::new(file);
+    ///     let writer: LineWriter<File> = LineWriter::new(file);
     ///
-    /// let file: File = writer.into_inner()?;
-    /// # Ok(())
-    /// # }
+    ///     let file: File = writer.into_inner()?;
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_inner(self) -> Result<W, IntoInnerError<LineWriter<W>>> {
@@ -1210,23 +1239,6 @@ mod tests {
     }
 
     #[test]
-    fn read_char_buffered() {
-        let buf = [195, 159];
-        let reader = BufReader::with_capacity(1, &buf[..]);
-        assert_eq!(reader.chars().next().unwrap().unwrap(), 'ß');
-    }
-
-    #[test]
-    fn test_chars() {
-        let buf = [195, 159, b'a'];
-        let reader = BufReader::with_capacity(1, &buf[..]);
-        let mut it = reader.chars();
-        assert_eq!(it.next().unwrap().unwrap(), 'ß');
-        assert_eq!(it.next().unwrap().unwrap(), 'a');
-        assert!(it.next().is_none());
-    }
-
-    #[test]
     #[should_panic]
     fn dont_panic_in_drop_on_panicked_flush() {
         struct FailFlushWriter;
diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs
index c8447707d5b..14f20151dca 100644
--- a/src/libstd/io/cursor.rs
+++ b/src/libstd/io/cursor.rs
@@ -14,12 +14,13 @@ use core::convert::TryInto;
 use cmp;
 use io::{self, Initializer, SeekFrom, Error, ErrorKind};
 
-/// A `Cursor` wraps another type and provides it with a
+/// A `Cursor` wraps an in-memory buffer and provides it with a
 /// [`Seek`] implementation.
 ///
-/// `Cursor`s are typically used with in-memory buffers to allow them to
-/// implement [`Read`] and/or [`Write`], allowing these buffers to be used
-/// anywhere you might use a reader or writer that does actual I/O.
+/// `Cursor`s are used with in-memory buffers, anything implementing
+/// `AsRef<[u8]>`, to allow them to implement [`Read`] and/or [`Write`],
+/// allowing these buffers to be used anywhere you might use a reader or writer
+/// that does actual I/O.
 ///
 /// The standard library implements some I/O traits on various types which
 /// are commonly used as a buffer, like `Cursor<`[`Vec`]`<u8>>` and
@@ -87,11 +88,11 @@ pub struct Cursor<T> {
 }
 
 impl<T> Cursor<T> {
-    /// Creates a new cursor wrapping the provided underlying I/O object.
+    /// Creates a new cursor wrapping the provided underlying in-memory buffer.
     ///
-    /// Cursor initial position is `0` even if underlying object (e.
-    /// g. `Vec`) is not empty. So writing to cursor starts with
-    /// overwriting `Vec` content, not with appending to it.
+    /// Cursor initial position is `0` even if underlying buffer (e.g. `Vec`)
+    /// is not empty. So writing to cursor starts with overwriting `Vec`
+    /// content, not with appending to it.
     ///
     /// # Examples
     ///
@@ -296,7 +297,7 @@ impl<'a> Write for Cursor<&'a mut [u8]> {
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
 }
 
-#[unstable(feature = "cursor_mut_vec", issue = "30132")]
+#[stable(feature = "cursor_mut_vec", since = "1.25.0")]
 impl<'a> Write for Cursor<&'a mut Vec<u8>> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         vec_write(&mut self.pos, self.inner, buf)
@@ -550,24 +551,6 @@ mod tests {
     }
 
     #[test]
-    fn test_read_char() {
-        let b = &b"Vi\xE1\xBB\x87t"[..];
-        let mut c = Cursor::new(b).chars();
-        assert_eq!(c.next().unwrap().unwrap(), 'V');
-        assert_eq!(c.next().unwrap().unwrap(), 'i');
-        assert_eq!(c.next().unwrap().unwrap(), 'ệ');
-        assert_eq!(c.next().unwrap().unwrap(), 't');
-        assert!(c.next().is_none());
-    }
-
-    #[test]
-    fn test_read_bad_char() {
-        let b = &b"\x80"[..];
-        let mut c = Cursor::new(b).chars();
-        assert!(c.next().unwrap().is_err());
-    }
-
-    #[test]
     fn seek_past_end() {
         let buf = [0xff];
         let mut r = Cursor::new(&buf[..]);
diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs
index f0b41f30251..3e50988a68b 100644
--- a/src/libstd/io/error.rs
+++ b/src/libstd/io/error.rs
@@ -83,7 +83,7 @@ enum Repr {
 #[derive(Debug)]
 struct Custom {
     kind: ErrorKind,
-    error: Box<error::Error+Send+Sync>,
+    error: Box<dyn error::Error+Send+Sync>,
 }
 
 /// A list specifying general categories of I/O error.
@@ -97,6 +97,7 @@ struct Custom {
 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow(deprecated)]
+#[non_exhaustive]
 pub enum ErrorKind {
     /// An entity was not found, often a file.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -180,15 +181,6 @@ pub enum ErrorKind {
     /// read.
     #[stable(feature = "read_exact", since = "1.6.0")]
     UnexpectedEof,
-
-    /// A marker variant that tells the compiler that users of this enum cannot
-    /// match it exhaustively.
-    #[unstable(feature = "io_error_internals",
-               reason = "better expressed through extensible enums that this \
-                         enum cannot be exhaustively matched against",
-               issue = "0")]
-    #[doc(hidden)]
-    __Nonexhaustive,
 }
 
 impl ErrorKind {
@@ -212,7 +204,6 @@ impl ErrorKind {
             ErrorKind::Interrupted => "operation interrupted",
             ErrorKind::Other => "other os error",
             ErrorKind::UnexpectedEof => "unexpected end of file",
-            ErrorKind::__Nonexhaustive => unreachable!()
         }
     }
 }
@@ -250,12 +241,12 @@ impl Error {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new<E>(kind: ErrorKind, error: E) -> Error
-        where E: Into<Box<error::Error+Send+Sync>>
+        where E: Into<Box<dyn error::Error+Send+Sync>>
     {
         Self::_new(kind, error.into())
     }
 
-    fn _new(kind: ErrorKind, error: Box<error::Error+Send+Sync>) -> Error {
+    fn _new(kind: ErrorKind, error: Box<dyn error::Error+Send+Sync>) -> Error {
         Error {
             repr: Repr::Custom(Box::new(Custom {
                 kind,
@@ -292,8 +283,8 @@ impl Error {
     /// # if cfg!(target_os = "linux") {
     /// use std::io;
     ///
-    /// let error = io::Error::from_raw_os_error(98);
-    /// assert_eq!(error.kind(), io::ErrorKind::AddrInUse);
+    /// let error = io::Error::from_raw_os_error(22);
+    /// assert_eq!(error.kind(), io::ErrorKind::InvalidInput);
     /// # }
     /// ```
     ///
@@ -303,8 +294,8 @@ impl Error {
     /// # if cfg!(windows) {
     /// use std::io;
     ///
-    /// let error = io::Error::from_raw_os_error(10048);
-    /// assert_eq!(error.kind(), io::ErrorKind::AddrInUse);
+    /// let error = io::Error::from_raw_os_error(10022);
+    /// assert_eq!(error.kind(), io::ErrorKind::InvalidInput);
     /// # }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -373,7 +364,7 @@ impl Error {
     /// }
     /// ```
     #[stable(feature = "io_error_inner", since = "1.3.0")]
-    pub fn get_ref(&self) -> Option<&(error::Error+Send+Sync+'static)> {
+    pub fn get_ref(&self) -> Option<&(dyn error::Error+Send+Sync+'static)> {
         match self.repr {
             Repr::Os(..) => None,
             Repr::Simple(..) => None,
@@ -444,7 +435,7 @@ impl Error {
     /// }
     /// ```
     #[stable(feature = "io_error_inner", since = "1.3.0")]
-    pub fn get_mut(&mut self) -> Option<&mut (error::Error+Send+Sync+'static)> {
+    pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error+Send+Sync+'static)> {
         match self.repr {
             Repr::Os(..) => None,
             Repr::Simple(..) => None,
@@ -478,7 +469,7 @@ impl Error {
     /// }
     /// ```
     #[stable(feature = "io_error_inner", since = "1.3.0")]
-    pub fn into_inner(self) -> Option<Box<error::Error+Send+Sync>> {
+    pub fn into_inner(self) -> Option<Box<dyn error::Error+Send+Sync>> {
         match self.repr {
             Repr::Os(..) => None,
             Repr::Simple(..) => None,
@@ -551,7 +542,7 @@ impl error::Error for Error {
         }
     }
 
-    fn cause(&self) -> Option<&error::Error> {
+    fn cause(&self) -> Option<&dyn error::Error> {
         match self.repr {
             Repr::Os(..) => None,
             Repr::Simple(..) => None,
diff --git a/src/libstd/io/lazy.rs b/src/libstd/io/lazy.rs
index 9cef4e3cdf1..4fb367fb6ba 100644
--- a/src/libstd/io/lazy.rs
+++ b/src/libstd/io/lazy.rs
@@ -15,15 +15,21 @@ use sys_common;
 use sys_common::mutex::Mutex;
 
 pub struct Lazy<T> {
+    // We never call `lock.init()`, so it is UB to attempt to acquire this mutex reentrantly!
     lock: Mutex,
     ptr: Cell<*mut Arc<T>>,
     init: fn() -> Arc<T>,
 }
 
+#[inline]
+const fn done<T>() -> *mut Arc<T> { 1_usize as *mut _ }
+
 unsafe impl<T> Sync for Lazy<T> {}
 
 impl<T: Send + Sync + 'static> Lazy<T> {
-    pub const fn new(init: fn() -> Arc<T>) -> Lazy<T> {
+    /// Safety: `init` must not call `get` on the variable that is being
+    /// initialized.
+    pub const unsafe fn new(init: fn() -> Arc<T>) -> Lazy<T> {
         Lazy {
             lock: Mutex::new(),
             ptr: Cell::new(ptr::null_mut()),
@@ -33,32 +39,34 @@ impl<T: Send + Sync + 'static> Lazy<T> {
 
     pub fn get(&'static self) -> Option<Arc<T>> {
         unsafe {
-            self.lock.lock();
+            let _guard = self.lock.lock();
             let ptr = self.ptr.get();
-            let ret = if ptr.is_null() {
+            if ptr.is_null() {
                 Some(self.init())
-            } else if ptr as usize == 1 {
+            } else if ptr == done() {
                 None
             } else {
                 Some((*ptr).clone())
-            };
-            self.lock.unlock();
-            return ret
+            }
         }
     }
 
+    // Must only be called with `lock` held
     unsafe fn init(&'static self) -> Arc<T> {
         // If we successfully register an at exit handler, then we cache the
         // `Arc` allocation in our own internal box (it will get deallocated by
         // the at exit handler). Otherwise we just return the freshly allocated
         // `Arc`.
         let registered = sys_common::at_exit(move || {
-            self.lock.lock();
-            let ptr = self.ptr.get();
-            self.ptr.set(1 as *mut _);
-            self.lock.unlock();
+            let ptr = {
+                let _guard = self.lock.lock();
+                self.ptr.replace(done())
+            };
             drop(Box::from_raw(ptr))
         });
+        // This could reentrantly call `init` again, which is a problem
+        // because our `lock` allows reentrancy!
+        // That's why `new` is unsafe and requires the caller to ensure no reentrancy happens.
         let ret = (self.init)();
         if registered.is_ok() {
             self.ptr.set(Box::into_raw(Box::new(ret.clone())));
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 33d11ebb350..b83f3fbe7a5 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -24,21 +24,21 @@
 //! example, [`Read`] adds a [`read`][`Read::read`] method, which we can use on
 //! [`File`]s:
 //!
-//! ```
+//! ```no_run
 //! use std::io;
 //! use std::io::prelude::*;
 //! use std::fs::File;
 //!
-//! # fn foo() -> io::Result<()> {
-//! let mut f = File::open("foo.txt")?;
-//! let mut buffer = [0; 10];
+//! fn main() -> io::Result<()> {
+//!     let mut f = File::open("foo.txt")?;
+//!     let mut buffer = [0; 10];
 //!
-//! // read up to 10 bytes
-//! f.read(&mut buffer)?;
+//!     // read up to 10 bytes
+//!     f.read(&mut buffer)?;
 //!
-//! println!("The bytes: {:?}", buffer);
-//! # Ok(())
-//! # }
+//!     println!("The bytes: {:?}", buffer);
+//!     Ok(())
+//! }
 //! ```
 //!
 //! [`Read`] and [`Write`] are so important, implementors of the two traits have a
@@ -52,25 +52,25 @@
 //! how the reading happens. [`Seek`] lets you control where the next byte is
 //! coming from:
 //!
-//! ```
+//! ```no_run
 //! use std::io;
 //! use std::io::prelude::*;
 //! use std::io::SeekFrom;
 //! use std::fs::File;
 //!
-//! # fn foo() -> io::Result<()> {
-//! let mut f = File::open("foo.txt")?;
-//! let mut buffer = [0; 10];
+//! fn main() -> io::Result<()> {
+//!     let mut f = File::open("foo.txt")?;
+//!     let mut buffer = [0; 10];
 //!
-//! // skip to the last 10 bytes of the file
-//! f.seek(SeekFrom::End(-10))?;
+//!     // skip to the last 10 bytes of the file
+//!     f.seek(SeekFrom::End(-10))?;
 //!
-//! // read up to 10 bytes
-//! f.read(&mut buffer)?;
+//!     // read up to 10 bytes
+//!     f.read(&mut buffer)?;
 //!
-//! println!("The bytes: {:?}", buffer);
-//! # Ok(())
-//! # }
+//!     println!("The bytes: {:?}", buffer);
+//!     Ok(())
+//! }
 //! ```
 //!
 //! [`BufRead`] uses an internal buffer to provide a number of other ways to read, but
@@ -87,70 +87,70 @@
 //! For example, [`BufReader`] works with the [`BufRead`] trait to add extra
 //! methods to any reader:
 //!
-//! ```
+//! ```no_run
 //! use std::io;
 //! use std::io::prelude::*;
 //! use std::io::BufReader;
 //! use std::fs::File;
 //!
-//! # fn foo() -> io::Result<()> {
-//! let f = File::open("foo.txt")?;
-//! let mut reader = BufReader::new(f);
-//! let mut buffer = String::new();
+//! fn main() -> io::Result<()> {
+//!     let f = File::open("foo.txt")?;
+//!     let mut reader = BufReader::new(f);
+//!     let mut buffer = String::new();
 //!
-//! // read a line into buffer
-//! reader.read_line(&mut buffer)?;
+//!     // read a line into buffer
+//!     reader.read_line(&mut buffer)?;
 //!
-//! println!("{}", buffer);
-//! # Ok(())
-//! # }
+//!     println!("{}", buffer);
+//!     Ok(())
+//! }
 //! ```
 //!
 //! [`BufWriter`] doesn't add any new ways of writing; it just buffers every call
 //! to [`write`][`Write::write`]:
 //!
-//! ```
+//! ```no_run
 //! use std::io;
 //! use std::io::prelude::*;
 //! use std::io::BufWriter;
 //! use std::fs::File;
 //!
-//! # fn foo() -> io::Result<()> {
-//! let f = File::create("foo.txt")?;
-//! {
-//!     let mut writer = BufWriter::new(f);
+//! fn main() -> io::Result<()> {
+//!     let f = File::create("foo.txt")?;
+//!     {
+//!         let mut writer = BufWriter::new(f);
 //!
-//!     // write a byte to the buffer
-//!     writer.write(&[42])?;
+//!         // write a byte to the buffer
+//!         writer.write(&[42])?;
 //!
-//! } // the buffer is flushed once writer goes out of scope
+//!     } // the buffer is flushed once writer goes out of scope
 //!
-//! # Ok(())
-//! # }
+//!     Ok(())
+//! }
 //! ```
 //!
 //! ## Standard input and output
 //!
 //! A very common source of input is standard input:
 //!
-//! ```
+//! ```no_run
 //! use std::io;
 //!
-//! # fn foo() -> io::Result<()> {
-//! let mut input = String::new();
+//! fn main() -> io::Result<()> {
+//!     let mut input = String::new();
 //!
-//! io::stdin().read_line(&mut input)?;
+//!     io::stdin().read_line(&mut input)?;
 //!
-//! println!("You typed: {}", input.trim());
-//! # Ok(())
-//! # }
+//!     println!("You typed: {}", input.trim());
+//!     Ok(())
+//! }
 //! ```
 //!
 //! Note that you cannot use the [`?` operator] in functions that do not return
-//! a [`Result<T, E>`][`Result`] (e.g. `main`). Instead, you can call [`.unwrap()`]
+//! a [`Result<T, E>`][`Result`]. Instead, you can call [`.unwrap()`]
 //! or `match` on the return value to catch any possible errors:
 //!
-//! ```
+//! ```no_run
 //! use std::io;
 //!
 //! let mut input = String::new();
@@ -160,14 +160,14 @@
 //!
 //! And a very common source of output is standard output:
 //!
-//! ```
+//! ```no_run
 //! use std::io;
 //! use std::io::prelude::*;
 //!
-//! # fn foo() -> io::Result<()> {
-//! io::stdout().write(&[42])?;
-//! # Ok(())
-//! # }
+//! fn main() -> io::Result<()> {
+//!     io::stdout().write(&[42])?;
+//!     Ok(())
+//! }
 //! ```
 //!
 //! Of course, using [`io::stdout`] directly is less common than something like
@@ -179,22 +179,21 @@
 //! ways of iterating over I/O. For example, [`Lines`] is used to split over
 //! lines:
 //!
-//! ```
+//! ```no_run
 //! use std::io;
 //! use std::io::prelude::*;
 //! use std::io::BufReader;
 //! use std::fs::File;
 //!
-//! # fn foo() -> io::Result<()> {
-//! let f = File::open("foo.txt")?;
-//! let reader = BufReader::new(f);
+//! fn main() -> io::Result<()> {
+//!     let f = File::open("foo.txt")?;
+//!     let reader = BufReader::new(f);
 //!
-//! for line in reader.lines() {
-//!     println!("{}", line?);
+//!     for line in reader.lines() {
+//!         println!("{}", line?);
+//!     }
+//!     Ok(())
 //! }
-//!
-//! # Ok(())
-//! # }
 //! ```
 //!
 //! ## Functions
@@ -203,13 +202,13 @@
 //! features. For example, we can use three of these functions to copy everything
 //! from standard input to standard output:
 //!
-//! ```
+//! ```no_run
 //! use std::io;
 //!
-//! # fn foo() -> io::Result<()> {
-//! io::copy(&mut io::stdin(), &mut io::stdout())?;
-//! # Ok(())
-//! # }
+//! fn main() -> io::Result<()> {
+//!     io::copy(&mut io::stdin(), &mut io::stdout())?;
+//!     Ok(())
+//! }
 //! ```
 //!
 //! [functions-list]: #functions-1
@@ -271,10 +270,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use cmp;
-use core::str as core_str;
-use error as std_error;
 use fmt;
-use result;
 use str;
 use memchr;
 use ptr;
@@ -358,19 +354,26 @@ fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize>
 // avoid paying to allocate and zero a huge chunk of memory if the reader only
 // has 4 bytes while still making large reads if the reader does have a ton
 // of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every
-// time is 4,500 times (!) slower than this if the reader has a very small
-// amount of data to return.
+// time is 4,500 times (!) slower than a default reservation size of 32 if the
+// reader has a very small amount of data to return.
 //
 // Because we're extending the buffer with uninitialized data for trusted
 // readers, we need to make sure to truncate that if any of this panics.
 fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> {
+    read_to_end_with_reservation(r, buf, 32)
+}
+
+fn read_to_end_with_reservation<R: Read + ?Sized>(r: &mut R,
+                                                  buf: &mut Vec<u8>,
+                                                  reservation_size: usize) -> Result<usize>
+{
     let start_len = buf.len();
     let mut g = Guard { len: buf.len(), buf: buf };
     let ret;
     loop {
         if g.len == g.buf.len() {
             unsafe {
-                g.buf.reserve(32);
+                g.buf.reserve(reservation_size);
                 let capacity = g.buf.capacity();
                 g.buf.set_len(capacity);
                 r.initializer().initialize(&mut g.buf[g.len..]);
@@ -416,47 +419,47 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize>
 ///
 /// [`File`]s implement `Read`:
 ///
-/// ```
-/// # use std::io;
+/// ```no_run
+/// use std::io;
 /// use std::io::prelude::*;
 /// use std::fs::File;
 ///
-/// # fn foo() -> io::Result<()> {
-/// let mut f = File::open("foo.txt")?;
-/// let mut buffer = [0; 10];
+/// fn main() -> io::Result<()> {
+///     let mut f = File::open("foo.txt")?;
+///     let mut buffer = [0; 10];
 ///
-/// // read up to 10 bytes
-/// f.read(&mut buffer)?;
+///     // read up to 10 bytes
+///     f.read(&mut buffer)?;
 ///
-/// let mut buffer = vec![0; 10];
-/// // read the whole file
-/// f.read_to_end(&mut buffer)?;
+///     let mut buffer = vec![0; 10];
+///     // read the whole file
+///     f.read_to_end(&mut buffer)?;
 ///
-/// // read into a String, so that you don't need to do the conversion.
-/// let mut buffer = String::new();
-/// f.read_to_string(&mut buffer)?;
+///     // read into a String, so that you don't need to do the conversion.
+///     let mut buffer = String::new();
+///     f.read_to_string(&mut buffer)?;
 ///
-/// // and more! See the other methods for more details.
-/// # Ok(())
-/// # }
+///     // and more! See the other methods for more details.
+///     Ok(())
+/// }
 /// ```
 ///
 /// Read from [`&str`] because [`&[u8]`][slice] implements `Read`:
 ///
-/// ```
+/// ```no_run
 /// # 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];
+/// fn main() -> 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)?;
+///     // read up to 10 bytes
+///     b.read(&mut buffer)?;
 ///
-/// // etc... it works exactly as a File does!
-/// # Ok(())
-/// # }
+///     // etc... it works exactly as a File does!
+///     Ok(())
+/// }
 /// ```
 ///
 /// [`read()`]: trait.Read.html#tymethod.read
@@ -509,19 +512,19 @@ pub trait Read {
     /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
     /// [`File`]: ../fs/struct.File.html
     ///
-    /// ```
+    /// ```no_run
     /// use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let mut f = File::open("foo.txt")?;
-    /// let mut buffer = [0; 10];
+    /// fn main() -> io::Result<()> {
+    ///     let mut f = File::open("foo.txt")?;
+    ///     let mut buffer = [0; 10];
     ///
-    /// // read up to 10 bytes
-    /// f.read(&mut buffer[..])?;
-    /// # Ok(())
-    /// # }
+    ///     // read up to 10 bytes
+    ///     f.read(&mut buffer[..])?;
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
@@ -582,20 +585,25 @@ pub trait Read {
     /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
     /// [`File`]: ../fs/struct.File.html
     ///
-    /// ```
+    /// ```no_run
     /// use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let mut f = File::open("foo.txt")?;
-    /// let mut buffer = Vec::new();
+    /// fn main() -> io::Result<()> {
+    ///     let mut f = File::open("foo.txt")?;
+    ///     let mut buffer = Vec::new();
     ///
-    /// // read the whole file
-    /// f.read_to_end(&mut buffer)?;
-    /// # Ok(())
-    /// # }
+    ///     // read the whole file
+    ///     f.read_to_end(&mut buffer)?;
+    ///     Ok(())
+    /// }
     /// ```
+    ///
+    /// (See also the [`std::fs::read`] convenience function for reading from a
+    /// file.)
+    ///
+    /// [`std::fs::read`]: ../fs/fn.read.html
     #[stable(feature = "rust1", since = "1.0.0")]
     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
         read_to_end(self, buf)
@@ -621,19 +629,24 @@ pub trait Read {
     ///
     /// [file]: ../fs/struct.File.html
     ///
-    /// ```
+    /// ```no_run
     /// use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let mut f = File::open("foo.txt")?;
-    /// let mut buffer = String::new();
+    /// fn main() -> io::Result<()> {
+    ///     let mut f = File::open("foo.txt")?;
+    ///     let mut buffer = String::new();
     ///
-    /// f.read_to_string(&mut buffer)?;
-    /// # Ok(())
-    /// # }
+    ///     f.read_to_string(&mut buffer)?;
+    ///     Ok(())
+    /// }
     /// ```
+    ///
+    /// (See also the [`std::fs::read_to_string`] convenience function for
+    /// reading from a file.)
+    ///
+    /// [`std::fs::read_to_string`]: ../fs/fn.read_to_string.html
     #[stable(feature = "rust1", since = "1.0.0")]
     fn read_to_string(&mut self, buf: &mut String) -> Result<usize> {
         // Note that we do *not* call `.read_to_end()` here. We are passing
@@ -683,19 +696,19 @@ pub trait Read {
     /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
     /// [`ErrorKind::UnexpectedEof`]: ../../std/io/enum.ErrorKind.html#variant.UnexpectedEof
     ///
-    /// ```
+    /// ```no_run
     /// use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let mut f = File::open("foo.txt")?;
-    /// let mut buffer = [0; 10];
+    /// fn main() -> io::Result<()> {
+    ///     let mut f = File::open("foo.txt")?;
+    ///     let mut buffer = [0; 10];
     ///
-    /// // read exactly 10 bytes
-    /// f.read_exact(&mut buffer)?;
-    /// # Ok(())
-    /// # }
+    ///     // read exactly 10 bytes
+    ///     f.read_exact(&mut buffer)?;
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "read_exact", since = "1.6.0")]
     fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> {
@@ -726,28 +739,28 @@ pub trait Read {
     ///
     /// [file]: ../fs/struct.File.html
     ///
-    /// ```
+    /// ```no_run
     /// use std::io;
     /// use std::io::Read;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let mut f = File::open("foo.txt")?;
-    /// let mut buffer = Vec::new();
-    /// let mut other_buffer = Vec::new();
+    /// fn main() -> io::Result<()> {
+    ///     let mut f = File::open("foo.txt")?;
+    ///     let mut buffer = Vec::new();
+    ///     let mut other_buffer = Vec::new();
     ///
-    /// {
-    ///     let reference = f.by_ref();
+    ///     {
+    ///         let reference = f.by_ref();
     ///
-    ///     // read at most 5 bytes
-    ///     reference.take(5).read_to_end(&mut buffer)?;
+    ///         // read at most 5 bytes
+    ///         reference.take(5).read_to_end(&mut buffer)?;
     ///
-    /// } // drop our &mut reference so we can use f again
+    ///     } // drop our &mut reference so we can use f again
     ///
-    /// // original file still usable, read the rest
-    /// f.read_to_end(&mut other_buffer)?;
-    /// # Ok(())
-    /// # }
+    ///     // original file still usable, read the rest
+    ///     f.read_to_end(&mut other_buffer)?;
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn by_ref(&mut self) -> &mut Self where Self: Sized { self }
@@ -772,69 +785,25 @@ pub trait Read {
     /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
     /// [`None`]: ../../std/option/enum.Option.html#variant.None
     ///
-    /// ```
+    /// ```no_run
     /// use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let mut f = File::open("foo.txt")?;
+    /// fn main() -> io::Result<()> {
+    ///     let mut f = File::open("foo.txt")?;
     ///
-    /// for byte in f.bytes() {
-    ///     println!("{}", byte.unwrap());
+    ///     for byte in f.bytes() {
+    ///         println!("{}", byte.unwrap());
+    ///     }
+    ///     Ok(())
     /// }
-    /// # Ok(())
-    /// # }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn bytes(self) -> Bytes<Self> where Self: Sized {
         Bytes { inner: self }
     }
 
-    /// Transforms this `Read` instance to an [`Iterator`] over [`char`]s.
-    ///
-    /// This adaptor will attempt to interpret this reader as a UTF-8 encoded
-    /// sequence of characters. The returned iterator will return [`None`] once
-    /// EOF is reached for this reader. Otherwise each element yielded will be a
-    /// [`Result`]`<`[`char`]`, E>` where `E` may contain information about what I/O error
-    /// occurred or where decoding failed.
-    ///
-    /// Currently this adaptor will discard intermediate data read, and should
-    /// be avoided if this is not desired.
-    ///
-    /// # Examples
-    ///
-    /// [`File`]s implement `Read`:
-    ///
-    /// [`File`]: ../fs/struct.File.html
-    /// [`Iterator`]: ../../std/iter/trait.Iterator.html
-    /// [`Result`]: ../../std/result/enum.Result.html
-    /// [`char`]: ../../std/primitive.char.html
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    ///
-    /// ```
-    /// #![feature(io)]
-    /// use std::io;
-    /// use std::io::prelude::*;
-    /// use std::fs::File;
-    ///
-    /// # fn foo() -> io::Result<()> {
-    /// let mut f = File::open("foo.txt")?;
-    ///
-    /// for c in f.chars() {
-    ///     println!("{}", c.unwrap());
-    /// }
-    /// # Ok(())
-    /// # }
-    /// ```
-    #[unstable(feature = "io", reason = "the semantics of a partial read/write \
-                                         of where errors happen is currently \
-                                         unclear and may change",
-               issue = "27802")]
-    fn chars(self) -> Chars<Self> where Self: Sized {
-        Chars { inner: self }
-    }
-
     /// Creates an adaptor which will chain this stream with another.
     ///
     /// The returned `Read` instance will first read all bytes from this object
@@ -847,23 +816,23 @@ pub trait Read {
     ///
     /// [file]: ../fs/struct.File.html
     ///
-    /// ```
+    /// ```no_run
     /// use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let mut f1 = File::open("foo.txt")?;
-    /// let mut f2 = File::open("bar.txt")?;
+    /// fn main() -> io::Result<()> {
+    ///     let mut f1 = File::open("foo.txt")?;
+    ///     let mut f2 = File::open("bar.txt")?;
     ///
-    /// let mut handle = f1.chain(f2);
-    /// let mut buffer = String::new();
+    ///     let mut handle = f1.chain(f2);
+    ///     let mut buffer = String::new();
     ///
-    /// // read the value into a String. We could use any Read method here,
-    /// // this is just one example.
-    /// handle.read_to_string(&mut buffer)?;
-    /// # Ok(())
-    /// # }
+    ///     // read the value into a String. We could use any Read method here,
+    ///     // this is just one example.
+    ///     handle.read_to_string(&mut buffer)?;
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn chain<R: Read>(self, next: R) -> Chain<Self, R> where Self: Sized {
@@ -885,21 +854,21 @@ pub trait Read {
     /// [`Ok(0)`]: ../../std/result/enum.Result.html#variant.Ok
     /// [`read()`]: trait.Read.html#tymethod.read
     ///
-    /// ```
+    /// ```no_run
     /// use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let mut f = File::open("foo.txt")?;
-    /// let mut buffer = [0; 5];
+    /// fn main() -> io::Result<()> {
+    ///     let mut f = File::open("foo.txt")?;
+    ///     let mut buffer = [0; 5];
     ///
-    /// // read at most five bytes
-    /// let mut handle = f.take(5);
+    ///     // read at most five bytes
+    ///     let mut handle = f.take(5);
     ///
-    /// handle.read(&mut buffer)?;
-    /// # Ok(())
-    /// # }
+    ///     handle.read(&mut buffer)?;
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn take(self, limit: u64) -> Take<Self> where Self: Sized {
@@ -974,16 +943,16 @@ impl Initializer {
 ///
 /// # Examples
 ///
-/// ```
+/// ```no_run
 /// use std::io::prelude::*;
 /// use std::fs::File;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// let mut buffer = File::create("foo.txt")?;
+/// fn main() -> std::io::Result<()> {
+///     let mut buffer = File::create("foo.txt")?;
 ///
-/// buffer.write(b"some bytes")?;
-/// # Ok(())
-/// # }
+///     buffer.write(b"some bytes")?;
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(spotlight)]
@@ -1022,17 +991,17 @@ pub trait Write {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::io::prelude::*;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let mut buffer = File::create("foo.txt")?;
+    /// fn main() -> std::io::Result<()> {
+    ///     let mut buffer = File::create("foo.txt")?;
     ///
-    /// // Writes some prefix of the byte string, not necessarily all of it.
-    /// buffer.write(b"some bytes")?;
-    /// # Ok(())
-    /// # }
+    ///     // Writes some prefix of the byte string, not necessarily all of it.
+    ///     buffer.write(b"some bytes")?;
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn write(&mut self, buf: &[u8]) -> Result<usize>;
@@ -1047,18 +1016,18 @@ pub trait Write {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::io::prelude::*;
     /// use std::io::BufWriter;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let mut buffer = BufWriter::new(File::create("foo.txt")?);
+    /// fn main() -> std::io::Result<()> {
+    ///     let mut buffer = BufWriter::new(File::create("foo.txt")?);
     ///
-    /// buffer.write(b"some bytes")?;
-    /// buffer.flush()?;
-    /// # Ok(())
-    /// # }
+    ///     buffer.write(b"some bytes")?;
+    ///     buffer.flush()?;
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn flush(&mut self) -> Result<()>;
@@ -1082,16 +1051,16 @@ pub trait Write {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::io::prelude::*;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let mut buffer = File::create("foo.txt")?;
+    /// fn main() -> std::io::Result<()> {
+    ///     let mut buffer = File::create("foo.txt")?;
     ///
-    /// buffer.write_all(b"some bytes")?;
-    /// # Ok(())
-    /// # }
+    ///     buffer.write_all(b"some bytes")?;
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
@@ -1131,19 +1100,19 @@ pub trait Write {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::io::prelude::*;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let mut buffer = File::create("foo.txt")?;
+    /// fn main() -> std::io::Result<()> {
+    ///     let mut buffer = File::create("foo.txt")?;
     ///
-    /// // this call
-    /// write!(buffer, "{:.*}", 2, 1.234567)?;
-    /// // turns into this:
-    /// buffer.write_fmt(format_args!("{:.*}", 2, 1.234567))?;
-    /// # Ok(())
-    /// # }
+    ///     // this call
+    ///     write!(buffer, "{:.*}", 2, 1.234567)?;
+    ///     // turns into this:
+    ///     buffer.write_fmt(format_args!("{:.*}", 2, 1.234567))?;
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<()> {
@@ -1187,19 +1156,19 @@ pub trait Write {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::io::Write;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let mut buffer = File::create("foo.txt")?;
+    /// fn main() -> std::io::Result<()> {
+    ///     let mut buffer = File::create("foo.txt")?;
     ///
-    /// let reference = buffer.by_ref();
+    ///     let reference = buffer.by_ref();
     ///
-    /// // we can use reference just like our original buffer
-    /// reference.write_all(b"some bytes")?;
-    /// # Ok(())
-    /// # }
+    ///     // we can use reference just like our original buffer
+    ///     reference.write_all(b"some bytes")?;
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn by_ref(&mut self) -> &mut Self where Self: Sized { self }
@@ -1217,19 +1186,19 @@ pub trait Write {
 ///
 /// [file]: ../fs/struct.File.html
 ///
-/// ```
+/// ```no_run
 /// use std::io;
 /// use std::io::prelude::*;
 /// use std::fs::File;
 /// use std::io::SeekFrom;
 ///
-/// # fn foo() -> io::Result<()> {
-/// let mut f = File::open("foo.txt")?;
+/// fn main() -> io::Result<()> {
+///     let mut f = File::open("foo.txt")?;
 ///
-/// // move the cursor 42 bytes from the start of the file
-/// f.seek(SeekFrom::Start(42))?;
-/// # Ok(())
-/// # }
+///     // move the cursor 42 bytes from the start of the file
+///     f.seek(SeekFrom::Start(42))?;
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Seek {
@@ -1320,7 +1289,7 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>)
 ///
 /// A locked standard input implements `BufRead`:
 ///
-/// ```
+/// ```no_run
 /// use std::io;
 /// use std::io::prelude::*;
 ///
@@ -1342,21 +1311,21 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>)
 /// [`lines`]: #method.lines
 /// [`Read`]: trait.Read.html
 ///
-/// ```
+/// ```no_run
 /// use std::io::{self, BufReader};
 /// use std::io::prelude::*;
 /// use std::fs::File;
 ///
-/// # fn foo() -> io::Result<()> {
-/// let f = File::open("foo.txt")?;
-/// let f = BufReader::new(f);
+/// fn main() -> io::Result<()> {
+///     let f = File::open("foo.txt")?;
+///     let f = BufReader::new(f);
 ///
-/// for line in f.lines() {
-///     println!("{}", line.unwrap());
-/// }
+///     for line in f.lines() {
+///         println!("{}", line.unwrap());
+///     }
 ///
-/// # Ok(())
-/// # }
+///     Ok(())
+/// }
 /// ```
 ///
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1383,7 +1352,7 @@ pub trait BufRead: Read {
     ///
     /// A locked standard input implements `BufRead`:
     ///
-    /// ```
+    /// ```no_run
     /// use std::io;
     /// use std::io::prelude::*;
     ///
@@ -1437,8 +1406,6 @@ 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
@@ -1508,6 +1475,8 @@ pub trait BufRead: Read {
     /// error is encountered then `buf` may contain some bytes already read in
     /// the event that all data read so far was valid UTF-8.
     ///
+    /// [`read_until`]: #method.read_until
+    ///
     /// # Examples
     ///
     /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
@@ -1645,19 +1614,19 @@ impl<T, U> Chain<T, U> {
     ///
     /// # Examples
     ///
-    /// ```
-    /// # use std::io;
+    /// ```no_run
+    /// use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let mut foo_file = File::open("foo.txt")?;
-    /// let mut bar_file = File::open("bar.txt")?;
+    /// fn main() -> io::Result<()> {
+    ///     let mut foo_file = File::open("foo.txt")?;
+    ///     let mut bar_file = File::open("bar.txt")?;
     ///
-    /// let chain = foo_file.chain(bar_file);
-    /// let (foo_file, bar_file) = chain.into_inner();
-    /// # Ok(())
-    /// # }
+    ///     let chain = foo_file.chain(bar_file);
+    ///     let (foo_file, bar_file) = chain.into_inner();
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "more_io_inner_methods", since = "1.20.0")]
     pub fn into_inner(self) -> (T, U) {
@@ -1668,19 +1637,19 @@ impl<T, U> Chain<T, U> {
     ///
     /// # Examples
     ///
-    /// ```
-    /// # use std::io;
+    /// ```no_run
+    /// use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let mut foo_file = File::open("foo.txt")?;
-    /// let mut bar_file = File::open("bar.txt")?;
+    /// fn main() -> io::Result<()> {
+    ///     let mut foo_file = File::open("foo.txt")?;
+    ///     let mut bar_file = File::open("bar.txt")?;
     ///
-    /// let chain = foo_file.chain(bar_file);
-    /// let (foo_file, bar_file) = chain.get_ref();
-    /// # Ok(())
-    /// # }
+    ///     let chain = foo_file.chain(bar_file);
+    ///     let (foo_file, bar_file) = chain.get_ref();
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "more_io_inner_methods", since = "1.20.0")]
     pub fn get_ref(&self) -> (&T, &U) {
@@ -1695,19 +1664,19 @@ impl<T, U> Chain<T, U> {
     ///
     /// # Examples
     ///
-    /// ```
-    /// # use std::io;
+    /// ```no_run
+    /// use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let mut foo_file = File::open("foo.txt")?;
-    /// let mut bar_file = File::open("bar.txt")?;
+    /// fn main() -> io::Result<()> {
+    ///     let mut foo_file = File::open("foo.txt")?;
+    ///     let mut bar_file = File::open("bar.txt")?;
     ///
-    /// let mut chain = foo_file.chain(bar_file);
-    /// let (foo_file, bar_file) = chain.get_mut();
-    /// # Ok(())
-    /// # }
+    ///     let mut chain = foo_file.chain(bar_file);
+    ///     let (foo_file, bar_file) = chain.get_mut();
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "more_io_inner_methods", since = "1.20.0")]
     pub fn get_mut(&mut self) -> (&mut T, &mut U) {
@@ -1794,20 +1763,20 @@ impl<T> Take<T> {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let f = File::open("foo.txt")?;
+    /// fn main() -> io::Result<()> {
+    ///     let f = File::open("foo.txt")?;
     ///
-    /// // read at most five bytes
-    /// let handle = f.take(5);
+    ///     // read at most five bytes
+    ///     let handle = f.take(5);
     ///
-    /// println!("limit: {}", handle.limit());
-    /// # Ok(())
-    /// # }
+    ///     println!("limit: {}", handle.limit());
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn limit(&self) -> u64 { self.limit }
@@ -1819,24 +1788,23 @@ impl<T> Take<T> {
     ///
     /// # Examples
     ///
-    /// ```
-    /// #![feature(take_set_limit)]
+    /// ```no_run
     /// use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let f = File::open("foo.txt")?;
+    /// fn main() -> io::Result<()> {
+    ///     let f = File::open("foo.txt")?;
     ///
-    /// // read at most five bytes
-    /// let mut handle = f.take(5);
-    /// handle.set_limit(10);
+    ///     // read at most five bytes
+    ///     let mut handle = f.take(5);
+    ///     handle.set_limit(10);
     ///
-    /// assert_eq!(handle.limit(), 10);
-    /// # Ok(())
-    /// # }
+    ///     assert_eq!(handle.limit(), 10);
+    ///     Ok(())
+    /// }
     /// ```
-    #[unstable(feature = "take_set_limit", issue = "42781")]
+    #[stable(feature = "take_set_limit", since = "1.27.0")]
     pub fn set_limit(&mut self, limit: u64) {
         self.limit = limit;
     }
@@ -1845,21 +1813,21 @@ impl<T> Take<T> {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let mut file = File::open("foo.txt")?;
+    /// fn main() -> io::Result<()> {
+    ///     let mut file = File::open("foo.txt")?;
     ///
-    /// let mut buffer = [0; 5];
-    /// let mut handle = file.take(5);
-    /// handle.read(&mut buffer)?;
+    ///     let mut buffer = [0; 5];
+    ///     let mut handle = file.take(5);
+    ///     handle.read(&mut buffer)?;
     ///
-    /// let file = handle.into_inner();
-    /// # Ok(())
-    /// # }
+    ///     let file = handle.into_inner();
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "io_take_into_inner", since = "1.15.0")]
     pub fn into_inner(self) -> T {
@@ -1870,21 +1838,21 @@ impl<T> Take<T> {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let mut file = File::open("foo.txt")?;
+    /// fn main() -> io::Result<()> {
+    ///     let mut file = File::open("foo.txt")?;
     ///
-    /// let mut buffer = [0; 5];
-    /// let mut handle = file.take(5);
-    /// handle.read(&mut buffer)?;
+    ///     let mut buffer = [0; 5];
+    ///     let mut handle = file.take(5);
+    ///     handle.read(&mut buffer)?;
     ///
-    /// let file = handle.get_ref();
-    /// # Ok(())
-    /// # }
+    ///     let file = handle.get_ref();
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "more_io_inner_methods", since = "1.20.0")]
     pub fn get_ref(&self) -> &T {
@@ -1899,21 +1867,21 @@ impl<T> Take<T> {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let mut file = File::open("foo.txt")?;
+    /// fn main() -> io::Result<()> {
+    ///     let mut file = File::open("foo.txt")?;
     ///
-    /// let mut buffer = [0; 5];
-    /// let mut handle = file.take(5);
-    /// handle.read(&mut buffer)?;
+    ///     let mut buffer = [0; 5];
+    ///     let mut handle = file.take(5);
+    ///     handle.read(&mut buffer)?;
     ///
-    /// let file = handle.get_mut();
-    /// # Ok(())
-    /// # }
+    ///     let file = handle.get_mut();
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "more_io_inner_methods", since = "1.20.0")]
     pub fn get_mut(&mut self) -> &mut T {
@@ -1938,6 +1906,12 @@ impl<T: Read> Read for Take<T> {
     unsafe fn initializer(&self) -> Initializer {
         self.inner.initializer()
     }
+
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
+        let reservation_size = cmp::min(self.limit, 32) as usize;
+
+        read_to_end_with_reservation(self, buf, reservation_size)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1961,7 +1935,7 @@ impl<T: BufRead> BufRead for Take<T> {
     }
 }
 
-fn read_one_byte(reader: &mut Read) -> Option<Result<u8>> {
+fn read_one_byte(reader: &mut dyn Read) -> Option<Result<u8>> {
     let mut buf = [0];
     loop {
         return match reader.read(&mut buf) {
@@ -1994,95 +1968,6 @@ impl<R: Read> Iterator for Bytes<R> {
     }
 }
 
-/// An iterator over the `char`s of a reader.
-///
-/// This struct is generally created by calling [`chars`][chars] on a reader.
-/// Please see the documentation of `chars()` for more details.
-///
-/// [chars]: trait.Read.html#method.chars
-#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
-           issue = "27802")]
-#[derive(Debug)]
-pub struct Chars<R> {
-    inner: R,
-}
-
-/// An enumeration of possible errors that can be generated from the `Chars`
-/// adapter.
-#[derive(Debug)]
-#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
-           issue = "27802")]
-pub enum CharsError {
-    /// Variant representing that the underlying stream was read successfully
-    /// but it did not contain valid utf8 data.
-    NotUtf8,
-
-    /// Variant representing that an I/O error occurred.
-    Other(Error),
-}
-
-#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
-           issue = "27802")]
-impl<R: Read> Iterator for Chars<R> {
-    type Item = result::Result<char, CharsError>;
-
-    fn next(&mut self) -> Option<result::Result<char, CharsError>> {
-        let first_byte = match read_one_byte(&mut self.inner)? {
-            Ok(b) => b,
-            Err(e) => return Some(Err(CharsError::Other(e))),
-        };
-        let width = core_str::utf8_char_width(first_byte);
-        if width == 1 { return Some(Ok(first_byte as char)) }
-        if width == 0 { return Some(Err(CharsError::NotUtf8)) }
-        let mut buf = [first_byte, 0, 0, 0];
-        {
-            let mut start = 1;
-            while start < width {
-                match self.inner.read(&mut buf[start..width]) {
-                    Ok(0) => return Some(Err(CharsError::NotUtf8)),
-                    Ok(n) => start += n,
-                    Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
-                    Err(e) => return Some(Err(CharsError::Other(e))),
-                }
-            }
-        }
-        Some(match str::from_utf8(&buf[..width]).ok() {
-            Some(s) => Ok(s.chars().next().unwrap()),
-            None => Err(CharsError::NotUtf8),
-        })
-    }
-}
-
-#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
-           issue = "27802")]
-impl std_error::Error for CharsError {
-    fn description(&self) -> &str {
-        match *self {
-            CharsError::NotUtf8 => "invalid utf8 encoding",
-            CharsError::Other(ref e) => std_error::Error::description(e),
-        }
-    }
-    fn cause(&self) -> Option<&std_error::Error> {
-        match *self {
-            CharsError::NotUtf8 => None,
-            CharsError::Other(ref e) => e.cause(),
-        }
-    }
-}
-
-#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
-           issue = "27802")]
-impl fmt::Display for CharsError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            CharsError::NotUtf8 => {
-                "byte stream did not contain valid utf8".fmt(f)
-            }
-            CharsError::Other(ref e) => e.fmt(f),
-        }
-    }
-}
-
 /// An iterator over the contents of an instance of `BufRead` split on a
 /// particular byte.
 ///
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index 831688bb73d..1f256f518c7 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -17,11 +17,11 @@ use io::{self, Initializer, BufReader, LineWriter};
 use sync::{Arc, Mutex, MutexGuard};
 use sys::stdio;
 use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
-use thread::{LocalKey, LocalKeyState};
+use thread::LocalKey;
 
 /// Stdout used by print! and println! macros
 thread_local! {
-    static LOCAL_STDOUT: RefCell<Option<Box<Write + Send>>> = {
+    static LOCAL_STDOUT: RefCell<Option<Box<dyn Write + Send>>> = {
         RefCell::new(None)
     }
 }
@@ -171,38 +171,39 @@ pub struct StdinLock<'a> {
 ///
 /// Using implicit synchronization:
 ///
-/// ```
+/// ```no_run
 /// use std::io::{self, Read};
 ///
-/// # fn foo() -> io::Result<String> {
-/// let mut buffer = String::new();
-/// io::stdin().read_to_string(&mut buffer)?;
-/// # Ok(buffer)
-/// # }
+/// fn main() -> io::Result<()> {
+///     let mut buffer = String::new();
+///     io::stdin().read_to_string(&mut buffer)?;
+///     Ok(())
+/// }
 /// ```
 ///
 /// Using explicit synchronization:
 ///
-/// ```
+/// ```no_run
 /// use std::io::{self, Read};
 ///
-/// # fn foo() -> io::Result<String> {
-/// let mut buffer = String::new();
-/// let stdin = io::stdin();
-/// let mut handle = stdin.lock();
+/// fn main() -> io::Result<()> {
+///     let mut buffer = String::new();
+///     let stdin = io::stdin();
+///     let mut handle = stdin.lock();
 ///
-/// handle.read_to_string(&mut buffer)?;
-/// # Ok(buffer)
-/// # }
+///     handle.read_to_string(&mut buffer)?;
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stdin() -> Stdin {
-    static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = Lazy::new(stdin_init);
+    static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = unsafe { Lazy::new(stdin_init) };
     return Stdin {
         inner: INSTANCE.get().expect("cannot access stdin during shutdown"),
     };
 
     fn stdin_init() -> Arc<Mutex<BufReader<Maybe<StdinRaw>>>> {
+        // This must not reentrantly access `INSTANCE`
         let stdin = match stdin_raw() {
             Ok(stdin) => Maybe::Real(stdin),
             _ => Maybe::Fake
@@ -225,17 +226,17 @@ impl Stdin {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::io::{self, Read};
     ///
-    /// # fn foo() -> io::Result<String> {
-    /// let mut buffer = String::new();
-    /// let stdin = io::stdin();
-    /// let mut handle = stdin.lock();
+    /// fn main() -> io::Result<()> {
+    ///     let mut buffer = String::new();
+    ///     let stdin = io::stdin();
+    ///     let mut handle = stdin.lock();
     ///
-    /// handle.read_to_string(&mut buffer)?;
-    /// # Ok(buffer)
-    /// # }
+    ///     handle.read_to_string(&mut buffer)?;
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn lock(&self) -> StdinLock {
@@ -369,39 +370,40 @@ pub struct StdoutLock<'a> {
 ///
 /// Using implicit synchronization:
 ///
-/// ```
+/// ```no_run
 /// use std::io::{self, Write};
 ///
-/// # fn foo() -> io::Result<()> {
-/// io::stdout().write(b"hello world")?;
+/// fn main() -> io::Result<()> {
+///     io::stdout().write(b"hello world")?;
 ///
-/// # Ok(())
-/// # }
+///     Ok(())
+/// }
 /// ```
 ///
 /// Using explicit synchronization:
 ///
-/// ```
+/// ```no_run
 /// use std::io::{self, Write};
 ///
-/// # fn foo() -> io::Result<()> {
-/// let stdout = io::stdout();
-/// let mut handle = stdout.lock();
+/// fn main() -> io::Result<()> {
+///     let stdout = io::stdout();
+///     let mut handle = stdout.lock();
 ///
-/// handle.write(b"hello world")?;
+///     handle.write(b"hello world")?;
 ///
-/// # Ok(())
-/// # }
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stdout() -> Stdout {
     static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>>
-        = Lazy::new(stdout_init);
+        = unsafe { Lazy::new(stdout_init) };
     return Stdout {
         inner: INSTANCE.get().expect("cannot access stdout during shutdown"),
     };
 
     fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> {
+        // This must not reentrantly access `INSTANCE`
         let stdout = match stdout_raw() {
             Ok(stdout) => Maybe::Real(stdout),
             _ => Maybe::Fake,
@@ -419,17 +421,17 @@ impl Stdout {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::io::{self, Write};
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let stdout = io::stdout();
-    /// let mut handle = stdout.lock();
+    /// fn main() -> io::Result<()> {
+    ///     let stdout = io::stdout();
+    ///     let mut handle = stdout.lock();
     ///
-    /// handle.write(b"hello world")?;
+    ///     handle.write(b"hello world")?;
     ///
-    /// # Ok(())
-    /// # }
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn lock(&self) -> StdoutLock {
@@ -505,38 +507,40 @@ pub struct StderrLock<'a> {
 ///
 /// Using implicit synchronization:
 ///
-/// ```
+/// ```no_run
 /// use std::io::{self, Write};
 ///
-/// # fn foo() -> io::Result<()> {
-/// io::stderr().write(b"hello world")?;
+/// fn main() -> io::Result<()> {
+///     io::stderr().write(b"hello world")?;
 ///
-/// # Ok(())
-/// # }
+///     Ok(())
+/// }
 /// ```
 ///
 /// Using explicit synchronization:
 ///
-/// ```
+/// ```no_run
 /// use std::io::{self, Write};
 ///
-/// # fn foo() -> io::Result<()> {
-/// let stderr = io::stderr();
-/// let mut handle = stderr.lock();
+/// fn main() -> io::Result<()> {
+///     let stderr = io::stderr();
+///     let mut handle = stderr.lock();
 ///
-/// handle.write(b"hello world")?;
+///     handle.write(b"hello world")?;
 ///
-/// # Ok(())
-/// # }
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stderr() -> Stderr {
-    static INSTANCE: Lazy<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> = Lazy::new(stderr_init);
+    static INSTANCE: Lazy<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> =
+        unsafe { Lazy::new(stderr_init) };
     return Stderr {
         inner: INSTANCE.get().expect("cannot access stderr during shutdown"),
     };
 
     fn stderr_init() -> Arc<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> {
+        // This must not reentrantly access `INSTANCE`
         let stderr = match stderr_raw() {
             Ok(stderr) => Maybe::Real(stderr),
             _ => Maybe::Fake,
@@ -624,7 +628,7 @@ impl<'a> fmt::Debug for StderrLock<'a> {
                      with a more general mechanism",
            issue = "0")]
 #[doc(hidden)]
-pub fn set_panic(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> {
+pub fn set_panic(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write + Send>> {
     use panicking::LOCAL_STDERR;
     use mem;
     LOCAL_STDERR.with(move |slot| {
@@ -648,7 +652,7 @@ pub fn set_panic(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> {
                      with a more general mechanism",
            issue = "0")]
 #[doc(hidden)]
-pub fn set_print(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> {
+pub fn set_print(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write + Send>> {
     use mem;
     LOCAL_STDOUT.with(move |slot| {
         mem::replace(&mut *slot.borrow_mut(), sink)
@@ -663,29 +667,31 @@ pub fn set_print(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> {
 ///
 /// This function is used to print error messages, so it takes extra
 /// care to avoid causing a panic when `local_stream` is unusable.
-/// For instance, if the TLS key for the local stream is uninitialized
-/// or already destroyed, or if the local stream is locked by another
+/// For instance, if the TLS key for the local stream is
+/// already destroyed, or if the local stream is locked by another
 /// thread, it will just fall back to the global stream.
 ///
 /// However, if the actual I/O causes an error, this function does panic.
-fn print_to<T>(args: fmt::Arguments,
-               local_s: &'static LocalKey<RefCell<Option<Box<Write+Send>>>>,
-               global_s: fn() -> T,
-               label: &str) where T: Write {
-    let result = match local_s.state() {
-        LocalKeyState::Uninitialized |
-        LocalKeyState::Destroyed => global_s().write_fmt(args),
-        LocalKeyState::Valid => {
-            local_s.with(|s| {
-                if let Ok(mut borrowed) = s.try_borrow_mut() {
-                    if let Some(w) = borrowed.as_mut() {
-                        return w.write_fmt(args);
-                    }
-                }
-                global_s().write_fmt(args)
-            })
+fn print_to<T>(
+    args: fmt::Arguments,
+    local_s: &'static LocalKey<RefCell<Option<Box<dyn Write+Send>>>>,
+    global_s: fn() -> T,
+    label: &str,
+)
+where
+    T: Write,
+{
+    let result = local_s.try_with(|s| {
+        if let Ok(mut borrowed) = s.try_borrow_mut() {
+            if let Some(w) = borrowed.as_mut() {
+                return w.write_fmt(args);
+            }
         }
-    };
+        global_s().write_fmt(args)
+    }).unwrap_or_else(|_| {
+        global_s().write_fmt(args)
+    });
+
     if let Err(e) = result {
         panic!("failed printing to {}: {}", label, e);
     }
@@ -710,10 +716,32 @@ pub fn _eprint(args: fmt::Arguments) {
 
 #[cfg(test)]
 mod tests {
+    use panic::{UnwindSafe, RefUnwindSafe};
     use thread;
     use super::*;
 
     #[test]
+    fn stdout_unwind_safe() {
+        assert_unwind_safe::<Stdout>();
+    }
+    #[test]
+    fn stdoutlock_unwind_safe() {
+        assert_unwind_safe::<StdoutLock>();
+        assert_unwind_safe::<StdoutLock<'static>>();
+    }
+    #[test]
+    fn stderr_unwind_safe() {
+        assert_unwind_safe::<Stderr>();
+    }
+    #[test]
+    fn stderrlock_unwind_safe() {
+        assert_unwind_safe::<StderrLock>();
+        assert_unwind_safe::<StderrLock<'static>>();
+    }
+
+    fn assert_unwind_safe<T: UnwindSafe + RefUnwindSafe>() {}
+
+    #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
     fn panic_doesnt_poison() {
         thread::spawn(|| {
diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs
index 45d281ee34a..33f741dbc38 100644
--- a/src/libstd/io/util.rs
+++ b/src/libstd/io/util.rs
@@ -34,16 +34,15 @@ use mem;
 /// ```
 /// use std::io;
 ///
-/// # fn foo() -> io::Result<()> {
-/// let mut reader: &[u8] = b"hello";
-/// let mut writer: Vec<u8> = vec![];
+/// fn main() -> io::Result<()> {
+///     let mut reader: &[u8] = b"hello";
+///     let mut writer: Vec<u8> = vec![];
 ///
-/// io::copy(&mut reader, &mut writer)?;
+///     io::copy(&mut reader, &mut writer)?;
 ///
-/// assert_eq!(&b"hello"[..], &writer[..]);
-/// # Ok(())
-/// # }
-/// # foo().unwrap();
+///     assert_eq!(&b"hello"[..], &writer[..]);
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64>
@@ -224,7 +223,7 @@ mod tests {
         assert_eq!(copy(&mut r, &mut w).unwrap(), 4);
 
         let mut r = repeat(0).take(1 << 17);
-        assert_eq!(copy(&mut r as &mut Read, &mut w as &mut Write).unwrap(), 1 << 17);
+        assert_eq!(copy(&mut r as &mut dyn Read, &mut w as &mut dyn Write).unwrap(), 1 << 17);
     }
 
     #[test]
diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs
new file mode 100644
index 00000000000..4f6bda6cfe3
--- /dev/null
+++ b/src/libstd/keyword_docs.rs
@@ -0,0 +1,58 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[doc(keyword = "fn")]
+//
+/// The `fn` keyword.
+///
+/// The `fn` keyword is used to declare a function.
+///
+/// Example:
+///
+/// ```rust
+/// fn some_function() {
+///     // code goes in here
+/// }
+/// ```
+///
+/// For more information about functions, take a look at the [Rust Book][book].
+///
+/// [book]: https://doc.rust-lang.org/book/second-edition/ch03-03-how-functions-work.html
+mod fn_keyword { }
+
+#[doc(keyword = "let")]
+//
+/// The `let` keyword.
+///
+/// The `let` keyword is used to declare a variable.
+///
+/// Example:
+///
+/// ```rust
+/// # #![allow(unused_assignments)]
+/// let x = 3; // We create a variable named `x` with the value `3`.
+/// ```
+///
+/// By default, all variables are **not** mutable. If you want a mutable variable,
+/// you'll have to use the `mut` keyword.
+///
+/// Example:
+///
+/// ```rust
+/// # #![allow(unused_assignments)]
+/// let mut x = 3; // We create a mutable variable named `x` with the value `3`.
+///
+/// x += 4; // `x` is now equal to `7`.
+/// ```
+///
+/// For more information about the `let` keyword, take a look at the [Rust Book][book].
+///
+/// [book]: https://doc.rust-lang.org/book/second-edition/ch03-01-variables-and-mutability.html
+mod let_keyword { }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 880b46fa507..b1d45b7f260 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -44,10 +44,10 @@
 //!
 //! Once you are familiar with the contents of the standard library you may
 //! begin to find the verbosity of the prose distracting. At this stage in your
-//! development you may want to press the **[-]** button near the top of the
+//! development you may want to press the `[-]` button near the top of the
 //! page to collapse it into a more skimmable view.
 //!
-//! While you are looking at that **[-]** button also notice the **[src]**
+//! While you are looking at that `[-]` button also notice the `[src]`
 //! button. Rust's API documentation comes with the source code and you are
 //! encouraged to read it. The standard library source is generally high
 //! quality and a peek behind the curtains is often enlightening.
@@ -227,24 +227,22 @@
 // Tell the compiler to link to either panic_abort or panic_unwind
 #![needs_panic_runtime]
 
-// Turn warnings into errors, but only after stage0, where it can be useful for
-// code to emit warnings during language transitions
-#![cfg_attr(not(stage0), deny(warnings))]
-
 // std may use features in a platform-specific way
 #![allow(unused_features)]
 
 // std is implemented with unstable features, many of which are internal
 // compiler details that will never be stable
+#![cfg_attr(test, feature(test, update_panic_count))]
 #![feature(alloc)]
-#![feature(allocator_api)]
+#![feature(alloc_error_handler)]
 #![feature(alloc_system)]
+#![feature(allocator_api)]
 #![feature(allocator_internals)]
 #![feature(allow_internal_unsafe)]
 #![feature(allow_internal_unstable)]
 #![feature(align_offset)]
+#![feature(arbitrary_self_types)]
 #![feature(array_error_internals)]
-#![feature(ascii_ctype)]
 #![feature(asm)]
 #![feature(attr_literals)]
 #![feature(box_syntax)]
@@ -252,79 +250,70 @@
 #![feature(cfg_target_thread_local)]
 #![feature(cfg_target_vendor)]
 #![feature(char_error_internals)]
-#![feature(char_internals)]
-#![feature(collections_range)]
 #![feature(compiler_builtins_lib)]
 #![feature(const_fn)]
-#![feature(convert_id)]
 #![feature(core_float)]
+#![feature(const_int_ops)]
+#![feature(const_ip)]
+#![feature(convert_id)]
 #![feature(core_intrinsics)]
 #![feature(dropck_eyepatch)]
 #![feature(exact_size_is_empty)]
-#![feature(fs_read_write)]
+#![feature(external_doc)]
 #![feature(fixed_size_array)]
-#![feature(float_from_str_radix)]
 #![feature(fn_traits)]
 #![feature(fnbox)]
-#![feature(fused)]
-#![feature(generic_param_attrs)]
-#![feature(hashmap_hasher)]
-#![feature(heap_api)]
-#![feature(i128)]
-#![feature(i128_type)]
-#![feature(inclusive_range)]
+#![feature(futures_api)]
+#![feature(generator_trait)]
+#![feature(hashmap_internals)]
 #![feature(int_error_internals)]
 #![feature(integer_atomics)]
-#![feature(into_cow)]
 #![feature(lang_items)]
 #![feature(libc)]
 #![feature(link_args)]
 #![feature(linkage)]
-#![feature(macro_reexport)]
 #![feature(macro_vis_matcher)]
 #![feature(needs_panic_runtime)]
 #![feature(never_type)]
-#![feature(num_bits_bytes)]
-#![feature(old_wrapping)]
+#![cfg_attr(not(stage0), feature(nll))]
+#![feature(exhaustive_patterns)]
 #![feature(on_unimplemented)]
-#![feature(oom)]
 #![feature(optin_builtin_traits)]
+#![feature(panic_internals)]
 #![feature(panic_unwind)]
-#![feature(peek)]
-#![feature(placement_in_syntax)]
-#![feature(placement_new_protocol)]
+#![feature(pin)]
 #![feature(prelude_import)]
-#![feature(rand)]
+#![feature(ptr_internals)]
 #![feature(raw)]
-#![feature(repr_align)]
 #![feature(rustc_attrs)]
-#![feature(shared)]
-#![feature(sip_hash_13)]
-#![feature(slice_bytes)]
+#![feature(rustc_const_unstable)]
+#![feature(std_internals)]
+#![feature(stdsimd)]
+#![feature(shrink_to)]
 #![feature(slice_concat_ext)]
 #![feature(slice_internals)]
 #![feature(slice_patterns)]
 #![feature(staged_api)]
 #![feature(stmt_expr_attributes)]
-#![feature(str_char)]
 #![feature(str_internals)]
-#![feature(str_utf16)]
-#![feature(termination_trait)]
-#![feature(test, rustc_private)]
+#![feature(rustc_private)]
 #![feature(thread_local)]
 #![feature(toowned_clone_into)]
 #![feature(try_from)]
+#![feature(try_reserve)]
 #![feature(unboxed_closures)]
-#![feature(unicode)]
-#![feature(unique)]
 #![feature(untagged_unions)]
 #![feature(unwind_attributes)]
-#![feature(vec_push_all)]
+#![cfg_attr(stage0, feature(use_extern_macros))]
 #![feature(doc_cfg)]
 #![feature(doc_masked)]
 #![feature(doc_spotlight)]
-#![cfg_attr(test, feature(update_panic_count))]
 #![cfg_attr(windows, feature(used))]
+#![feature(doc_alias)]
+#![feature(doc_keyword)]
+#![feature(panic_info_message)]
+#![feature(panic_implementation)]
+#![feature(non_exhaustive)]
 
 #![default_lib_allocator]
 
@@ -334,11 +323,8 @@
 // `force_alloc_system` is *only* intended as a workaround for local rebuilds
 // with a rustc without jemalloc.
 // FIXME(#44236) shouldn't need MSVC logic
-#![cfg_attr(all(not(target_env = "msvc"),
-                any(stage0, feature = "force_alloc_system")),
-            feature(global_allocator))]
 #[cfg(all(not(target_env = "msvc"),
-          any(stage0, feature = "force_alloc_system")))]
+          any(all(stage0, not(test)), feature = "force_alloc_system")))]
 #[global_allocator]
 static ALLOC: alloc_system::System = alloc_system::System;
 
@@ -352,18 +338,16 @@ use prelude::v1::*;
 #[cfg(test)] extern crate test;
 #[cfg(test)] extern crate rand;
 
-// We want to re-export a few macros from core but libcore has already been
-// imported by the compiler (via our #[no_std] attribute) In this case we just
-// add a new crate name so we can attach the re-exports to it.
-#[macro_reexport(assert, assert_eq, assert_ne, debug_assert, debug_assert_eq,
-                 debug_assert_ne, unreachable, unimplemented, write, writeln, try)]
-extern crate core as __core;
+// Re-export a few macros from core
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use core::{assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne};
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use core::{unreachable, unimplemented, write, writeln, try};
 
+#[allow(unused_imports)] // macros from `alloc` are not used on all platforms
 #[macro_use]
-#[macro_reexport(vec, format)]
-extern crate alloc;
+extern crate alloc as alloc_crate;
 extern crate alloc_system;
-extern crate std_unicode;
 #[doc(masked)]
 extern crate libc;
 
@@ -372,14 +356,10 @@ extern crate libc;
 #[allow(unused_extern_crates)]
 extern crate unwind;
 
-// compiler-rt intrinsics
-#[doc(masked)]
-extern crate compiler_builtins;
-
 // During testing, this crate is not actually the "real" std library, but rather
 // it links to the real std library, which was compiled from this same source
 // code. So any lang items std defines are conditionally excluded (or else they
-// wolud generate duplicate lang item errors), and any globals it defines are
+// would generate duplicate lang item errors), and any globals it defines are
 // _not_ the globals used by "real" std. So this import, defined only during
 // testing gives test-std access to real-std lang items and globals. See #2912
 #[cfg(test)] extern crate std as realstd;
@@ -434,7 +414,7 @@ pub use core::i16;
 pub use core::i32;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::i64;
-#[unstable(feature = "i128", issue = "35118")]
+#[stable(feature = "i128", since = "1.26.0")]
 pub use core::i128;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::usize;
@@ -447,25 +427,29 @@ pub use core::u32;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::u64;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::boxed;
+pub use alloc_crate::boxed;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use alloc_crate::rc;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::rc;
+pub use alloc_crate::borrow;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::borrow;
+pub use alloc_crate::fmt;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::fmt;
+pub use alloc_crate::format;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::slice;
+pub use alloc_crate::slice;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::str;
+pub use alloc_crate::str;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::string;
+pub use alloc_crate::string;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::vec;
+pub use alloc_crate::vec;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use std_unicode::char;
-#[unstable(feature = "i128", issue = "35118")]
+pub use core::char;
+#[stable(feature = "i128", since = "1.26.0")]
 pub use core::u128;
+#[stable(feature = "core_hint", since = "1.27.0")]
+pub use core::hint;
 
 pub mod f32;
 pub mod f64;
@@ -487,13 +471,30 @@ pub mod path;
 pub mod process;
 pub mod sync;
 pub mod time;
-pub mod heap;
+
+#[unstable(feature = "futures_api",
+           reason = "futures in libcore are unstable",
+           issue = "50547")]
+pub mod task {
+    //! Types and Traits for working with asynchronous tasks.
+    #[doc(inline)]
+    pub use core::task::*;
+    #[doc(inline)]
+    pub use alloc_crate::task::*;
+}
+
+#[unstable(feature = "futures_api",
+           reason = "futures in libcore are unstable",
+           issue = "50547")]
+pub mod future;
 
 // Platform-abstraction modules
 #[macro_use]
 mod sys_common;
 mod sys;
 
+pub mod alloc;
+
 // Private support modules
 mod panicking;
 mod memchr;
@@ -501,13 +502,38 @@ mod memchr;
 // The runtime entry point and a few unstable public functions used by the
 // compiler
 pub mod rt;
-// The trait to support returning arbitrary types in the main function
-mod termination;
 
-#[unstable(feature = "termination_trait", issue = "43301")]
-pub use self::termination::Termination;
+// Pull in the the `stdsimd` crate directly into libstd. This is the same as
+// libcore's arch/simd modules where the source of truth here is in a different
+// repository, but we pull things in here manually to get it into libstd.
+//
+// Note that the #[cfg] here is intended to do two things. First it allows us to
+// change the rustc implementation of intrinsics in stage0 by not compiling simd
+// intrinsics in stage0. Next it doesn't compile anything in test mode as
+// stdsimd has tons of its own tests which we don't want to run.
+#[path = "../stdsimd/stdsimd/mod.rs"]
+#[allow(missing_debug_implementations, missing_docs, dead_code)]
+#[unstable(feature = "stdsimd", issue = "48556")]
+#[cfg(all(not(stage0), not(test)))]
+mod stdsimd;
+
+// A "fake" module needed by the `stdsimd` module to compile, not actually
+// exported though.
+#[cfg(not(stage0))]
+mod coresimd {
+    pub use core::arch;
+}
+
+#[stable(feature = "simd_arch", since = "1.27.0")]
+#[cfg(all(not(stage0), not(test)))]
+pub use stdsimd::arch;
 
 // 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.
 include!("primitive_docs.rs");
+
+// Include a number of private modules that exist solely to provide
+// the rustdoc documentation for the existing keywords. Using `include!`
+// because rustdoc only looks for these modules at the crate level.
+include!("keyword_docs.rs");
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index f058b1caef5..f15494c5fd7 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -38,10 +38,13 @@
 /// The multi-argument form of this macro panics with a string and has the
 /// [`format!`] syntax for building a string.
 ///
+/// See also the macro [`compile_error!`], for raising errors during compilation.
+///
 /// [runwrap]: ../std/result/enum.Result.html#method.unwrap
 /// [`Option`]: ../std/option/enum.Option.html#method.unwrap
 /// [`Result`]: ../std/result/enum.Result.html
 /// [`format!`]: ../std/macro.format.html
+/// [`compile_error!`]: ../std/macro.compile_error.html
 /// [book]: ../book/second-edition/ch09-01-unrecoverable-errors-with-panic.html
 ///
 /// # Current implementation
@@ -68,6 +71,9 @@ macro_rules! panic {
     ($msg:expr) => ({
         $crate::rt::begin_panic($msg, &(file!(), line!(), __rust_unstable_column!()))
     });
+    ($msg:expr,) => ({
+        panic!($msg)
+    });
     ($fmt:expr, $($arg:tt)+) => ({
         $crate::rt::begin_panic_fmt(&format_args!($fmt, $($arg)+),
                                     &(file!(), line!(), __rust_unstable_column!()))
@@ -147,10 +153,12 @@ macro_rules! print {
 /// ```
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow_internal_unstable]
 macro_rules! println {
     () => (print!("\n"));
-    ($fmt:expr) => (print!(concat!($fmt, "\n")));
-    ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
+    ($($arg:tt)*) => ({
+        $crate::io::_print(format_args_nl!($($arg)*));
+    })
 }
 
 /// Macro for printing to the standard error.
@@ -204,10 +212,34 @@ macro_rules! eprint {
 /// ```
 #[macro_export]
 #[stable(feature = "eprint", since = "1.19.0")]
+#[allow_internal_unstable]
 macro_rules! eprintln {
     () => (eprint!("\n"));
-    ($fmt:expr) => (eprint!(concat!($fmt, "\n")));
-    ($fmt:expr, $($arg:tt)*) => (eprint!(concat!($fmt, "\n"), $($arg)*));
+    ($($arg:tt)*) => ({
+        $crate::io::_eprint(format_args_nl!($($arg)*));
+    })
+}
+
+#[macro_export]
+#[unstable(feature = "await_macro", issue = "50547")]
+#[allow_internal_unstable]
+#[allow_internal_unsafe]
+macro_rules! await {
+    ($e:expr) => { {
+        let mut pinned = $e;
+        loop {
+            if let $crate::task::Poll::Ready(x) =
+                $crate::future::poll_in_task_cx(unsafe {
+                    $crate::mem::PinMut::new_unchecked(&mut pinned)
+                })
+            {
+                break x;
+            }
+            // FIXME(cramertj) prior to stabilizing await, we have to ensure that this
+            // can't be used to create a generator on stable via `|| await!()`.
+            yield
+        }
+    } }
 }
 
 /// A macro to select an event from a number of receivers.
@@ -278,18 +310,21 @@ macro_rules! assert_approx_eq {
 /// macro, but are documented here. Their implementations can be found hardcoded
 /// into libsyntax itself.
 #[cfg(dox)]
-pub mod builtin {
+mod builtin {
 
     /// Unconditionally causes compilation to fail with the given error message when encountered.
     ///
     /// This macro should be used when a crate uses a conditional compilation strategy to provide
-    /// better error messages for erroneous conditions.
+    /// better error messages for erroneous conditions. It's the compiler-level form of [`panic!`],
+    /// which emits an error at *runtime*, rather than during compilation.
     ///
     /// # Examples
     ///
     /// Two such examples are macros and `#[cfg]` environments.
     ///
-    /// Emit better compiler error if a macro is passed invalid values.
+    /// Emit better compiler error if a macro is passed invalid values. Without the final branch,
+    /// the compiler would still emit an error, but the error's message would not mention the two
+    /// valid values.
     ///
     /// ```compile_fail
     /// macro_rules! give_me_foo_or_bar {
@@ -310,9 +345,14 @@ pub mod builtin {
     /// #[cfg(not(any(feature = "foo", feature = "bar")))]
     /// compile_error!("Either feature \"foo\" or \"bar\" must be enabled for this crate.")
     /// ```
+    ///
+    /// [`panic!`]: ../std/macro.panic.html
     #[stable(feature = "compile_error_macro", since = "1.20.0")]
-    #[macro_export]
-    macro_rules! compile_error { ($msg:expr) => ({ /* compiler built-in */ }) }
+    #[rustc_doc_only_macro]
+    macro_rules! compile_error {
+        ($msg:expr) => ({ /* compiler built-in */ });
+        ($msg:expr,) => ({ /* compiler built-in */ });
+    }
 
     /// The core macro for formatted string creation & output.
     ///
@@ -329,6 +369,18 @@ pub mod builtin {
     /// proxied through this one.  `format_args!`, unlike its derived macros, avoids
     /// heap allocations.
     ///
+    /// You can use the [`fmt::Arguments`] value that `format_args!` returns
+    /// in `Debug` and `Display` contexts as seen below. The example also shows
+    /// that `Debug` and `Display` format to the same thing: the interpolated
+    /// format string in `format_args!`.
+    ///
+    /// ```rust
+    /// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2));
+    /// let display = format!("{}", format_args!("{} foo {:?}", 1, 2));
+    /// assert_eq!("1 foo 2", display);
+    /// assert_eq!(display, debug);
+    /// ```
+    ///
     /// For more information, see the documentation in [`std::fmt`].
     ///
     /// [`Display`]: ../std/fmt/trait.Display.html
@@ -346,10 +398,9 @@ pub mod builtin {
     ///
     /// let s = fmt::format(format_args!("hello {}", "world"));
     /// assert_eq!(s, format!("hello {}", "world"));
-    ///
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[macro_export]
+    #[rustc_doc_only_macro]
     macro_rules! format_args {
         ($fmt:expr) => ({ /* compiler built-in */ });
         ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ });
@@ -361,7 +412,7 @@ pub mod builtin {
     /// compile time, yielding an expression of type `&'static str`.
     ///
     /// If the environment variable is not defined, then a compilation error
-    /// will be emitted.  To not emit a compile error, use the [`option_env!`]
+    /// will be emitted. To not emit a compile error, use the [`option_env!`]
     /// macro instead.
     ///
     /// [`option_env!`]: ../std/macro.option_env.html
@@ -372,8 +423,22 @@ pub mod builtin {
     /// let path: &'static str = env!("PATH");
     /// println!("the $PATH variable at the time of compiling was: {}", path);
     /// ```
+    ///
+    /// You can customize the error message by passing a string as the second
+    /// parameter:
+    ///
+    /// ```compile_fail
+    /// let doc: &'static str = env!("documentation", "what's that?!");
+    /// ```
+    ///
+    /// If the `documentation` environment variable is not defined, you'll get
+    /// the following error:
+    ///
+    /// ```text
+    /// error: what's that?!
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[macro_export]
+    #[rustc_doc_only_macro]
     macro_rules! env {
         ($name:expr) => ({ /* compiler built-in */ });
         ($name:expr,) => ({ /* compiler built-in */ });
@@ -399,8 +464,11 @@ pub mod builtin {
     /// println!("the secret key might be: {:?}", key);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[macro_export]
-    macro_rules! option_env { ($name:expr) => ({ /* compiler built-in */ }) }
+    #[rustc_doc_only_macro]
+    macro_rules! option_env {
+        ($name:expr) => ({ /* compiler built-in */ });
+        ($name:expr,) => ({ /* compiler built-in */ });
+    }
 
     /// Concatenate identifiers into one identifier.
     ///
@@ -427,10 +495,10 @@ pub mod builtin {
     /// # }
     /// ```
     #[unstable(feature = "concat_idents_macro", issue = "29599")]
-    #[macro_export]
+    #[rustc_doc_only_macro]
     macro_rules! concat_idents {
-        ($($e:ident),*) => ({ /* compiler built-in */ });
-        ($($e:ident,)*) => ({ /* compiler built-in */ });
+        ($($e:ident),+) => ({ /* compiler built-in */ });
+        ($($e:ident,)+) => ({ /* compiler built-in */ });
     }
 
     /// Concatenates literals into a static string slice.
@@ -449,7 +517,7 @@ pub mod builtin {
     /// assert_eq!(s, "test10btrue");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[macro_export]
+    #[rustc_doc_only_macro]
     macro_rules! concat {
         ($($e:expr),*) => ({ /* compiler built-in */ });
         ($($e:expr,)*) => ({ /* compiler built-in */ });
@@ -463,7 +531,7 @@ pub mod builtin {
     /// The expanded expression has type `u32` and is 1-based, so the first line
     /// in each file evaluates to 1, the second to 2, etc. This is consistent
     /// with error messages by common compilers or popular editors.
-    /// The returned line is not the invocation of the `line!` macro itself,
+    /// The returned line is *not necessarily* the line of the `line!` invocation itself,
     /// but rather the first macro invocation leading up to the invocation
     /// of the `line!` macro.
     ///
@@ -477,7 +545,7 @@ pub mod builtin {
     /// println!("defined on line: {}", current_line);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[macro_export]
+    #[rustc_doc_only_macro]
     macro_rules! line { () => ({ /* compiler built-in */ }) }
 
     /// A macro which expands to the column number on which it was invoked.
@@ -488,7 +556,7 @@ pub mod builtin {
     /// The expanded expression has type `u32` and is 1-based, so the first column
     /// in each line evaluates to 1, the second to 2, etc. This is consistent
     /// with error messages by common compilers or popular editors.
-    /// The returned column is not the invocation of the `column!` macro itself,
+    /// The returned column is *not necessarily* the line of the `column!` invocation itself,
     /// but rather the first macro invocation leading up to the invocation
     /// of the `column!` macro.
     ///
@@ -502,7 +570,7 @@ pub mod builtin {
     /// println!("defined on column: {}", current_col);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[macro_export]
+    #[rustc_doc_only_macro]
     macro_rules! column { () => ({ /* compiler built-in */ }) }
 
     /// A macro which expands to the file name from which it was invoked.
@@ -526,7 +594,7 @@ pub mod builtin {
     /// println!("defined in file: {}", this_file);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[macro_export]
+    #[rustc_doc_only_macro]
     macro_rules! file { () => ({ /* compiler built-in */ }) }
 
     /// A macro which stringifies its arguments.
@@ -545,7 +613,7 @@ pub mod builtin {
     /// assert_eq!(one_plus_one, "1 + 1");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[macro_export]
+    #[rustc_doc_only_macro]
     macro_rules! stringify { ($($t:tt)*) => ({ /* compiler built-in */ }) }
 
     /// Includes a utf8-encoded file as a string.
@@ -579,8 +647,11 @@ pub mod builtin {
     ///
     /// Compiling 'main.rs' and running the resulting binary will print "adiós".
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[macro_export]
-    macro_rules! include_str { ($file:expr) => ({ /* compiler built-in */ }) }
+    #[rustc_doc_only_macro]
+    macro_rules! include_str {
+        ($file:expr) => ({ /* compiler built-in */ });
+        ($file:expr,) => ({ /* compiler built-in */ });
+    }
 
     /// Includes a file as a reference to a byte array.
     ///
@@ -613,8 +684,11 @@ pub mod builtin {
     ///
     /// Compiling 'main.rs' and running the resulting binary will print "adiós".
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[macro_export]
-    macro_rules! include_bytes { ($file:expr) => ({ /* compiler built-in */ }) }
+    #[rustc_doc_only_macro]
+    macro_rules! include_bytes {
+        ($file:expr) => ({ /* compiler built-in */ });
+        ($file:expr,) => ({ /* compiler built-in */ });
+    }
 
     /// Expands to a string that represents the current module path.
     ///
@@ -634,7 +708,7 @@ pub mod builtin {
     /// test::foo();
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[macro_export]
+    #[rustc_doc_only_macro]
     macro_rules! module_path { () => ({ /* compiler built-in */ }) }
 
     /// Boolean evaluation of configuration flags, at compile-time.
@@ -656,7 +730,7 @@ pub mod builtin {
     /// };
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[macro_export]
+    #[rustc_doc_only_macro]
     macro_rules! cfg { ($($cfg:tt)*) => ({ /* compiler built-in */ }) }
 
     /// Parse a file as an expression or an item according to the context.
@@ -699,17 +773,74 @@ pub mod builtin {
     /// Compiling 'main.rs' and running the resulting binary will print
     /// "🙈🙊🙉🙈🙊🙉".
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[macro_export]
-    macro_rules! include { ($file:expr) => ({ /* compiler built-in */ }) }
+    #[rustc_doc_only_macro]
+    macro_rules! include {
+        ($file:expr) => ({ /* compiler built-in */ });
+        ($file:expr,) => ({ /* compiler built-in */ });
+    }
+
+    /// Ensure that a boolean expression is `true` at runtime.
+    ///
+    /// This will invoke the [`panic!`] macro if the provided expression cannot be
+    /// evaluated to `true` at runtime.
+    ///
+    /// # Uses
+    ///
+    /// Assertions are always checked in both debug and release builds, and cannot
+    /// be disabled. See [`debug_assert!`] for assertions that are not enabled in
+    /// release builds by default.
+    ///
+    /// Unsafe code relies on `assert!` to enforce run-time invariants that, if
+    /// violated could lead to unsafety.
+    ///
+    /// Other use-cases of `assert!` include [testing] and enforcing run-time
+    /// invariants in safe code (whose violation cannot result in unsafety).
+    ///
+    /// # Custom Messages
+    ///
+    /// This macro has a second form, where a custom panic message can
+    /// be provided with or without arguments for formatting.  See [`std::fmt`]
+    /// for syntax for this form.
+    ///
+    /// [`panic!`]: macro.panic.html
+    /// [`debug_assert!`]: macro.debug_assert.html
+    /// [testing]: ../book/second-edition/ch11-01-writing-tests.html#checking-results-with-the-assert-macro
+    /// [`std::fmt`]: ../std/fmt/index.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// // the panic message for these assertions is the stringified value of the
+    /// // expression given.
+    /// assert!(true);
+    ///
+    /// fn some_computation() -> bool { true } // a very simple function
+    ///
+    /// assert!(some_computation());
+    ///
+    /// // assert with a custom message
+    /// let x = true;
+    /// assert!(x, "x wasn't true!");
+    ///
+    /// let a = 3; let b = 27;
+    /// assert!(a + b == 30, "a = {}, b = {}", a, b);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_doc_only_macro]
+    macro_rules! assert {
+        ($cond:expr) => ({ /* compiler built-in */ });
+        ($cond:expr,) => ({ /* compiler built-in */ });
+        ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ });
+    }
 }
 
-/// A macro for defining #[cfg] if-else statements.
+/// 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
+/// 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 {
     ($(
diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs
index 1ca7e66ed9c..e80c3eeb876 100644
--- a/src/libstd/net/addr.rs
+++ b/src/libstd/net/addr.rs
@@ -12,10 +12,11 @@ use fmt;
 use hash;
 use io;
 use mem;
-use net::{lookup_host, ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr};
+use net::{ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr};
 use option;
 use sys::net::netc as c;
 use sys_common::{FromInner, AsInner, IntoInner};
+use sys_common::net::lookup_host;
 use vec;
 use iter;
 use slice;
@@ -26,6 +27,9 @@ use slice;
 /// as possibly some version-dependent additional information. See [`SocketAddrV4`]'s and
 /// [`SocketAddrV6`]'s respective documentation for more details.
 ///
+/// The size of a `SocketAddr` instance may vary depending on the target operating
+/// system.
+///
 /// [IP address]: ../../std/net/enum.IpAddr.html
 /// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
 /// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
@@ -59,6 +63,9 @@ pub enum SocketAddr {
 ///
 /// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
 ///
+/// The size of a `SocketAddrV4` struct may vary depending on the target operating
+/// system.
+///
 /// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
 /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
 /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
@@ -86,6 +93,9 @@ pub struct SocketAddrV4 { inner: c::sockaddr_in }
 ///
 /// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
 ///
+/// The size of a `SocketAddrV6` struct may vary depending on the target operating
+/// system.
+///
 /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
 /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
 /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs
index 0d73a6f4fd7..9a610cd7d6b 100644
--- a/src/libstd/net/ip.rs
+++ b/src/libstd/net/ip.rs
@@ -16,8 +16,6 @@
 use cmp::Ordering;
 use fmt;
 use hash;
-use mem;
-use net::{hton, ntoh};
 use sys::net::netc as c;
 use sys_common::{AsInner, FromInner};
 
@@ -26,6 +24,9 @@ use sys_common::{AsInner, FromInner};
 /// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their
 /// respective documentation for more details.
 ///
+/// The size of an `IpAddr` instance may vary depending on the target operating
+/// system.
+///
 /// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
 /// [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
 ///
@@ -61,6 +62,9 @@ pub enum IpAddr {
 ///
 /// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
 ///
+/// The size of an `Ipv4Addr` struct may vary depending on the target operating
+/// system.
+///
 /// [IETF RFC 791]: https://tools.ietf.org/html/rfc791
 /// [`IpAddr`]: ../../std/net/enum.IpAddr.html
 ///
@@ -93,6 +97,9 @@ pub struct Ipv4Addr {
 ///
 /// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
 ///
+/// The size of an `Ipv6Addr` struct may vary depending on the target operating
+/// system.
+///
 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
 /// [`IpAddr`]: ../../std/net/enum.IpAddr.html
 ///
@@ -153,9 +160,9 @@ impl IpAddr {
     /// ```
     #[stable(feature = "ip_shared", since = "1.12.0")]
     pub fn is_unspecified(&self) -> bool {
-        match *self {
-            IpAddr::V4(ref a) => a.is_unspecified(),
-            IpAddr::V6(ref a) => a.is_unspecified(),
+        match self {
+            IpAddr::V4(ip) => ip.is_unspecified(),
+            IpAddr::V6(ip) => ip.is_unspecified(),
         }
     }
 
@@ -178,9 +185,9 @@ impl IpAddr {
     /// ```
     #[stable(feature = "ip_shared", since = "1.12.0")]
     pub fn is_loopback(&self) -> bool {
-        match *self {
-            IpAddr::V4(ref a) => a.is_loopback(),
-            IpAddr::V6(ref a) => a.is_loopback(),
+        match self {
+            IpAddr::V4(ip) => ip.is_loopback(),
+            IpAddr::V6(ip) => ip.is_loopback(),
         }
     }
 
@@ -207,9 +214,9 @@ impl IpAddr {
     /// }
     /// ```
     pub fn is_global(&self) -> bool {
-        match *self {
-            IpAddr::V4(ref a) => a.is_global(),
-            IpAddr::V6(ref a) => a.is_global(),
+        match self {
+            IpAddr::V4(ip) => ip.is_global(),
+            IpAddr::V6(ip) => ip.is_global(),
         }
     }
 
@@ -232,9 +239,9 @@ impl IpAddr {
     /// ```
     #[stable(feature = "ip_shared", since = "1.12.0")]
     pub fn is_multicast(&self) -> bool {
-        match *self {
-            IpAddr::V4(ref a) => a.is_multicast(),
-            IpAddr::V6(ref a) => a.is_multicast(),
+        match self {
+            IpAddr::V4(ip) => ip.is_multicast(),
+            IpAddr::V6(ip) => ip.is_multicast(),
         }
     }
 
@@ -261,9 +268,9 @@ impl IpAddr {
     /// }
     /// ```
     pub fn is_documentation(&self) -> bool {
-        match *self {
-            IpAddr::V4(ref a) => a.is_documentation(),
-            IpAddr::V6(ref a) => a.is_documentation(),
+        match self {
+            IpAddr::V4(ip) => ip.is_documentation(),
+            IpAddr::V6(ip) => ip.is_documentation(),
         }
     }
 
@@ -286,7 +293,7 @@ impl IpAddr {
     /// ```
     #[stable(feature = "ipaddr_checker", since = "1.16.0")]
     pub fn is_ipv4(&self) -> bool {
-        match *self {
+        match self {
             IpAddr::V4(_) => true,
             IpAddr::V6(_) => false,
         }
@@ -311,7 +318,7 @@ impl IpAddr {
     /// ```
     #[stable(feature = "ipaddr_checker", since = "1.16.0")]
     pub fn is_ipv6(&self) -> bool {
-        match *self {
+        match self {
             IpAddr::V4(_) => false,
             IpAddr::V6(_) => true,
         }
@@ -331,18 +338,21 @@ impl Ipv4Addr {
     /// let addr = Ipv4Addr::new(127, 0, 0, 1);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
+    #[rustc_const_unstable(feature = "const_ip")]
+    pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
         Ipv4Addr {
             inner: c::in_addr {
-                s_addr: hton(((a as u32) << 24) |
-                             ((b as u32) << 16) |
-                             ((c as u32) <<  8) |
-                              (d as u32)),
+                s_addr: u32::to_be(
+                    ((a as u32) << 24) |
+                    ((b as u32) << 16) |
+                    ((c as u32) <<  8) |
+                    (d as u32)
+                ),
             }
         }
     }
 
-    /// Creates a new IPv4 address with the address pointing to localhost: 127.0.0.1.
+    /// An IPv4 address with the address pointing to localhost: 127.0.0.1.
     ///
     /// # Examples
     ///
@@ -350,17 +360,15 @@ impl Ipv4Addr {
     /// #![feature(ip_constructors)]
     /// use std::net::Ipv4Addr;
     ///
-    /// let addr = Ipv4Addr::localhost();
+    /// let addr = Ipv4Addr::LOCALHOST;
     /// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1));
     /// ```
     #[unstable(feature = "ip_constructors",
                reason = "requires greater scrutiny before stabilization",
                issue = "44582")]
-    pub fn localhost() -> Ipv4Addr {
-        Ipv4Addr::new(127, 0, 0, 1)
-    }
+    pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
 
-    /// Creates a new IPv4 address representing an unspecified address: 0.0.0.0
+    /// An IPv4 address representing an unspecified address: 0.0.0.0
     ///
     /// # Examples
     ///
@@ -368,15 +376,29 @@ impl Ipv4Addr {
     /// #![feature(ip_constructors)]
     /// use std::net::Ipv4Addr;
     ///
-    /// let addr = Ipv4Addr::unspecified();
+    /// let addr = Ipv4Addr::UNSPECIFIED;
     /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0));
     /// ```
     #[unstable(feature = "ip_constructors",
                reason = "requires greater scrutiny before stabilization",
                issue = "44582")]
-    pub fn unspecified() -> Ipv4Addr {
-        Ipv4Addr::new(0, 0, 0, 0)
-    }
+    pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
+
+    /// An IPv4 address representing the broadcast address: 255.255.255.255
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip_constructors)]
+    /// use std::net::Ipv4Addr;
+    ///
+    /// let addr = Ipv4Addr::BROADCAST;
+    /// assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255));
+    /// ```
+    #[unstable(feature = "ip_constructors",
+               reason = "requires greater scrutiny before stabilization",
+               issue = "44582")]
+    pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
 
     /// Returns the four eight-bit integers that make up this address.
     ///
@@ -390,7 +412,7 @@ impl Ipv4Addr {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn octets(&self) -> [u8; 4] {
-        let bits = ntoh(self.inner.s_addr);
+        let bits = u32::from_be(self.inner.s_addr);
         [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
     }
 
@@ -461,11 +483,11 @@ impl Ipv4Addr {
     /// ```
     #[stable(since = "1.7.0", feature = "ip_17")]
     pub fn is_private(&self) -> bool {
-        match (self.octets()[0], self.octets()[1]) {
-            (10, _) => true,
-            (172, b) if b >= 16 && b <= 31 => true,
-            (192, 168) => true,
-            _ => false
+        match self.octets() {
+            [10, ..] => true,
+            [172, b, ..] if b >= 16 && b <= 31 => true,
+            [192, 168, ..] => true,
+            _ => false,
         }
     }
 
@@ -487,7 +509,10 @@ impl Ipv4Addr {
     /// ```
     #[stable(since = "1.7.0", feature = "ip_17")]
     pub fn is_link_local(&self) -> bool {
-        self.octets()[0] == 169 && self.octets()[1] == 254
+        match self.octets() {
+            [169, 254, ..] => true,
+            _ => false,
+        }
     }
 
     /// Returns [`true`] if the address appears to be globally routable.
@@ -564,8 +589,7 @@ impl Ipv4Addr {
     /// ```
     #[stable(since = "1.7.0", feature = "ip_17")]
     pub fn is_broadcast(&self) -> bool {
-        self.octets()[0] == 255 && self.octets()[1] == 255 &&
-        self.octets()[2] == 255 && self.octets()[3] == 255
+        self == &Self::BROADCAST
     }
 
     /// Returns [`true`] if this address is in a range designated for documentation.
@@ -591,11 +615,11 @@ impl Ipv4Addr {
     /// ```
     #[stable(since = "1.7.0", feature = "ip_17")]
     pub fn is_documentation(&self) -> bool {
-        match(self.octets()[0], self.octets()[1], self.octets()[2], self.octets()[3]) {
-            (192, 0, 2, _) => true,
-            (198, 51, 100, _) => true,
-            (203, 0, 113, _) => true,
-            _ => false
+        match self.octets() {
+            [192, 0, 2, _] => true,
+            [198, 51, 100, _] => true,
+            [203, 0, 113, _] => true,
+            _ => false,
         }
     }
 
@@ -645,9 +669,9 @@ impl Ipv4Addr {
 #[stable(feature = "ip_addr", since = "1.7.0")]
 impl fmt::Display for IpAddr {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            IpAddr::V4(ref a) => a.fmt(fmt),
-            IpAddr::V6(ref a) => a.fmt(fmt),
+        match self {
+            IpAddr::V4(ip) => ip.fmt(fmt),
+            IpAddr::V6(ip) => ip.fmt(fmt),
         }
     }
 }
@@ -696,8 +720,8 @@ impl PartialEq for Ipv4Addr {
 #[stable(feature = "ip_cmp", since = "1.16.0")]
 impl PartialEq<Ipv4Addr> for IpAddr {
     fn eq(&self, other: &Ipv4Addr) -> bool {
-        match *self {
-            IpAddr::V4(ref v4) => v4 == other,
+        match self {
+            IpAddr::V4(v4) => v4 == other,
             IpAddr::V6(_) => false,
         }
     }
@@ -706,8 +730,8 @@ impl PartialEq<Ipv4Addr> for IpAddr {
 #[stable(feature = "ip_cmp", since = "1.16.0")]
 impl PartialEq<IpAddr> for Ipv4Addr {
     fn eq(&self, other: &IpAddr) -> bool {
-        match *other {
-            IpAddr::V4(ref v4) => self == v4,
+        match other {
+            IpAddr::V4(v4) => self == v4,
             IpAddr::V6(_) => false,
         }
     }
@@ -734,8 +758,8 @@ impl PartialOrd for Ipv4Addr {
 #[stable(feature = "ip_cmp", since = "1.16.0")]
 impl PartialOrd<Ipv4Addr> for IpAddr {
     fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
-        match *self {
-            IpAddr::V4(ref v4) => v4.partial_cmp(other),
+        match self {
+            IpAddr::V4(v4) => v4.partial_cmp(other),
             IpAddr::V6(_) => Some(Ordering::Greater),
         }
     }
@@ -744,8 +768,8 @@ impl PartialOrd<Ipv4Addr> for IpAddr {
 #[stable(feature = "ip_cmp", since = "1.16.0")]
 impl PartialOrd<IpAddr> for Ipv4Addr {
     fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
-        match *other {
-            IpAddr::V4(ref v4) => self.partial_cmp(v4),
+        match other {
+            IpAddr::V4(v4) => self.partial_cmp(v4),
             IpAddr::V6(_) => Some(Ordering::Less),
         }
     }
@@ -754,7 +778,7 @@ impl PartialOrd<IpAddr> for Ipv4Addr {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Ord for Ipv4Addr {
     fn cmp(&self, other: &Ipv4Addr) -> Ordering {
-        ntoh(self.inner.s_addr).cmp(&ntoh(other.inner.s_addr))
+        u32::from_be(self.inner.s_addr).cmp(&u32::from_be(other.inner.s_addr))
     }
 }
 
@@ -769,7 +793,16 @@ impl FromInner<c::in_addr> for Ipv4Addr {
 
 #[stable(feature = "ip_u32", since = "1.1.0")]
 impl From<Ipv4Addr> for u32 {
-    /// It performs the conversion in network order (big-endian).
+    /// Convert an `Ipv4Addr` into a host byte order `u32`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv4Addr;
+    ///
+    /// let addr = Ipv4Addr::new(13, 12, 11, 10);
+    /// assert_eq!(0x0d0c0b0au32, u32::from(addr));
+    /// ```
     fn from(ip: Ipv4Addr) -> u32 {
         let ip = ip.octets();
         ((ip[0] as u32) << 24) + ((ip[1] as u32) << 16) + ((ip[2] as u32) << 8) + (ip[3] as u32)
@@ -778,7 +811,16 @@ impl From<Ipv4Addr> for u32 {
 
 #[stable(feature = "ip_u32", since = "1.1.0")]
 impl From<u32> for Ipv4Addr {
-    /// It performs the conversion in network order (big-endian).
+    /// Convert a host byte order `u32` into an `Ipv4Addr`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv4Addr;
+    ///
+    /// let addr = Ipv4Addr::from(0x0d0c0b0au32);
+    /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
+    /// ```
     fn from(ip: u32) -> Ipv4Addr {
         Ipv4Addr::new((ip >> 24) as u8, (ip >> 16) as u8, (ip >> 8) as u8, ip as u8)
     }
@@ -786,6 +828,14 @@ impl From<u32> for Ipv4Addr {
 
 #[stable(feature = "from_slice_v4", since = "1.9.0")]
 impl From<[u8; 4]> for Ipv4Addr {
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv4Addr;
+    ///
+    /// let addr = Ipv4Addr::from([13u8, 12u8, 11u8, 10u8]);
+    /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
+    /// ```
     fn from(octets: [u8; 4]) -> Ipv4Addr {
         Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])
     }
@@ -793,6 +843,16 @@ impl From<[u8; 4]> for Ipv4Addr {
 
 #[stable(feature = "ip_from_slice", since = "1.17.0")]
 impl From<[u8; 4]> for IpAddr {
+    /// Create an `IpAddr::V4` from a four element byte array.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv4Addr};
+    ///
+    /// let addr = IpAddr::from([13u8, 12u8, 11u8, 10u8]);
+    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(13, 12, 11, 10)), addr);
+    /// ```
     fn from(octets: [u8; 4]) -> IpAddr {
         IpAddr::V4(Ipv4Addr::from(octets))
     }
@@ -811,21 +871,27 @@ impl Ipv6Addr {
     /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16,
-               h: u16) -> Ipv6Addr {
-        let mut addr: c::in6_addr = unsafe { mem::zeroed() };
-        addr.s6_addr = [(a >> 8) as u8, a as u8,
-                        (b >> 8) as u8, b as u8,
-                        (c >> 8) as u8, c as u8,
-                        (d >> 8) as u8, d as u8,
-                        (e >> 8) as u8, e as u8,
-                        (f >> 8) as u8, f as u8,
-                        (g >> 8) as u8, g as u8,
-                        (h >> 8) as u8, h as u8];
-        Ipv6Addr { inner: addr }
+    #[rustc_const_unstable(feature = "const_ip")]
+    pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16,
+                     g: u16, h: u16) -> Ipv6Addr {
+        Ipv6Addr {
+            inner: c::in6_addr {
+                s6_addr: [
+                    (a >> 8) as u8, a as u8,
+                    (b >> 8) as u8, b as u8,
+                    (c >> 8) as u8, c as u8,
+                    (d >> 8) as u8, d as u8,
+                    (e >> 8) as u8, e as u8,
+                    (f >> 8) as u8, f as u8,
+                    (g >> 8) as u8, g as u8,
+                    (h >> 8) as u8, h as u8
+                ],
+            }
+        }
+
     }
 
-    /// Creates a new IPv6 address representing localhost: `::1`.
+    /// An IPv6 address representing localhost: `::1`.
     ///
     /// # Examples
     ///
@@ -833,17 +899,15 @@ impl Ipv6Addr {
     /// #![feature(ip_constructors)]
     /// use std::net::Ipv6Addr;
     ///
-    /// let addr = Ipv6Addr::localhost();
+    /// let addr = Ipv6Addr::LOCALHOST;
     /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
     /// ```
     #[unstable(feature = "ip_constructors",
                reason = "requires greater scrutiny before stabilization",
                issue = "44582")]
-    pub fn localhost() -> Ipv6Addr {
-        Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)
-    }
+    pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
 
-    /// Creates a new IPv6 address representing the unspecified address: `::`
+    /// An IPv6 address representing the unspecified address: `::`
     ///
     /// # Examples
     ///
@@ -851,15 +915,13 @@ impl Ipv6Addr {
     /// #![feature(ip_constructors)]
     /// use std::net::Ipv6Addr;
     ///
-    /// let addr = Ipv6Addr::unspecified();
+    /// let addr = Ipv6Addr::UNSPECIFIED;
     /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
     /// ```
     #[unstable(feature = "ip_constructors",
                reason = "requires greater scrutiny before stabilization",
                issue = "44582")]
-    pub fn unspecified() -> Ipv6Addr {
-        Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)
-    }
+    pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
 
     /// Returns the eight 16-bit segments that make up this address.
     ///
@@ -1276,9 +1338,9 @@ impl PartialEq for Ipv6Addr {
 #[stable(feature = "ip_cmp", since = "1.16.0")]
 impl PartialEq<IpAddr> for Ipv6Addr {
     fn eq(&self, other: &IpAddr) -> bool {
-        match *other {
+        match other {
             IpAddr::V4(_) => false,
-            IpAddr::V6(ref v6) => self == v6,
+            IpAddr::V6(v6) => self == v6,
         }
     }
 }
@@ -1286,9 +1348,9 @@ impl PartialEq<IpAddr> for Ipv6Addr {
 #[stable(feature = "ip_cmp", since = "1.16.0")]
 impl PartialEq<Ipv6Addr> for IpAddr {
     fn eq(&self, other: &Ipv6Addr) -> bool {
-        match *self {
+        match self {
             IpAddr::V4(_) => false,
-            IpAddr::V6(ref v6) => v6 == other,
+            IpAddr::V6(v6) => v6 == other,
         }
     }
 }
@@ -1313,9 +1375,9 @@ impl PartialOrd for Ipv6Addr {
 #[stable(feature = "ip_cmp", since = "1.16.0")]
 impl PartialOrd<Ipv6Addr> for IpAddr {
     fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
-        match *self {
+        match self {
             IpAddr::V4(_) => Some(Ordering::Less),
-            IpAddr::V6(ref v6) => v6.partial_cmp(other),
+            IpAddr::V6(v6) => v6.partial_cmp(other),
         }
     }
 }
@@ -1323,9 +1385,9 @@ impl PartialOrd<Ipv6Addr> for IpAddr {
 #[stable(feature = "ip_cmp", since = "1.16.0")]
 impl PartialOrd<IpAddr> for Ipv6Addr {
     fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
-        match *other {
+        match other {
             IpAddr::V4(_) => Some(Ordering::Greater),
-            IpAddr::V6(ref v6) => self.partial_cmp(v6),
+            IpAddr::V6(v6) => self.partial_cmp(v6),
         }
     }
 }
@@ -1346,7 +1408,7 @@ impl FromInner<c::in6_addr> for Ipv6Addr {
     }
 }
 
-#[unstable(feature = "i128", issue = "35118")]
+#[stable(feature = "i128", since = "1.26.0")]
 impl From<Ipv6Addr> for u128 {
     fn from(ip: Ipv6Addr) -> u128 {
         let ip = ip.segments();
@@ -1355,7 +1417,7 @@ impl From<Ipv6Addr> for u128 {
             ((ip[6] as u128) << 16) + (ip[7] as u128)
     }
 }
-#[unstable(feature = "i128", issue = "35118")]
+#[stable(feature = "i128", since = "1.26.0")]
 impl From<u128> for Ipv6Addr {
     fn from(ip: u128) -> Ipv6Addr {
         Ipv6Addr::new(
@@ -1369,8 +1431,7 @@ impl From<u128> for Ipv6Addr {
 #[stable(feature = "ipv6_from_octets", since = "1.9.0")]
 impl From<[u8; 16]> for Ipv6Addr {
     fn from(octets: [u8; 16]) -> Ipv6Addr {
-        let mut inner: c::in6_addr = unsafe { mem::zeroed() };
-        inner.s6_addr = octets;
+        let inner = c::in6_addr { s6_addr: octets };
         Ipv6Addr::from_inner(inner)
     }
 }
@@ -1386,6 +1447,27 @@ impl From<[u16; 8]> for Ipv6Addr {
 
 #[stable(feature = "ip_from_slice", since = "1.17.0")]
 impl From<[u8; 16]> for IpAddr {
+    /// Create an `IpAddr::V6` from a sixteen element byte array.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv6Addr};
+    ///
+    /// let addr = IpAddr::from([
+    ///     25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
+    ///     17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
+    /// ]);
+    /// assert_eq!(
+    ///     IpAddr::V6(Ipv6Addr::new(
+    ///         0x1918, 0x1716,
+    ///         0x1514, 0x1312,
+    ///         0x1110, 0x0f0e,
+    ///         0x0d0c, 0x0b0a
+    ///     )),
+    ///     addr
+    /// );
+    /// ```
     fn from(octets: [u8; 16]) -> IpAddr {
         IpAddr::V6(Ipv6Addr::from(octets))
     }
@@ -1393,6 +1475,27 @@ impl From<[u8; 16]> for IpAddr {
 
 #[stable(feature = "ip_from_slice", since = "1.17.0")]
 impl From<[u16; 8]> for IpAddr {
+    /// Create an `IpAddr::V6` from an eight element 16-bit array.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv6Addr};
+    ///
+    /// let addr = IpAddr::from([
+    ///     525u16, 524u16, 523u16, 522u16,
+    ///     521u16, 520u16, 519u16, 518u16,
+    /// ]);
+    /// assert_eq!(
+    ///     IpAddr::V6(Ipv6Addr::new(
+    ///         0x20d, 0x20c,
+    ///         0x20b, 0x20a,
+    ///         0x209, 0x208,
+    ///         0x207, 0x206
+    ///     )),
+    ///     addr
+    /// );
+    /// ```
     fn from(segments: [u16; 8]) -> IpAddr {
         IpAddr::V6(Ipv6Addr::from(segments))
     }
@@ -1759,18 +1862,20 @@ mod tests {
 
     #[test]
     fn ipv4_from_constructors() {
-        assert_eq!(Ipv4Addr::localhost(), Ipv4Addr::new(127, 0, 0, 1));
-        assert!(Ipv4Addr::localhost().is_loopback());
-        assert_eq!(Ipv4Addr::unspecified(), Ipv4Addr::new(0, 0, 0, 0));
-        assert!(Ipv4Addr::unspecified().is_unspecified());
+        assert_eq!(Ipv4Addr::LOCALHOST, Ipv4Addr::new(127, 0, 0, 1));
+        assert!(Ipv4Addr::LOCALHOST.is_loopback());
+        assert_eq!(Ipv4Addr::UNSPECIFIED, Ipv4Addr::new(0, 0, 0, 0));
+        assert!(Ipv4Addr::UNSPECIFIED.is_unspecified());
+        assert_eq!(Ipv4Addr::BROADCAST, Ipv4Addr::new(255, 255, 255, 255));
+        assert!(Ipv4Addr::BROADCAST.is_broadcast());
     }
 
     #[test]
     fn ipv6_from_contructors() {
-        assert_eq!(Ipv6Addr::localhost(), Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
-        assert!(Ipv6Addr::localhost().is_loopback());
-        assert_eq!(Ipv6Addr::unspecified(), Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
-        assert!(Ipv6Addr::unspecified().is_unspecified());
+        assert_eq!(Ipv6Addr::LOCALHOST, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+        assert!(Ipv6Addr::LOCALHOST.is_loopback());
+        assert_eq!(Ipv6Addr::UNSPECIFIED, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
+        assert!(Ipv6Addr::UNSPECIFIED.is_unspecified());
     }
 
     #[test]
diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs
index 9fcb93e2032..be4bcee8a68 100644
--- a/src/libstd/net/mod.rs
+++ b/src/libstd/net/mod.rs
@@ -38,9 +38,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use fmt;
 use io::{self, Error, ErrorKind};
-use sys_common::net as net_imp;
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
@@ -128,59 +126,3 @@ fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
                    "could not resolve to any addresses")
     }))
 }
-
-/// An iterator over `SocketAddr` values returned from a host lookup operation.
-#[unstable(feature = "lookup_host", reason = "unsure about the returned \
-                                              iterator and returning socket \
-                                              addresses",
-           issue = "27705")]
-pub struct LookupHost(net_imp::LookupHost);
-
-#[unstable(feature = "lookup_host", reason = "unsure about the returned \
-                                              iterator and returning socket \
-                                              addresses",
-           issue = "27705")]
-impl Iterator for LookupHost {
-    type Item = SocketAddr;
-    fn next(&mut self) -> Option<SocketAddr> { self.0.next() }
-}
-
-#[unstable(feature = "lookup_host", reason = "unsure about the returned \
-                                              iterator and returning socket \
-                                              addresses",
-           issue = "27705")]
-impl fmt::Debug for LookupHost {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.pad("LookupHost { .. }")
-    }
-}
-
-/// Resolve the host specified by `host` as a number of `SocketAddr` instances.
-///
-/// This method may perform a DNS query to resolve `host` and may also inspect
-/// system configuration to resolve the specified hostname.
-///
-/// The returned iterator will skip over any unknown addresses returned by the
-/// operating system.
-///
-/// # Examples
-///
-/// ```no_run
-/// #![feature(lookup_host)]
-///
-/// use std::net;
-///
-/// # fn foo() -> std::io::Result<()> {
-/// for host in net::lookup_host("rust-lang.org")? {
-///     println!("found address: {}", host);
-/// }
-/// # Ok(())
-/// # }
-/// ```
-#[unstable(feature = "lookup_host", reason = "unsure about the returned \
-                                              iterator and returning socket \
-                                              addresses",
-           issue = "27705")]
-pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
-    net_imp::lookup_host(host).map(LookupHost)
-}
diff --git a/src/libstd/net/parser.rs b/src/libstd/net/parser.rs
index 261d44eebaa..cf3e5354a31 100644
--- a/src/libstd/net/parser.rs
+++ b/src/libstd/net/parser.rs
@@ -53,15 +53,12 @@ impl<'a> Parser<'a> {
         F: FnOnce(&mut Parser) -> Option<T>,
     {
         self.read_atomically(move |p| {
-            match cb(p) {
-                Some(x) => if p.is_eof() {Some(x)} else {None},
-                None => None,
-            }
+            cb(p).filter(|_| p.is_eof())
         })
     }
 
     // Return result of first successful parser
-    fn read_or<T>(&mut self, parsers: &mut [Box<FnMut(&mut Parser) -> Option<T> + 'static>])
+    fn read_or<T>(&mut self, parsers: &mut [Box<dyn FnMut(&mut Parser) -> Option<T> + 'static>])
                -> Option<T> {
         for pf in parsers {
             if let Some(r) = self.read_atomically(|p: &mut Parser| pf(p)) {
@@ -372,6 +369,25 @@ impl FromStr for SocketAddr {
 /// [`IpAddr`], [`Ipv4Addr`], [`Ipv6Addr`], [`SocketAddr`], [`SocketAddrV4`], and
 /// [`SocketAddrV6`].
 ///
+/// # Potential causes
+///
+/// `AddrParseError` may be thrown because the provided string does not parse as the given type,
+/// often because it includes information only handled by a different address type.
+///
+/// ```should_panic
+/// use std::net::IpAddr;
+/// let _foo: IpAddr = "127.0.0.1:8080".parse().expect("Cannot handle the socket port");
+/// ```
+///
+/// [`IpAddr`] doesn't handle the port. Use [`SocketAddr`] instead.
+///
+/// ```
+/// use std::net::SocketAddr;
+///
+/// // No problem, the `panic!` message has disappeared.
+/// let _foo: SocketAddr = "127.0.0.1:8080".parse().expect("unreachable panic");
+/// ```
+///
 /// [`FromStr`]: ../../std/str/trait.FromStr.html
 /// [`IpAddr`]: ../../std/net/enum.IpAddr.html
 /// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs
index 78235ea1b4b..75c7a3d9280 100644
--- a/src/libstd/net/tcp.rs
+++ b/src/libstd/net/tcp.rs
@@ -72,7 +72,7 @@ pub struct TcpStream(net_imp::TcpStream);
 ///
 /// # Examples
 ///
-/// ```
+/// ```no_run
 /// # use std::io;
 /// use std::net::{TcpListener, TcpStream};
 ///
@@ -80,15 +80,15 @@ pub struct TcpStream(net_imp::TcpStream);
 ///     // ...
 /// }
 ///
-/// # fn process() -> io::Result<()> {
-/// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
+/// fn main() -> io::Result<()> {
+///     let listener = TcpListener::bind("127.0.0.1:80")?;
 ///
-/// // accept connections and process them serially
-/// for stream in listener.incoming() {
-///     handle_client(stream?);
+///     // accept connections and process them serially
+///     for stream in listener.incoming() {
+///         handle_client(stream?);
+///     }
+///     Ok(())
 /// }
-/// # Ok(())
-/// # }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct TcpListener(net_imp::TcpListener);
@@ -259,19 +259,21 @@ impl TcpStream {
     /// Sets the read timeout to the timeout specified.
     ///
     /// If the value specified is [`None`], then [`read`] calls will block
-    /// indefinitely. It is an error to pass the zero `Duration` to this
-    /// method.
+    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
+    /// passed to this method.
     ///
-    /// # Note
+    /// # Platform-specific behavior
     ///
     /// Platforms may return a different error code whenever a read times out as
     /// a result of setting this option. For example Unix typically returns an
     /// error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
     ///
     /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
     /// [`read`]: ../../std/io/trait.Read.html#tymethod.read
     /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
     /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut
+    /// [`Duration`]: ../../std/time/struct.Duration.html
     ///
     /// # Examples
     ///
@@ -282,6 +284,20 @@ impl TcpStream {
     ///                        .expect("Couldn't connect to the server...");
     /// stream.set_read_timeout(None).expect("set_read_timeout call failed");
     /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::net::TcpStream;
+    /// use std::time::Duration;
+    ///
+    /// let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
+    /// let result = stream.set_read_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
     #[stable(feature = "socket_timeout", since = "1.4.0")]
     pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
         self.0.set_read_timeout(dur)
@@ -290,16 +306,17 @@ impl TcpStream {
     /// Sets the write timeout to the timeout specified.
     ///
     /// If the value specified is [`None`], then [`write`] calls will block
-    /// indefinitely. It is an error to pass the zero [`Duration`] to this
-    /// method.
+    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
+    /// passed to this method.
     ///
-    /// # Note
+    /// # Platform-specific behavior
     ///
     /// Platforms may return a different error code whenever a write times out
     /// as a result of setting this option. For example Unix typically returns
     /// an error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
     ///
     /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
     /// [`write`]: ../../std/io/trait.Write.html#tymethod.write
     /// [`Duration`]: ../../std/time/struct.Duration.html
     /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
@@ -314,6 +331,20 @@ impl TcpStream {
     ///                        .expect("Couldn't connect to the server...");
     /// stream.set_write_timeout(None).expect("set_write_timeout call failed");
     /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::net::TcpStream;
+    /// use std::time::Duration;
+    ///
+    /// let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
+    /// let result = stream.set_write_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
     #[stable(feature = "socket_timeout", since = "1.4.0")]
     pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
         self.0.set_write_timeout(dur)
@@ -323,7 +354,7 @@ impl TcpStream {
     ///
     /// If the timeout is [`None`], then [`read`] calls will block indefinitely.
     ///
-    /// # Note
+    /// # Platform-specific behavior
     ///
     /// Some platforms do not provide access to the current timeout.
     ///
@@ -349,7 +380,7 @@ impl TcpStream {
     ///
     /// If the timeout is [`None`], then [`write`] calls will block indefinitely.
     ///
-    /// # Note
+    /// # Platform-specific behavior
     ///
     /// Some platforms do not provide access to the current timeout.
     ///
@@ -896,7 +927,7 @@ mod tests {
     use time::{Instant, Duration};
     use thread;
 
-    fn each_ip(f: &mut FnMut(SocketAddr)) {
+    fn each_ip(f: &mut dyn FnMut(SocketAddr)) {
         f(next_test_ip4());
         f(next_test_ip6());
     }
@@ -1545,6 +1576,26 @@ mod tests {
         drop(listener);
     }
 
+    // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors
+    // when passed zero Durations
+    #[test]
+    fn test_timeout_zero_duration() {
+        let addr = next_test_ip4();
+
+        let listener = t!(TcpListener::bind(&addr));
+        let stream = t!(TcpStream::connect(&addr));
+
+        let result = stream.set_write_timeout(Some(Duration::new(0, 0)));
+        let err = result.unwrap_err();
+        assert_eq!(err.kind(), ErrorKind::InvalidInput);
+
+        let result = stream.set_read_timeout(Some(Duration::new(0, 0)));
+        let err = result.unwrap_err();
+        assert_eq!(err.kind(), ErrorKind::InvalidInput);
+
+        drop(listener);
+    }
+
     #[test]
     fn nodelay() {
         let addr = next_test_ip4();
diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs
index fc7f9205d06..0ebe3284b4f 100644
--- a/src/libstd/net/udp.rs
+++ b/src/libstd/net/udp.rs
@@ -44,22 +44,22 @@ use time::Duration;
 /// ```no_run
 /// use std::net::UdpSocket;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// {
-///     let mut socket = UdpSocket::bind("127.0.0.1:34254")?;
+/// fn main() -> std::io::Result<()> {
+///     {
+///         let mut socket = UdpSocket::bind("127.0.0.1:34254")?;
 ///
-///     // Receives a single datagram message on the socket. If `buf` is too small to hold
-///     // the message, it will be cut off.
-///     let mut buf = [0; 10];
-///     let (amt, src) = socket.recv_from(&mut buf)?;
+///         // Receives a single datagram message on the socket. If `buf` is too small to hold
+///         // the message, it will be cut off.
+///         let mut buf = [0; 10];
+///         let (amt, src) = socket.recv_from(&mut buf)?;
 ///
-///     // Redeclare `buf` as slice of the received data and send reverse data back to origin.
-///     let buf = &mut buf[..amt];
-///     buf.reverse();
-///     socket.send_to(buf, &src)?;
-///     # Ok(())
-/// } // the socket is closed here
-/// # }
+///         // Redeclare `buf` as slice of the received data and send reverse data back to origin.
+///         let buf = &mut buf[..amt];
+///         buf.reverse();
+///         socket.send_to(buf, &src)?;
+///     } // the socket is closed here
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct UdpSocket(net_imp::UdpSocket);
@@ -228,16 +228,17 @@ impl UdpSocket {
     /// Sets the read timeout to the timeout specified.
     ///
     /// If the value specified is [`None`], then [`read`] calls will block
-    /// indefinitely. It is an error to pass the zero [`Duration`] to this
-    /// method.
+    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
+    /// passed to this method.
     ///
-    /// # Note
+    /// # Platform-specific behavior
     ///
     /// Platforms may return a different error code whenever a read times out as
     /// a result of setting this option. For example Unix typically returns an
     /// error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
     ///
     /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
     /// [`read`]: ../../std/io/trait.Read.html#tymethod.read
     /// [`Duration`]: ../../std/time/struct.Duration.html
     /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
@@ -251,6 +252,20 @@ impl UdpSocket {
     /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
     /// socket.set_read_timeout(None).expect("set_read_timeout call failed");
     /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::net::UdpSocket;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap();
+    /// let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
     #[stable(feature = "socket_timeout", since = "1.4.0")]
     pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
         self.0.set_read_timeout(dur)
@@ -259,16 +274,17 @@ impl UdpSocket {
     /// Sets the write timeout to the timeout specified.
     ///
     /// If the value specified is [`None`], then [`write`] calls will block
-    /// indefinitely. It is an error to pass the zero [`Duration`] to this
-    /// method.
+    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
+    /// passed to this method.
     ///
-    /// # Note
+    /// # Platform-specific behavior
     ///
     /// Platforms may return a different error code whenever a write times out
     /// as a result of setting this option. For example Unix typically returns
     /// an error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
     ///
     /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
     /// [`write`]: ../../std/io/trait.Write.html#tymethod.write
     /// [`Duration`]: ../../std/time/struct.Duration.html
     /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
@@ -282,6 +298,20 @@ impl UdpSocket {
     /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
     /// socket.set_write_timeout(None).expect("set_write_timeout call failed");
     /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::net::UdpSocket;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap();
+    /// let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
     #[stable(feature = "socket_timeout", since = "1.4.0")]
     pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
         self.0.set_write_timeout(dur)
@@ -796,7 +826,7 @@ mod tests {
     use time::{Instant, Duration};
     use thread;
 
-    fn each_ip(f: &mut FnMut(SocketAddr, SocketAddr)) {
+    fn each_ip(f: &mut dyn FnMut(SocketAddr, SocketAddr)) {
         f(next_test_ip4(), next_test_ip4());
         f(next_test_ip6(), next_test_ip6());
     }
@@ -1024,6 +1054,23 @@ mod tests {
         assert!(start.elapsed() > Duration::from_millis(400));
     }
 
+    // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors
+    // when passed zero Durations
+    #[test]
+    fn test_timeout_zero_duration() {
+        let addr = next_test_ip4();
+
+        let socket = t!(UdpSocket::bind(&addr));
+
+        let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
+        let err = result.unwrap_err();
+        assert_eq!(err.kind(), ErrorKind::InvalidInput);
+
+        let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
+        let err = result.unwrap_err();
+        assert_eq!(err.kind(), ErrorKind::InvalidInput);
+    }
+
     #[test]
     fn connect_send_recv() {
         let addr = next_test_ip4();
diff --git a/src/libstd/num.rs b/src/libstd/num.rs
index a2c133954a3..3f90c1fa3b1 100644
--- a/src/libstd/num.rs
+++ b/src/libstd/num.rs
@@ -21,6 +21,9 @@ pub use core::num::{FpCategory, ParseIntError, ParseFloatError, TryFromIntError}
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::num::Wrapping;
 
+#[stable(feature = "nonzero", since = "1.28.0")]
+pub use core::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize};
+
 #[cfg(test)] use fmt;
 #[cfg(test)] use ops::{Add, Sub, Mul, Div, Rem};
 
@@ -169,7 +172,6 @@ mod tests {
 
     macro_rules! test_checked_next_power_of_two {
         ($test_name:ident, $T:ident) => (
-            #[cfg_attr(target_os = "emscripten", ignore)] // FIXME(#39119)
             fn $test_name() {
                 #![test]
                 assert_eq!((0 as $T).checked_next_power_of_two(), Some(1));
diff --git a/src/libstd/os/android/fs.rs b/src/libstd/os/android/fs.rs
index a51b4655985..5899dc688e2 100644
--- a/src/libstd/os/android/fs.rs
+++ b/src/libstd/os/android/fs.rs
@@ -18,7 +18,9 @@ use sys_common::AsInner;
 #[allow(deprecated)]
 use os::android::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
diff --git a/src/libstd/os/bitrig/fs.rs b/src/libstd/os/bitrig/fs.rs
index e4f1c9432f3..24caf326ab0 100644
--- a/src/libstd/os/bitrig/fs.rs
+++ b/src/libstd/os/bitrig/fs.rs
@@ -18,7 +18,9 @@ use sys_common::AsInner;
 #[allow(deprecated)]
 use os::bitrig::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
diff --git a/src/libstd/os/dragonfly/fs.rs b/src/libstd/os/dragonfly/fs.rs
index db672e56435..6aea450774f 100644
--- a/src/libstd/os/dragonfly/fs.rs
+++ b/src/libstd/os/dragonfly/fs.rs
@@ -18,7 +18,9 @@ use sys_common::AsInner;
 #[allow(deprecated)]
 use os::dragonfly::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
diff --git a/src/libstd/os/emscripten/fs.rs b/src/libstd/os/emscripten/fs.rs
index 8056ce4fdc4..e0e197dc122 100644
--- a/src/libstd/os/emscripten/fs.rs
+++ b/src/libstd/os/emscripten/fs.rs
@@ -18,7 +18,9 @@ use sys_common::AsInner;
 #[allow(deprecated)]
 use os::emscripten::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
diff --git a/src/libstd/os/freebsd/fs.rs b/src/libstd/os/freebsd/fs.rs
index 2f17d2f7409..5f24cd636d5 100644
--- a/src/libstd/os/freebsd/fs.rs
+++ b/src/libstd/os/freebsd/fs.rs
@@ -18,7 +18,9 @@ use sys_common::AsInner;
 #[allow(deprecated)]
 use os::freebsd::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
diff --git a/src/libstd/os/fuchsia/fs.rs b/src/libstd/os/fuchsia/fs.rs
index d22f9a628bd..16802576356 100644
--- a/src/libstd/os/fuchsia/fs.rs
+++ b/src/libstd/os/fuchsia/fs.rs
@@ -13,7 +13,9 @@
 use fs::Metadata;
 use sys_common::AsInner;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
diff --git a/src/libstd/os/haiku/fs.rs b/src/libstd/os/haiku/fs.rs
index 54f8ea1b71b..453136e0ac8 100644
--- a/src/libstd/os/haiku/fs.rs
+++ b/src/libstd/os/haiku/fs.rs
@@ -18,7 +18,9 @@ use sys_common::AsInner;
 #[allow(deprecated)]
 use os::haiku::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
diff --git a/src/libstd/os/hermit/fs.rs b/src/libstd/os/hermit/fs.rs
new file mode 100644
index 00000000000..d2e751668a6
--- /dev/null
+++ b/src/libstd/os/hermit/fs.rs
@@ -0,0 +1,389 @@
+// Copyright 2018 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::hermit::raw;
+
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
+#[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.
+    ///
+    /// [`stat`]: ../../../../std/os/linux/raw/struct.stat.html
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> 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 \
+                                 methods of this trait")]
+    #[allow(deprecated)]
+    fn as_raw_stat(&self) -> &raw::stat;
+
+    /// Returns the device ID on which this file resides.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> 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
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> 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
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> 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
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> 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
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> 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
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> 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
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> 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
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> 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
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> 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
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> 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
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> 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
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> 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
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> 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
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> 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
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> 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
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::linux::fs::MetadataExt;
+    ///
+    /// fn main() -> 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;
+}
+
+#[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/hermit/mod.rs b/src/libstd/os/hermit/mod.rs
new file mode 100644
index 00000000000..fcb22cdad64
--- /dev/null
+++ b/src/libstd/os/hermit/mod.rs
@@ -0,0 +1,16 @@
+// Copyright 2018 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.
+
+//! HermitCore-specific definitions
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+
+pub mod raw;
+pub mod fs;
diff --git a/src/libstd/os/hermit/raw.rs b/src/libstd/os/hermit/raw.rs
new file mode 100644
index 00000000000..282afe0b6e1
--- /dev/null
+++ b/src/libstd/os/hermit/raw.rs
@@ -0,0 +1,27 @@
+// Copyright 2018 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.
+
+//! HermitCore-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)]
+#![allow(missing_debug_implementations)]
+
+#[stable(feature = "pthread_t", since = "1.8.0")]
+pub use libc::pthread_t;
+
+#[doc(inline)]
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub use libc::{dev_t, mode_t, off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t};
diff --git a/src/libstd/os/ios/fs.rs b/src/libstd/os/ios/fs.rs
index 275daf3d3a0..296ce69ff43 100644
--- a/src/libstd/os/ios/fs.rs
+++ b/src/libstd/os/ios/fs.rs
@@ -18,7 +18,9 @@ use sys_common::AsInner;
 #[allow(deprecated)]
 use os::ios::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
diff --git a/src/libstd/os/linux/fs.rs b/src/libstd/os/linux/fs.rs
index 5d37d970e89..76fb10da850 100644
--- a/src/libstd/os/linux/fs.rs
+++ b/src/libstd/os/linux/fs.rs
@@ -18,7 +18,9 @@ use sys_common::AsInner;
 #[allow(deprecated)]
 use os::linux::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
@@ -32,16 +34,16 @@ pub trait MetadataExt {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
+    /// use std::io;
     /// 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(())
-    /// # }
+    /// fn main() -> 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",
@@ -54,16 +56,16 @@ pub trait MetadataExt {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
+    /// use std::io;
     /// use std::os::linux::fs::MetadataExt;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// println!("{}", meta.st_dev());
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -71,16 +73,16 @@ pub trait MetadataExt {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
+    /// use std::io;
     /// use std::os::linux::fs::MetadataExt;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// println!("{}", meta.st_ino());
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -88,16 +90,16 @@ pub trait MetadataExt {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
+    /// use std::io;
     /// use std::os::linux::fs::MetadataExt;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// println!("{}", meta.st_mode());
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -105,16 +107,16 @@ pub trait MetadataExt {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
+    /// use std::io;
     /// use std::os::linux::fs::MetadataExt;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// println!("{}", meta.st_nlink());
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -122,16 +124,16 @@ pub trait MetadataExt {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
+    /// use std::io;
     /// use std::os::linux::fs::MetadataExt;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// println!("{}", meta.st_uid());
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -139,16 +141,16 @@ pub trait MetadataExt {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
+    /// use std::io;
     /// use std::os::linux::fs::MetadataExt;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// println!("{}", meta.st_gid());
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -156,16 +158,16 @@ pub trait MetadataExt {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
+    /// use std::io;
     /// use std::os::linux::fs::MetadataExt;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// println!("{}", meta.st_rdev());
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -176,16 +178,16 @@ pub trait MetadataExt {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
+    /// use std::io;
     /// use std::os::linux::fs::MetadataExt;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// println!("{}", meta.st_size());
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -193,16 +195,16 @@ pub trait MetadataExt {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
+    /// use std::io;
     /// use std::os::linux::fs::MetadataExt;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// println!("{}", meta.st_atime());
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -210,16 +212,16 @@ pub trait MetadataExt {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
+    /// use std::io;
     /// 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(())
-    /// # }
+    /// fn main() -> 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;
@@ -227,16 +229,16 @@ pub trait MetadataExt {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
+    /// use std::io;
     /// use std::os::linux::fs::MetadataExt;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// println!("{}", meta.st_mtime());
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -244,16 +246,16 @@ pub trait MetadataExt {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
+    /// use std::io;
     /// 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(())
-    /// # }
+    /// fn main() -> 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;
@@ -261,16 +263,16 @@ pub trait MetadataExt {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
+    /// use std::io;
     /// use std::os::linux::fs::MetadataExt;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// println!("{}", meta.st_ctime());
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -278,16 +280,16 @@ pub trait MetadataExt {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
+    /// use std::io;
     /// 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(())
-    /// # }
+    /// fn main() -> 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;
@@ -295,16 +297,16 @@ pub trait MetadataExt {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
+    /// use std::io;
     /// use std::os::linux::fs::MetadataExt;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// println!("{}", meta.st_blksize());
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -312,16 +314,16 @@ pub trait MetadataExt {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
+    /// use std::io;
     /// use std::os::linux::fs::MetadataExt;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// println!("{}", meta.st_blocks());
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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/macos/fs.rs b/src/libstd/os/macos/fs.rs
index 12b44901d03..0b14c05cb55 100644
--- a/src/libstd/os/macos/fs.rs
+++ b/src/libstd/os/macos/fs.rs
@@ -18,7 +18,9 @@ use sys_common::AsInner;
 #[allow(deprecated)]
 use os::macos::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
diff --git a/src/libstd/os/mod.rs b/src/libstd/os/mod.rs
index ac7809451d1..c384ec9168a 100644
--- a/src/libstd/os/mod.rs
+++ b/src/libstd/os/mod.rs
@@ -47,6 +47,7 @@ cfg_if! {
         #[cfg(target_os = "solaris")]    pub mod solaris;
         #[cfg(target_os = "emscripten")] pub mod emscripten;
         #[cfg(target_os = "fuchsia")]    pub mod fuchsia;
+        #[cfg(target_os = "hermit")]     pub mod hermit;
 
         #[cfg(any(target_os = "redox", unix))]
         #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libstd/os/netbsd/fs.rs b/src/libstd/os/netbsd/fs.rs
index cd7d5fafd1c..e9cad33fee6 100644
--- a/src/libstd/os/netbsd/fs.rs
+++ b/src/libstd/os/netbsd/fs.rs
@@ -18,7 +18,9 @@ use sys_common::AsInner;
 #[allow(deprecated)]
 use os::netbsd::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
diff --git a/src/libstd/os/openbsd/fs.rs b/src/libstd/os/openbsd/fs.rs
index cc812fcf12c..0f6b83b6e32 100644
--- a/src/libstd/os/openbsd/fs.rs
+++ b/src/libstd/os/openbsd/fs.rs
@@ -18,7 +18,9 @@ use sys_common::AsInner;
 #[allow(deprecated)]
 use os::openbsd::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
diff --git a/src/libstd/os/raw/char.md b/src/libstd/os/raw/char.md
new file mode 100644
index 00000000000..9a55767d965
--- /dev/null
+++ b/src/libstd/os/raw/char.md
@@ -0,0 +1,11 @@
+Equivalent to C's `char` type.
+
+[C's `char` type] is completely unlike [Rust's `char` type]; while Rust's type represents a unicode scalar value, C's `char` type is just an ordinary integer. This type will always be either [`i8`] or [`u8`], as the type is defined as being one byte long.
+
+C chars are most commonly used to make C strings. Unlike Rust, where the length of a string is included alongside the string, C strings mark the end of a string with the character `'\0'`. See [`CStr`] for more information.
+
+[C's `char` type]: https://en.wikipedia.org/wiki/C_data_types#Basic_types
+[Rust's `char` type]: ../../primitive.char.html
+[`CStr`]: ../../ffi/struct.CStr.html
+[`i8`]: ../../primitive.i8.html
+[`u8`]: ../../primitive.u8.html
diff --git a/src/libstd/os/raw/double.md b/src/libstd/os/raw/double.md
new file mode 100644
index 00000000000..6818dada317
--- /dev/null
+++ b/src/libstd/os/raw/double.md
@@ -0,0 +1,7 @@
+Equivalent to C's `double` type.
+
+This type will almost always be [`f64`], which is guaranteed to be an [IEEE-754 double-precision float] in Rust. That said, the standard technically only guarantees that it be a floating-point number with at least the precision of a [`float`], and it may be `f32` or something entirely different from the IEEE-754 standard.
+
+[IEEE-754 double-precision float]: https://en.wikipedia.org/wiki/IEEE_754
+[`float`]: type.c_float.html
+[`f64`]: ../../primitive.f64.html
diff --git a/src/libstd/os/raw/float.md b/src/libstd/os/raw/float.md
new file mode 100644
index 00000000000..57d1071d0da
--- /dev/null
+++ b/src/libstd/os/raw/float.md
@@ -0,0 +1,6 @@
+Equivalent to C's `float` type.
+
+This type will almost always be [`f32`], which is guaranteed to be an [IEEE-754 single-precision float] in Rust. That said, the standard technically only guarantees that it be a floating-point number, and it may have less precision than `f32` or not follow the IEEE-754 standard at all.
+
+[IEEE-754 single-precision float]: https://en.wikipedia.org/wiki/IEEE_754
+[`f32`]: ../../primitive.f32.html
diff --git a/src/libstd/os/raw/int.md b/src/libstd/os/raw/int.md
new file mode 100644
index 00000000000..a0d25fd21d8
--- /dev/null
+++ b/src/libstd/os/raw/int.md
@@ -0,0 +1,7 @@
+Equivalent to C's `signed int` (`int`) type.
+
+This type will almost always be [`i32`], but may differ on some esoteric systems. The C standard technically only requires that this type be a signed integer that is at least the size of a [`short`]; some systems define it as an [`i16`], for example.
+
+[`short`]: type.c_short.html
+[`i32`]: ../../primitive.i32.html
+[`i16`]: ../../primitive.i16.html
diff --git a/src/libstd/os/raw/long.md b/src/libstd/os/raw/long.md
new file mode 100644
index 00000000000..c620b402819
--- /dev/null
+++ b/src/libstd/os/raw/long.md
@@ -0,0 +1,7 @@
+Equivalent to C's `signed long` (`long`) type.
+
+This type will always be [`i32`] or [`i64`]. Most notably, many Linux-based systems assume an `i64`, but Windows assumes `i32`. The C standard technically only requires that this type be a signed integer that is at least 32 bits and at least the size of an [`int`], although in practice, no system would have a `long` that is neither an `i32` nor `i64`.
+
+[`int`]: type.c_int.html
+[`i32`]: ../../primitive.i32.html
+[`i64`]: ../../primitive.i64.html
diff --git a/src/libstd/os/raw/longlong.md b/src/libstd/os/raw/longlong.md
new file mode 100644
index 00000000000..ab3d6436568
--- /dev/null
+++ b/src/libstd/os/raw/longlong.md
@@ -0,0 +1,7 @@
+Equivalent to C's `signed long long` (`long long`) type.
+
+This type will almost always be [`i64`], but may differ on some systems. The C standard technically only requires that this type be a signed integer that is at least 64 bits and at least the size of a [`long`], although in practice, no system would have a `long long` that is not an `i64`, as most systems do not have a standardised [`i128`] type.
+
+[`long`]: type.c_int.html
+[`i64`]: ../../primitive.i64.html
+[`i128`]: ../../primitive.i128.html
diff --git a/src/libstd/os/raw.rs b/src/libstd/os/raw/mod.rs
index 279caf8053a..dc33747c05b 100644
--- a/src/libstd/os/raw.rs
+++ b/src/libstd/os/raw/mod.rs
@@ -8,12 +8,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Raw OS-specific types for the current platform/architecture
+//! Platform-specific types, as defined by C.
+//!
+//! Code that interacts via FFI will almost certainly be using the
+//! base types provided by C, which aren't nearly as nicely defined
+//! as Rust's primitive types. This module provides types which will
+//! match those defined by C, so that code that interacts with C will
+//! refer to the correct types.
 
 #![stable(feature = "raw_os", since = "1.1.0")]
 
 use fmt;
 
+#[doc(include = "os/raw/char.md")]
 #[cfg(any(all(target_os = "linux", any(target_arch = "aarch64",
                                        target_arch = "arm",
                                        target_arch = "powerpc",
@@ -22,9 +29,13 @@ use fmt;
           all(target_os = "android", any(target_arch = "aarch64",
                                          target_arch = "arm")),
           all(target_os = "l4re", target_arch = "x86_64"),
+          all(target_os = "netbsd", any(target_arch = "aarch64",
+                                        target_arch = "arm",
+                                        target_arch = "powerpc")),
           all(target_os = "openbsd", target_arch = "aarch64"),
           all(target_os = "fuchsia", target_arch = "aarch64")))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8;
+#[doc(include = "os/raw/char.md")]
 #[cfg(not(any(all(target_os = "linux", any(target_arch = "aarch64",
                                            target_arch = "arm",
                                            target_arch = "powerpc",
@@ -33,33 +44,56 @@ use fmt;
               all(target_os = "android", any(target_arch = "aarch64",
                                              target_arch = "arm")),
               all(target_os = "l4re", target_arch = "x86_64"),
+              all(target_os = "netbsd", any(target_arch = "aarch64",
+                                            target_arch = "arm",
+                                            target_arch = "powerpc")),
               all(target_os = "openbsd", target_arch = "aarch64"),
               all(target_os = "fuchsia", target_arch = "aarch64"))))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8;
+#[doc(include = "os/raw/schar.md")]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8;
+#[doc(include = "os/raw/uchar.md")]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8;
+#[doc(include = "os/raw/short.md")]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_short = i16;
+#[doc(include = "os/raw/ushort.md")]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ushort = u16;
+#[doc(include = "os/raw/int.md")]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_int = i32;
+#[doc(include = "os/raw/uint.md")]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uint = u32;
+#[doc(include = "os/raw/long.md")]
 #[cfg(any(target_pointer_width = "32", windows))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i32;
+#[doc(include = "os/raw/ulong.md")]
 #[cfg(any(target_pointer_width = "32", windows))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u32;
+#[doc(include = "os/raw/long.md")]
 #[cfg(all(target_pointer_width = "64", not(windows)))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i64;
+#[doc(include = "os/raw/ulong.md")]
 #[cfg(all(target_pointer_width = "64", not(windows)))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u64;
+#[doc(include = "os/raw/longlong.md")]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_longlong = i64;
+#[doc(include = "os/raw/ulonglong.md")]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulonglong = u64;
+#[doc(include = "os/raw/float.md")]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_float = f32;
+#[doc(include = "os/raw/double.md")]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_double = f64;
 
-/// Type used to construct void pointers for use with C.
+/// Equivalent to C's `void` type when used as a [pointer].
 ///
-/// This type is only useful as a pointer target. Do not use it as a
-/// return type for FFI functions which have the `void` return type in
-/// C. Use the unit type `()` or omit the return type instead.
+/// In essence, `*const c_void` is equivalent to C's `const void*`
+/// and `*mut c_void` is equivalent to C's `void*`. That said, this is
+/// *not* the same as C's `void` return type, which is Rust's `()` type.
+///
+/// Ideally, this type would be equivalent to [`!`], but currently it may
+/// be more ideal to use `c_void` for FFI purposes.
+///
+/// [`!`]: ../../primitive.never.html
+/// [pointer]: ../../primitive.pointer.html
 // NB: For LLVM to recognize the void pointer type and by extension
 //     functions like malloc(), we need to have it represented as i8* in
 //     LLVM bitcode. The enum used here ensures this and prevents misuse
diff --git a/src/libstd/os/raw/schar.md b/src/libstd/os/raw/schar.md
new file mode 100644
index 00000000000..6aa8b1211d8
--- /dev/null
+++ b/src/libstd/os/raw/schar.md
@@ -0,0 +1,6 @@
+Equivalent to C's `signed char` type.
+
+This type will always be [`i8`], but is included for completeness. It is defined as being a signed integer the same size as a C [`char`].
+
+[`char`]: type.c_char.html
+[`i8`]: ../../primitive.i8.html
diff --git a/src/libstd/os/raw/short.md b/src/libstd/os/raw/short.md
new file mode 100644
index 00000000000..be92c6c106d
--- /dev/null
+++ b/src/libstd/os/raw/short.md
@@ -0,0 +1,6 @@
+Equivalent to C's `signed short` (`short`) type.
+
+This type will almost always be [`i16`], but may differ on some esoteric systems. The C standard technically only requires that this type be a signed integer with at least 16 bits; some systems may define it as `i32`, for example.
+
+[`char`]: type.c_char.html
+[`i16`]: ../../primitive.i16.html
diff --git a/src/libstd/os/raw/uchar.md b/src/libstd/os/raw/uchar.md
new file mode 100644
index 00000000000..b6ca711f869
--- /dev/null
+++ b/src/libstd/os/raw/uchar.md
@@ -0,0 +1,6 @@
+Equivalent to C's `unsigned char` type.
+
+This type will always be [`u8`], but is included for completeness. It is defined as being an unsigned integer the same size as a C [`char`].
+
+[`char`]: type.c_char.html
+[`u8`]: ../../primitive.u8.html
diff --git a/src/libstd/os/raw/uint.md b/src/libstd/os/raw/uint.md
new file mode 100644
index 00000000000..6f7013a8ac1
--- /dev/null
+++ b/src/libstd/os/raw/uint.md
@@ -0,0 +1,7 @@
+Equivalent to C's `unsigned int` type.
+
+This type will almost always be [`u32`], but may differ on some esoteric systems. The C standard technically only requires that this type be an unsigned integer with the same size as an [`int`]; some systems define it as a [`u16`], for example.
+
+[`int`]: type.c_int.html
+[`u32`]: ../../primitive.u32.html
+[`u16`]: ../../primitive.u16.html
diff --git a/src/libstd/os/raw/ulong.md b/src/libstd/os/raw/ulong.md
new file mode 100644
index 00000000000..c350395080e
--- /dev/null
+++ b/src/libstd/os/raw/ulong.md
@@ -0,0 +1,7 @@
+Equivalent to C's `unsigned long` type.
+
+This type will always be [`u32`] or [`u64`]. Most notably, many Linux-based systems assume an `u64`, but Windows assumes `u32`. The C standard technically only requires that this type be an unsigned integer with the size of a [`long`], although in practice, no system would have a `ulong` that is neither a `u32` nor `u64`.
+
+[`long`]: type.c_long.html
+[`u32`]: ../../primitive.u32.html
+[`u64`]: ../../primitive.u64.html
diff --git a/src/libstd/os/raw/ulonglong.md b/src/libstd/os/raw/ulonglong.md
new file mode 100644
index 00000000000..c41faf74c5c
--- /dev/null
+++ b/src/libstd/os/raw/ulonglong.md
@@ -0,0 +1,7 @@
+Equivalent to C's `unsigned long long` type.
+
+This type will almost always be [`u64`], but may differ on some systems. The C standard technically only requires that this type be an unsigned integer with the size of a [`long long`], although in practice, no system would have a `long long` that is not a `u64`, as most systems do not have a standardised [`u128`] type.
+
+[`long long`]: type.c_longlong.html
+[`u64`]: ../../primitive.u64.html
+[`u128`]: ../../primitive.u128.html
diff --git a/src/libstd/os/raw/ushort.md b/src/libstd/os/raw/ushort.md
new file mode 100644
index 00000000000..d364abb3c8e
--- /dev/null
+++ b/src/libstd/os/raw/ushort.md
@@ -0,0 +1,6 @@
+Equivalent to C's `unsigned short` type.
+
+This type will almost always be [`u16`], but may differ on some esoteric systems. The C standard technically only requires that this type be an unsigned integer with the same size as a [`short`].
+
+[`short`]: type.c_short.html
+[`u16`]: ../../primitive.u16.html
diff --git a/src/libstd/os/solaris/fs.rs b/src/libstd/os/solaris/fs.rs
index 5dc43d03a86..19dce1ba34c 100644
--- a/src/libstd/os/solaris/fs.rs
+++ b/src/libstd/os/solaris/fs.rs
@@ -18,7 +18,9 @@ use sys_common::AsInner;
 #[allow(deprecated)]
 use os::solaris::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs
index 53c2211745c..b8c1c4f9e68 100644
--- a/src/libstd/panic.rs
+++ b/src/libstd/panic.rs
@@ -15,23 +15,33 @@
 use any::Any;
 use cell::UnsafeCell;
 use fmt;
+use future::Future;
+use mem::PinMut;
 use ops::{Deref, DerefMut};
 use panicking;
-use ptr::{Unique, Shared};
+use ptr::{Unique, NonNull};
 use rc::Rc;
 use sync::{Arc, Mutex, RwLock, atomic};
+use task::{self, Poll};
 use thread::Result;
 
 #[stable(feature = "panic_hooks", since = "1.10.0")]
-pub use panicking::{take_hook, set_hook, PanicInfo, Location};
+pub use panicking::{take_hook, set_hook};
+
+#[stable(feature = "panic_hooks", since = "1.10.0")]
+pub use core::panic::{PanicInfo, Location};
 
 /// A marker trait which represents "panic safe" types in Rust.
 ///
 /// This trait is implemented by default for many types and behaves similarly in
-/// terms of inference of implementation to the `Send` and `Sync` traits. The
-/// purpose of this trait is to encode what types are safe to cross a `catch_unwind`
+/// terms of inference of implementation to the [`Send`] and [`Sync`] traits. The
+/// purpose of this trait is to encode what types are safe to cross a [`catch_unwind`]
 /// boundary with no fear of unwind safety.
 ///
+/// [`Send`]: ../marker/trait.Send.html
+/// [`Sync`]: ../marker/trait.Sync.html
+/// [`catch_unwind`]: ./fn.catch_unwind.html
+///
 /// ## What is unwind safety?
 ///
 /// In Rust a function can "return" early if it either panics or calls a
@@ -92,41 +102,51 @@ pub use panicking::{take_hook, set_hook, PanicInfo, Location};
 ///
 /// ## When should `UnwindSafe` be used?
 ///
-/// Is not intended that most types or functions need to worry about this trait.
-/// It is only used as a bound on the `catch_unwind` function and as mentioned above,
-/// the lack of `unsafe` means it is mostly an advisory. The `AssertUnwindSafe`
-/// wrapper struct in this module can be used to force this trait to be
-/// implemented for any closed over variables passed to the `catch_unwind` function
-/// (more on this below).
+/// It is not intended that most types or functions need to worry about this trait.
+/// It is only used as a bound on the `catch_unwind` function and as mentioned
+/// above, the lack of `unsafe` means it is mostly an advisory. The
+/// [`AssertUnwindSafe`] wrapper struct can be used to force this trait to be
+/// implemented for any closed over variables passed to `catch_unwind`.
+///
+/// [`AssertUnwindSafe`]: ./struct.AssertUnwindSafe.html
 #[stable(feature = "catch_unwind", since = "1.9.0")]
-#[rustc_on_unimplemented = "the type {Self} may not be safely transferred \
-                            across an unwind boundary"]
+#[rustc_on_unimplemented(
+    message="the type `{Self}` may not be safely transferred across an unwind boundary",
+    label="`{Self}` may not be safely transferred across an unwind boundary",
+)]
 pub auto trait UnwindSafe {}
 
 /// A marker trait representing types where a shared reference is considered
 /// unwind safe.
 ///
-/// This trait is namely not implemented by `UnsafeCell`, the root of all
+/// This trait is namely not implemented by [`UnsafeCell`], the root of all
 /// interior mutability.
 ///
 /// This is a "helper marker trait" used to provide impl blocks for the
-/// `UnwindSafe` trait, for more information see that documentation.
+/// [`UnwindSafe`] trait, for more information see that documentation.
+///
+/// [`UnsafeCell`]: ../cell/struct.UnsafeCell.html
+/// [`UnwindSafe`]: ./trait.UnwindSafe.html
 #[stable(feature = "catch_unwind", since = "1.9.0")]
-#[rustc_on_unimplemented = "the type {Self} may contain interior mutability \
-                            and a reference may not be safely transferrable \
-                            across a catch_unwind boundary"]
+#[rustc_on_unimplemented(
+    message="the type `{Self}` may contain interior mutability and a reference may not be safely \
+             transferrable across a catch_unwind boundary",
+    label="`{Self}` may contain interior mutability and a reference may not be safely \
+           transferrable across a catch_unwind boundary",
+)]
 pub auto trait RefUnwindSafe {}
 
 /// A simple wrapper around a type to assert that it is unwind safe.
 ///
-/// When using `catch_unwind` it may be the case that some of the closed over
+/// When using [`catch_unwind`] it may be the case that some of the closed over
 /// variables are not unwind safe. For example if `&mut T` is captured the
 /// compiler will generate a warning indicating that it is not unwind safe. It
 /// may not be the case, however, that this is actually a problem due to the
-/// specific usage of `catch_unwind` if unwind safety is specifically taken into
+/// specific usage of [`catch_unwind`] if unwind safety is specifically taken into
 /// account. This wrapper struct is useful for a quick and lightweight
 /// annotation that a variable is indeed unwind safe.
 ///
+/// [`catch_unwind`]: ./fn.catch_unwind.html
 /// # Examples
 ///
 /// One way to use `AssertUnwindSafe` is to assert that the entire closure
@@ -185,7 +205,7 @@ pub struct AssertUnwindSafe<T>(
 // * By default everything is unwind safe
 // * pointers T contains mutability of some form are not unwind safe
 // * Unique, an owning pointer, lifts an implementation
-// * Types like Mutex/RwLock which are explicilty poisoned are unwind safe
+// * Types like Mutex/RwLock which are explicitly poisoned are unwind safe
 // * Our custom AssertUnwindSafe wrapper is indeed unwind safe
 
 #[stable(feature = "catch_unwind", since = "1.9.0")]
@@ -196,10 +216,10 @@ impl<'a, T: RefUnwindSafe + ?Sized> UnwindSafe for &'a T {}
 impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *const T {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *mut T {}
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 impl<T: UnwindSafe + ?Sized> UnwindSafe for Unique<T> {}
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Shared<T> {}
+#[stable(feature = "nonnull", since = "1.25.0")]
+impl<T: RefUnwindSafe + ?Sized> UnwindSafe for NonNull<T> {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T: ?Sized> UnwindSafe for Mutex<T> {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
@@ -303,6 +323,16 @@ impl<T: fmt::Debug> fmt::Debug for AssertUnwindSafe<T> {
     }
 }
 
+#[unstable(feature = "futures_api", issue = "50547")]
+impl<'a, F: Future> Future for AssertUnwindSafe<F> {
+    type Output = F::Output;
+
+    fn poll(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
+        let pinned_field = unsafe { PinMut::map_unchecked(self, |x| &mut x.0) };
+        pinned_field.poll(cx)
+    }
+}
+
 /// Invokes a closure, capturing the cause of an unwinding panic if one occurs.
 ///
 /// This function will return `Ok` with the closure's result if the closure
@@ -315,18 +345,22 @@ impl<T: fmt::Debug> fmt::Debug for AssertUnwindSafe<T> {
 /// panic and allowing a graceful handling of the error.
 ///
 /// It is **not** recommended to use this function for a general try/catch
-/// mechanism. The `Result` type is more appropriate to use for functions that
+/// mechanism. The [`Result`] type is more appropriate to use for functions that
 /// can fail on a regular basis. Additionally, this function is not guaranteed
 /// to catch all panics, see the "Notes" section below.
 ///
-/// The closure provided is required to adhere to the `UnwindSafe` trait to ensure
+/// [`Result`]: ../result/enum.Result.html
+///
+/// The closure provided is required to adhere to the [`UnwindSafe`] trait to ensure
 /// that all captured variables are safe to cross this boundary. The purpose of
 /// this bound is to encode the concept of [exception safety][rfc] in the type
 /// system. Most usage of this function should not need to worry about this
 /// bound as programs are naturally unwind safe without `unsafe` code. If it
-/// becomes a problem the associated `AssertUnwindSafe` wrapper type in this
-/// module can be used to quickly assert that the usage here is indeed unwind
-/// safe.
+/// becomes a problem the [`AssertUnwindSafe`] wrapper struct can be used to quickly
+/// assert that the usage here is indeed unwind safe.
+///
+/// [`AssertUnwindSafe`]: ./struct.AssertUnwindSafe.html
+/// [`UnwindSafe`]: ./trait.UnwindSafe.html
 ///
 /// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md
 ///
@@ -361,9 +395,11 @@ pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
 
 /// Triggers a panic without invoking the panic hook.
 ///
-/// This is designed to be used in conjunction with `catch_unwind` to, for
+/// This is designed to be used in conjunction with [`catch_unwind`] to, for
 /// example, carry a panic across a layer of C code.
 ///
+/// [`catch_unwind`]: ./fn.catch_unwind.html
+///
 /// # Notes
 ///
 /// Note that panics in Rust are not always implemented via unwinding, but they
@@ -385,6 +421,6 @@ pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
 /// }
 /// ```
 #[stable(feature = "resume_unwind", since = "1.9.0")]
-pub fn resume_unwind(payload: Box<Any + Send>) -> ! {
+pub fn resume_unwind(payload: Box<dyn Any + Send>) -> ! {
     panicking::update_count_then_panic(payload)
 }
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index f91eaf433d7..283fd36af41 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -17,23 +17,26 @@
 //! * Executing a panic up to doing the actual implementation
 //! * Shims around "try"
 
+use core::panic::BoxMeUp;
+
 use io::prelude::*;
 
 use any::Any;
 use cell::RefCell;
+use core::panic::{PanicInfo, Location};
 use fmt;
 use intrinsics;
 use mem;
 use ptr;
 use raw;
-use sys::stdio::Stderr;
+use sys::stdio::{Stderr, stderr_prints_nothing};
 use sys_common::rwlock::RWLock;
 use sys_common::thread_info;
 use sys_common::util;
 use thread;
 
 thread_local! {
-    pub static LOCAL_STDERR: RefCell<Option<Box<Write + Send>>> = {
+    pub static LOCAL_STDERR: RefCell<Option<Box<dyn Write + Send>>> = {
         RefCell::new(None)
     }
 }
@@ -54,14 +57,14 @@ extern {
                                 data: *mut u8,
                                 data_ptr: *mut usize,
                                 vtable_ptr: *mut usize) -> u32;
-    #[unwind]
-    fn __rust_start_panic(data: usize, vtable: usize) -> u32;
+    #[unwind(allowed)]
+    fn __rust_start_panic(payload: usize) -> u32;
 }
 
 #[derive(Copy, Clone)]
 enum Hook {
     Default,
-    Custom(*mut (Fn(&PanicInfo) + 'static + Sync + Send)),
+    Custom(*mut (dyn Fn(&PanicInfo) + 'static + Sync + Send)),
 }
 
 static HOOK_LOCK: RWLock = RWLock::new();
@@ -73,7 +76,9 @@ static mut HOOK: Hook = Hook::Default;
 /// is invoked. As such, the hook will run with both the aborting and unwinding
 /// runtimes. The default hook prints a message to standard error and generates
 /// a backtrace if requested, but this behavior can be customized with the
-/// `set_hook` and `take_hook` functions.
+/// `set_hook` and [`take_hook`] functions.
+///
+/// [`take_hook`]: ./fn.take_hook.html
 ///
 /// The hook is provided with a `PanicInfo` struct which contains information
 /// about the origin of the panic, including the payload passed to `panic!` and
@@ -99,7 +104,7 @@ static mut HOOK: Hook = Hook::Default;
 /// panic!("Normal panic");
 /// ```
 #[stable(feature = "panic_hooks", since = "1.10.0")]
-pub fn set_hook(hook: Box<Fn(&PanicInfo) + 'static + Sync + Send>) {
+pub fn set_hook(hook: Box<dyn Fn(&PanicInfo) + 'static + Sync + Send>) {
     if thread::panicking() {
         panic!("cannot modify the panic hook from a panicking thread");
     }
@@ -118,6 +123,10 @@ pub fn set_hook(hook: Box<Fn(&PanicInfo) + 'static + Sync + Send>) {
 
 /// Unregisters the current panic hook, returning it.
 ///
+/// *See also the function [`set_hook`].*
+///
+/// [`set_hook`]: ./fn.set_hook.html
+///
 /// If no custom hook is registered, the default hook will be returned.
 ///
 /// # Panics
@@ -140,7 +149,7 @@ pub fn set_hook(hook: Box<Fn(&PanicInfo) + 'static + Sync + Send>) {
 /// panic!("Normal panic");
 /// ```
 #[stable(feature = "panic_hooks", since = "1.10.0")]
-pub fn take_hook() -> Box<Fn(&PanicInfo) + 'static + Sync + Send> {
+pub fn take_hook() -> Box<dyn Fn(&PanicInfo) + 'static + Sync + Send> {
     if thread::panicking() {
         panic!("cannot modify the panic hook from a panicking thread");
     }
@@ -158,182 +167,6 @@ pub fn take_hook() -> Box<Fn(&PanicInfo) + 'static + Sync + Send> {
     }
 }
 
-/// A struct providing information about a panic.
-///
-/// `PanicInfo` structure is passed to a panic hook set by the [`set_hook`]
-/// function.
-///
-/// [`set_hook`]: ../../std/panic/fn.set_hook.html
-///
-/// # Examples
-///
-/// ```should_panic
-/// use std::panic;
-///
-/// panic::set_hook(Box::new(|panic_info| {
-///     println!("panic occurred: {:?}", panic_info.payload().downcast_ref::<&str>().unwrap());
-/// }));
-///
-/// panic!("Normal panic");
-/// ```
-#[stable(feature = "panic_hooks", since = "1.10.0")]
-#[derive(Debug)]
-pub struct PanicInfo<'a> {
-    payload: &'a (Any + Send),
-    location: Location<'a>,
-}
-
-impl<'a> PanicInfo<'a> {
-    /// Returns the payload associated with the panic.
-    ///
-    /// This will commonly, but not always, be a `&'static str` or [`String`].
-    ///
-    /// [`String`]: ../../std/string/struct.String.html
-    ///
-    /// # Examples
-    ///
-    /// ```should_panic
-    /// use std::panic;
-    ///
-    /// panic::set_hook(Box::new(|panic_info| {
-    ///     println!("panic occurred: {:?}", panic_info.payload().downcast_ref::<&str>().unwrap());
-    /// }));
-    ///
-    /// panic!("Normal panic");
-    /// ```
-    #[stable(feature = "panic_hooks", since = "1.10.0")]
-    pub fn payload(&self) -> &(Any + Send) {
-        self.payload
-    }
-
-    /// Returns information about the location from which the panic originated,
-    /// if available.
-    ///
-    /// This method will currently always return [`Some`], but this may change
-    /// in future versions.
-    ///
-    /// [`Some`]: ../../std/option/enum.Option.html#variant.Some
-    ///
-    /// # Examples
-    ///
-    /// ```should_panic
-    /// use std::panic;
-    ///
-    /// panic::set_hook(Box::new(|panic_info| {
-    ///     if let Some(location) = panic_info.location() {
-    ///         println!("panic occurred in file '{}' at line {}", location.file(),
-    ///             location.line());
-    ///     } else {
-    ///         println!("panic occurred but can't get location information...");
-    ///     }
-    /// }));
-    ///
-    /// panic!("Normal panic");
-    /// ```
-    #[stable(feature = "panic_hooks", since = "1.10.0")]
-    pub fn location(&self) -> Option<&Location> {
-        Some(&self.location)
-    }
-}
-
-/// A struct containing information about the location of a panic.
-///
-/// This structure is created by the [`location`] method of [`PanicInfo`].
-///
-/// [`location`]: ../../std/panic/struct.PanicInfo.html#method.location
-/// [`PanicInfo`]: ../../std/panic/struct.PanicInfo.html
-///
-/// # Examples
-///
-/// ```should_panic
-/// use std::panic;
-///
-/// panic::set_hook(Box::new(|panic_info| {
-///     if let Some(location) = panic_info.location() {
-///         println!("panic occurred in file '{}' at line {}", location.file(), location.line());
-///     } else {
-///         println!("panic occurred but can't get location information...");
-///     }
-/// }));
-///
-/// panic!("Normal panic");
-/// ```
-#[derive(Debug)]
-#[stable(feature = "panic_hooks", since = "1.10.0")]
-pub struct Location<'a> {
-    file: &'a str,
-    line: u32,
-    col: u32,
-}
-
-impl<'a> Location<'a> {
-    /// Returns the name of the source file from which the panic originated.
-    ///
-    /// # Examples
-    ///
-    /// ```should_panic
-    /// use std::panic;
-    ///
-    /// panic::set_hook(Box::new(|panic_info| {
-    ///     if let Some(location) = panic_info.location() {
-    ///         println!("panic occurred in file '{}'", location.file());
-    ///     } else {
-    ///         println!("panic occurred but can't get location information...");
-    ///     }
-    /// }));
-    ///
-    /// panic!("Normal panic");
-    /// ```
-    #[stable(feature = "panic_hooks", since = "1.10.0")]
-    pub fn file(&self) -> &str {
-        self.file
-    }
-
-    /// Returns the line number from which the panic originated.
-    ///
-    /// # Examples
-    ///
-    /// ```should_panic
-    /// use std::panic;
-    ///
-    /// panic::set_hook(Box::new(|panic_info| {
-    ///     if let Some(location) = panic_info.location() {
-    ///         println!("panic occurred at line {}", location.line());
-    ///     } else {
-    ///         println!("panic occurred but can't get location information...");
-    ///     }
-    /// }));
-    ///
-    /// panic!("Normal panic");
-    /// ```
-    #[stable(feature = "panic_hooks", since = "1.10.0")]
-    pub fn line(&self) -> u32 {
-        self.line
-    }
-
-    /// Returns the column from which the panic originated.
-    ///
-    /// # Examples
-    ///
-    /// ```should_panic
-    /// use std::panic;
-    ///
-    /// panic::set_hook(Box::new(|panic_info| {
-    ///     if let Some(location) = panic_info.location() {
-    ///         println!("panic occurred at column {}", location.column());
-    ///     } else {
-    ///         println!("panic occurred but can't get location information...");
-    ///     }
-    /// }));
-    ///
-    /// panic!("Normal panic");
-    /// ```
-    #[stable(feature = "panic_col", since = "1.25")]
-    pub fn column(&self) -> u32 {
-        self.col
-    }
-}
-
 fn default_hook(info: &PanicInfo) {
     #[cfg(feature = "backtrace")]
     use sys_common::backtrace;
@@ -351,13 +184,11 @@ fn default_hook(info: &PanicInfo) {
         }
     };
 
-    let file = info.location.file;
-    let line = info.location.line;
-    let col = info.location.col;
+    let location = info.location().unwrap();  // The current implementation always returns Some
 
-    let msg = match info.payload.downcast_ref::<&'static str>() {
+    let msg = match info.payload().downcast_ref::<&'static str>() {
         Some(s) => *s,
-        None => match info.payload.downcast_ref::<String>() {
+        None => match info.payload().downcast_ref::<String>() {
             Some(s) => &s[..],
             None => "Box<Any>",
         }
@@ -366,9 +197,9 @@ fn default_hook(info: &PanicInfo) {
     let thread = thread_info::current_thread();
     let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
 
-    let write = |err: &mut ::io::Write| {
-        let _ = writeln!(err, "thread '{}' panicked at '{}', {}:{}:{}",
-                         name, msg, file, line, col);
+    let write = |err: &mut dyn (::io::Write)| {
+        let _ = writeln!(err, "thread '{}' panicked at '{}', {}",
+                         name, msg, location);
 
         #[cfg(feature = "backtrace")]
         {
@@ -386,15 +217,15 @@ fn default_hook(info: &PanicInfo) {
 
     let prev = LOCAL_STDERR.with(|s| s.borrow_mut().take());
     match (prev, err.as_mut()) {
-        (Some(mut stderr), _) => {
-            write(&mut *stderr);
-            let mut s = Some(stderr);
-            LOCAL_STDERR.with(|slot| {
-                *slot.borrow_mut() = s.take();
-            });
-        }
-        (None, Some(ref mut err)) => { write(err) }
-        _ => {}
+       (Some(mut stderr), _) => {
+           write(&mut *stderr);
+           let mut s = Some(stderr);
+           LOCAL_STDERR.with(|slot| {
+               *slot.borrow_mut() = s.take();
+           });
+       }
+       (None, Some(ref mut err)) => { write(err) }
+       _ => {}
     }
 }
 
@@ -417,7 +248,7 @@ pub fn update_panic_count(amt: isize) -> usize {
 pub use realstd::rt::update_panic_count;
 
 /// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
-pub unsafe fn try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<Any + Send>> {
+pub unsafe fn try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
     #[allow(unions_with_drop_fields)]
     union Data<F, R> {
         f: F,
@@ -488,13 +319,10 @@ pub fn panicking() -> bool {
 
 /// Entry point of panic from the libcore crate.
 #[cfg(not(test))]
-#[lang = "panic_fmt"]
-#[unwind]
-pub extern fn rust_begin_panic(msg: fmt::Arguments,
-                               file: &'static str,
-                               line: u32,
-                               col: u32) -> ! {
-    begin_panic_fmt(&msg, &(file, line, col))
+#[panic_implementation]
+#[unwind(allowed)]
+pub fn rust_begin_panic(info: &PanicInfo) -> ! {
+    continue_panic_fmt(&info)
 }
 
 /// The entry point for panicking with a formatted message.
@@ -509,16 +337,60 @@ pub extern fn rust_begin_panic(msg: fmt::Arguments,
 #[inline(never)] #[cold]
 pub fn begin_panic_fmt(msg: &fmt::Arguments,
                        file_line_col: &(&'static str, u32, u32)) -> ! {
-    use fmt::Write;
+    let (file, line, col) = *file_line_col;
+    let info = PanicInfo::internal_constructor(
+        Some(msg),
+        Location::internal_constructor(file, line, col),
+    );
+    continue_panic_fmt(&info)
+}
+
+fn continue_panic_fmt(info: &PanicInfo) -> ! {
+    struct PanicPayload<'a> {
+        inner: &'a fmt::Arguments<'a>,
+        string: Option<String>,
+    }
+
+    impl<'a> PanicPayload<'a> {
+        fn new(inner: &'a fmt::Arguments<'a>) -> PanicPayload<'a> {
+            PanicPayload { inner, string: None }
+        }
+
+        fn fill(&mut self) -> &mut String {
+            use fmt::Write;
+
+            let inner = self.inner;
+            self.string.get_or_insert_with(|| {
+                let mut s = String::new();
+                drop(s.write_fmt(*inner));
+                s
+            })
+        }
+    }
+
+    unsafe impl<'a> BoxMeUp for PanicPayload<'a> {
+        fn box_me_up(&mut self) -> *mut (dyn Any + Send) {
+            let contents = mem::replace(self.fill(), String::new());
+            Box::into_raw(Box::new(contents))
+        }
+
+        fn get(&mut self) -> &(dyn Any + Send) {
+            self.fill()
+        }
+    }
 
     // We do two allocations here, unfortunately. But (a) they're
     // required with the current scheme, and (b) we don't handle
     // panic + OOM properly anyway (see comment in begin_panic
     // below).
 
-    let mut s = String::new();
-    let _ = s.write_fmt(*msg);
-    begin_panic(s, file_line_col)
+    let loc = info.location().unwrap(); // The current implementation always returns Some
+    let msg = info.message().unwrap(); // The current implementation always returns Some
+    let file_line_col = (loc.file(), loc.line(), loc.column());
+    rust_panic_with_hook(
+        &mut PanicPayload::new(msg),
+        info.message(),
+        &file_line_col);
 }
 
 /// This is the entry point of panicking for panic!() and assert!().
@@ -534,19 +406,44 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u3
     // be performed in the parent of this thread instead of the thread that's
     // panicking.
 
-    rust_panic_with_hook(Box::new(msg), file_line_col)
+    rust_panic_with_hook(&mut PanicPayload::new(msg), None, file_line_col);
+
+    struct PanicPayload<A> {
+        inner: Option<A>,
+    }
+
+    impl<A: Send + 'static> PanicPayload<A> {
+        fn new(inner: A) -> PanicPayload<A> {
+            PanicPayload { inner: Some(inner) }
+        }
+    }
+
+    unsafe impl<A: Send + 'static> BoxMeUp for PanicPayload<A> {
+        fn box_me_up(&mut self) -> *mut (dyn Any + Send) {
+            let data = match self.inner.take() {
+                Some(a) => Box::new(a) as Box<dyn Any + Send>,
+                None => Box::new(()),
+            };
+            Box::into_raw(data)
+        }
+
+        fn get(&mut self) -> &(dyn Any + Send) {
+            match self.inner {
+                Some(ref a) => a,
+                None => &(),
+            }
+        }
+    }
 }
 
-/// Executes the primary logic for a panic, including checking for recursive
-/// panics and panic hooks.
+/// Central point for dispatching panics.
 ///
-/// This is the entry point or panics from libcore, formatted panics, and
-/// `Box<Any>` panics. Here we'll verify that we're not panicking recursively,
-/// run panic hooks, and then delegate to the actual implementation of panics.
-#[inline(never)]
-#[cold]
-fn rust_panic_with_hook(msg: Box<Any + Send>,
-                        file_line_col: &(&'static str, u32, u32)) -> ! {
+/// Executes the primary logic for a panic, including checking for recursive
+/// panics, panic hooks, and finally dispatching to the panic runtime to either
+/// abort or unwind.
+fn rust_panic_with_hook(payload: &mut dyn BoxMeUp,
+                        message: Option<&fmt::Arguments>,
+                        file_line_col: &(&str, u32, u32)) -> ! {
     let (file, line, col) = *file_line_col;
 
     let panics = update_panic_count(1);
@@ -563,18 +460,24 @@ fn rust_panic_with_hook(msg: Box<Any + Send>,
     }
 
     unsafe {
-        let info = PanicInfo {
-            payload: &*msg,
-            location: Location {
-                file,
-                line,
-                col,
-            },
-        };
+        let mut info = PanicInfo::internal_constructor(
+            message,
+            Location::internal_constructor(file, line, col),
+        );
         HOOK_LOCK.read();
         match HOOK {
-            Hook::Default => default_hook(&info),
-            Hook::Custom(ptr) => (*ptr)(&info),
+            // Some platforms know that printing to stderr won't ever actually
+            // print anything, and if that's the case we can skip the default
+            // hook.
+            Hook::Default if stderr_prints_nothing() => {}
+            Hook::Default => {
+                info.set_payload(payload.get());
+                default_hook(&info);
+            }
+            Hook::Custom(ptr) => {
+                info.set_payload(payload.get());
+                (*ptr)(&info);
+            }
         }
         HOOK_LOCK.read_unlock();
     }
@@ -589,22 +492,35 @@ fn rust_panic_with_hook(msg: Box<Any + Send>,
         unsafe { intrinsics::abort() }
     }
 
-    rust_panic(msg)
+    rust_panic(payload)
 }
 
 /// Shim around rust_panic. Called by resume_unwind.
-pub fn update_count_then_panic(msg: Box<Any + Send>) -> ! {
+pub fn update_count_then_panic(msg: Box<dyn Any + Send>) -> ! {
     update_panic_count(1);
-    rust_panic(msg)
+
+    struct RewrapBox(Box<dyn Any + Send>);
+
+    unsafe impl BoxMeUp for RewrapBox {
+        fn box_me_up(&mut self) -> *mut (dyn Any + Send) {
+            Box::into_raw(mem::replace(&mut self.0, Box::new(())))
+        }
+
+        fn get(&mut self) -> &(dyn Any + Send) {
+            &*self.0
+        }
+    }
+
+    rust_panic(&mut RewrapBox(msg))
 }
 
 /// A private no-mangle function on which to slap yer breakpoints.
 #[no_mangle]
 #[allow(private_no_mangle_fns)] // yes we get it, but we like breakpoints
-pub fn rust_panic(msg: Box<Any + Send>) -> ! {
+pub fn rust_panic(mut msg: &mut dyn BoxMeUp) -> ! {
     let code = unsafe {
-        let obj = mem::transmute::<_, raw::TraitObject>(msg);
-        __rust_start_panic(obj.data as usize, obj.vtable as usize)
+        let obj = &mut msg as *mut &mut dyn BoxMeUp;
+        __rust_start_panic(obj as usize)
     };
     rtabort!("failed to initiate panic, error {}", code)
 }
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index 7631a9a44bb..ca8be75fab5 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -297,10 +297,9 @@ pub const MAIN_SEPARATOR: char = ::sys::path::MAIN_SEP;
 // Iterate through `iter` while it matches `prefix`; return `None` if `prefix`
 // is not a prefix of `iter`, otherwise return `Some(iter_after_prefix)` giving
 // `iter` after having exhausted `prefix`.
-fn iter_after<A, I, J>(mut iter: I, mut prefix: J) -> Option<I>
-    where I: Iterator<Item = A> + Clone,
-          J: Iterator<Item = A>,
-          A: PartialEq
+fn iter_after<'a, 'b, I, J>(mut iter: I, mut prefix: J) -> Option<I>
+    where I: Iterator<Item = Component<'a>> + Clone,
+          J: Iterator<Item = Component<'b>>,
 {
     loop {
         let mut iter_next = iter.clone();
@@ -576,7 +575,7 @@ impl<'a> AsRef<OsStr> for Component<'a> {
     }
 }
 
-#[stable(feature = "path_component_asref", since = "1.24.0")]
+#[stable(feature = "path_component_asref", since = "1.25.0")]
 impl<'a> AsRef<Path> for Component<'a> {
     fn as_ref(&self) -> &Path {
         self.as_os_str().as_ref()
@@ -905,7 +904,7 @@ impl<'a> DoubleEndedIterator for Iter<'a> {
     }
 }
 
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
 impl<'a> FusedIterator for Iter<'a> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1008,7 +1007,7 @@ impl<'a> DoubleEndedIterator for Components<'a> {
     }
 }
 
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
 impl<'a> FusedIterator for Components<'a> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1035,6 +1034,45 @@ impl<'a> cmp::Ord for Components<'a> {
     }
 }
 
+/// An iterator over [`Path`] and its ancestors.
+///
+/// This `struct` is created by the [`ancestors`] method on [`Path`].
+/// See its documentation for more.
+///
+/// # Examples
+///
+/// ```
+/// use std::path::Path;
+///
+/// let path = Path::new("/foo/bar");
+///
+/// for ancestor in path.ancestors() {
+///     println!("{}", ancestor.display());
+/// }
+/// ```
+///
+/// [`ancestors`]: struct.Path.html#method.ancestors
+/// [`Path`]: struct.Path.html
+#[derive(Copy, Clone, Debug)]
+#[stable(feature = "path_ancestors", since = "1.28.0")]
+pub struct Ancestors<'a> {
+    next: Option<&'a Path>,
+}
+
+#[stable(feature = "path_ancestors", since = "1.28.0")]
+impl<'a> Iterator for Ancestors<'a> {
+    type Item = &'a Path;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let next = self.next;
+        self.next = next.and_then(Path::parent);
+        next
+    }
+}
+
+#[stable(feature = "path_ancestors", since = "1.28.0")]
+impl<'a> FusedIterator for Ancestors<'a> {}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Basic types and traits
 ////////////////////////////////////////////////////////////////////////////////
@@ -1369,6 +1407,14 @@ impl From<PathBuf> for Box<Path> {
     }
 }
 
+#[stable(feature = "more_box_slice_clone", since = "1.29.0")]
+impl Clone for Box<Path> {
+    #[inline]
+    fn clone(&self) -> Self {
+        self.to_path_buf().into_boxed_path()
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for PathBuf {
     fn from(s: &'a T) -> PathBuf {
@@ -1417,7 +1463,7 @@ impl<P: AsRef<Path>> iter::Extend<P> for PathBuf {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for PathBuf {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         fmt::Debug::fmt(&**self, formatter)
     }
 }
@@ -1461,6 +1507,22 @@ impl<'a> From<PathBuf> for Cow<'a, Path> {
     }
 }
 
+#[stable(feature = "cow_from_pathbuf_ref", since = "1.28.0")]
+impl<'a> From<&'a PathBuf> for Cow<'a, Path> {
+    #[inline]
+    fn from(p: &'a PathBuf) -> Cow<'a, Path> {
+        Cow::Borrowed(p.as_path())
+    }
+}
+
+#[stable(feature = "pathbuf_from_cow_path", since = "1.28.0")]
+impl<'a> From<Cow<'a, Path>> for PathBuf {
+    #[inline]
+    fn from(p: Cow<'a, Path>) -> Self {
+        p.into_owned()
+    }
+}
+
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<PathBuf> for Arc<Path> {
     #[inline]
@@ -1675,9 +1737,11 @@ impl Path {
 
     /// Converts a `Path` to a [`Cow<str>`].
     ///
-    /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
+    /// Any non-Unicode sequences are replaced with
+    /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
     ///
     /// [`Cow<str>`]: ../borrow/enum.Cow.html
+    /// [U+FFFD]: ../char/constant.REPLACEMENT_CHARACTER.html
     ///
     /// # Examples
     ///
@@ -1771,7 +1835,7 @@ impl Path {
     /// * On Unix, a path has a root if it begins with `/`.
     ///
     /// * On Windows, a path has a root if it:
-    ///     * has no prefix and begins with a separator, e.g. `\\windows`
+    ///     * has no prefix and begins with a separator, e.g. `\windows`
     ///     * has a prefix followed by a separator, e.g. `c:\windows` but not `c:windows`
     ///     * has any non-disk prefix, e.g. `\\server\share`
     ///
@@ -1820,12 +1884,41 @@ impl Path {
         })
     }
 
+    /// Produces an iterator over `Path` and its ancestors.
+    ///
+    /// The iterator will yield the `Path` that is returned if the [`parent`] method is used zero
+    /// or more times. That means, the iterator will yield `&self`, `&self.parent().unwrap()`,
+    /// `&self.parent().unwrap().parent().unwrap()` and so on. If the [`parent`] method returns
+    /// [`None`], the iterator will do likewise. The iterator will always yield at least one value,
+    /// namely `&self`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// let mut ancestors = Path::new("/foo/bar").ancestors();
+    /// assert_eq!(ancestors.next(), Some(Path::new("/foo/bar")));
+    /// assert_eq!(ancestors.next(), Some(Path::new("/foo")));
+    /// assert_eq!(ancestors.next(), Some(Path::new("/")));
+    /// assert_eq!(ancestors.next(), None);
+    /// ```
+    ///
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    /// [`parent`]: struct.Path.html#method.parent
+    #[stable(feature = "path_ancestors", since = "1.28.0")]
+    pub fn ancestors(&self) -> Ancestors {
+        Ancestors {
+            next: Some(&self),
+        }
+    }
+
     /// Returns the final component of the `Path`, if there is one.
     ///
     /// If the path is a normal file, this is the file name. If it's the path of a directory, this
     /// is the directory name.
     ///
-    /// Returns [`None`] If the path terminates in `..`.
+    /// Returns [`None`] if the path terminates in `..`.
     ///
     /// [`None`]: ../../std/option/enum.Option.html#variant.None
     ///
@@ -1865,24 +1958,31 @@ impl Path {
     /// # Examples
     ///
     /// ```
-    /// use std::path::Path;
+    /// use std::path::{Path, PathBuf};
     ///
     /// let path = Path::new("/test/haha/foo.txt");
     ///
+    /// assert_eq!(path.strip_prefix("/"), Ok(Path::new("test/haha/foo.txt")));
     /// assert_eq!(path.strip_prefix("/test"), Ok(Path::new("haha/foo.txt")));
+    /// assert_eq!(path.strip_prefix("/test/"), Ok(Path::new("haha/foo.txt")));
+    /// assert_eq!(path.strip_prefix("/test/haha/foo.txt"), Ok(Path::new("")));
+    /// assert_eq!(path.strip_prefix("/test/haha/foo.txt/"), Ok(Path::new("")));
     /// assert_eq!(path.strip_prefix("test").is_ok(), false);
     /// assert_eq!(path.strip_prefix("/haha").is_ok(), false);
+    ///
+    /// let prefix = PathBuf::from("/test/");
+    /// assert_eq!(path.strip_prefix(prefix), Ok(Path::new("haha/foo.txt")));
     /// ```
     #[stable(since = "1.7.0", feature = "path_strip_prefix")]
-    pub fn strip_prefix<'a, P: ?Sized>(&'a self, base: &'a P)
-                                       -> Result<&'a Path, StripPrefixError>
+    pub fn strip_prefix<P>(&self, base: P)
+                           -> Result<&Path, StripPrefixError>
         where P: AsRef<Path>
     {
         self._strip_prefix(base.as_ref())
     }
 
-    fn _strip_prefix<'a>(&'a self, base: &'a Path)
-                         -> Result<&'a Path, StripPrefixError> {
+    fn _strip_prefix(&self, base: &Path)
+                     -> Result<&Path, StripPrefixError> {
         iter_after(self.components(), base.components())
             .map(|c| c.as_path())
             .ok_or(StripPrefixError(()))
@@ -1900,6 +2000,9 @@ impl Path {
     /// let path = Path::new("/etc/passwd");
     ///
     /// assert!(path.starts_with("/etc"));
+    /// assert!(path.starts_with("/etc/"));
+    /// assert!(path.starts_with("/etc/passwd"));
+    /// assert!(path.starts_with("/etc/passwd/"));
     ///
     /// assert!(!path.starts_with("/e"));
     /// ```
@@ -2200,8 +2303,8 @@ impl Path {
         fs::symlink_metadata(self)
     }
 
-    /// Returns the canonical form of the path with all intermediate components
-    /// normalized and symbolic links resolved.
+    /// Returns the canonical, absolute form of the path with all intermediate
+    /// components normalized and symbolic links resolved.
     ///
     /// This is an alias to [`fs::canonicalize`].
     ///
diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs
index d256353ab30..53763da5e28 100644
--- a/src/libstd/prelude/v1.rs
+++ b/src/libstd/prelude/v1.rs
@@ -12,45 +12,68 @@
 //!
 //! See the [module-level documentation](../index.html) for more.
 
+
+
 #![stable(feature = "rust1", since = "1.0.0")]
 
 // Re-exported core operators
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use marker::{Copy, Send, Sized, Sync};
+#[doc(no_inline)]
+pub use marker::{Copy, Send, Sized, Sync};
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use ops::{Drop, Fn, FnMut, FnOnce};
+#[doc(no_inline)]
+pub use ops::{Drop, Fn, FnMut, FnOnce};
 
 // Re-exported functions
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use mem::drop;
-#[unstable(feature = "convert_id_prelude", issue = "0")]
 #[doc(no_inline)]
-pub use convert::id;
+pub use mem::drop;
 
 // Re-exported types and traits
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use boxed::Box;
+#[doc(no_inline)]
+pub use clone::Clone;
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use borrow::ToOwned;
+#[doc(no_inline)]
+pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use clone::Clone;
+#[doc(no_inline)]
+pub use convert::{AsRef, AsMut, Into, From};
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
+#[doc(no_inline)]
+pub use default::Default;
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use convert::{AsRef, AsMut, Into, From};
+#[doc(no_inline)]
+pub use iter::{Iterator, Extend, IntoIterator};
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use default::Default;
+#[doc(no_inline)]
+pub use iter::{DoubleEndedIterator, ExactSizeIterator};
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use iter::{Iterator, Extend, IntoIterator};
+#[doc(no_inline)]
+pub use option::Option::{self, Some, None};
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use iter::{DoubleEndedIterator, ExactSizeIterator};
+#[doc(no_inline)]
+pub use result::Result::{self, Ok, Err};
+
+
+// The file so far is equivalent to src/libcore/prelude/v1.rs,
+// and below to src/liballoc/prelude.rs.
+// Those files are duplicated rather than using glob imports
+// because we want docs to show these re-exports as pointing to within `std`.
+
+
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use option::Option::{self, Some, None};
+#[doc(no_inline)]
+pub use boxed::Box;
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use result::Result::{self, Ok, Err};
+#[doc(no_inline)]
+pub use borrow::ToOwned;
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use slice::SliceConcatExt;
+#[doc(no_inline)]
+pub use slice::SliceConcatExt;
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use string::{String, ToString};
+#[doc(no_inline)]
+pub use string::{String, ToString};
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use vec::Vec;
+#[doc(no_inline)]
+pub use vec::Vec;
diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs
index a2caf47e8cc..7074928eaf6 100644
--- a/src/libstd/primitive_docs.rs
+++ b/src/libstd/primitive_docs.rs
@@ -9,6 +9,8 @@
 // except according to those terms.
 
 #[doc(primitive = "bool")]
+#[doc(alias = "true")]
+#[doc(alias = "false")]
 //
 /// The boolean type.
 ///
@@ -68,6 +70,7 @@
 mod prim_bool { }
 
 #[doc(primitive = "never")]
+#[doc(alias = "!")]
 //
 /// The `!` type, also called "never".
 ///
@@ -113,6 +116,8 @@ mod prim_bool { }
 ///
 /// # `!` and generics
 ///
+/// ## Infallible errors
+///
 /// The main place you'll see `!` used explicitly is in generic code. Consider the [`FromStr`]
 /// trait:
 ///
@@ -131,17 +136,70 @@ mod prim_bool { }
 /// [`Result<String, !>`] which we can unpack like this:
 ///
 /// ```ignore (string-from-str-error-type-is-not-never-yet)
+/// #[feature(exhaustive_patterns)]
 /// // NOTE: This does not work today!
 /// let Ok(s) = String::from_str("hello");
 /// ```
 ///
-/// Since the [`Err`] variant contains a `!`, it can never occur. So we can exhaustively match on
-/// [`Result<T, !>`] by just taking the [`Ok`] variant. This illustrates another behaviour of `!` -
-/// it can be used to "delete" certain enum variants from generic types like `Result`.
+/// Since the [`Err`] variant contains a `!`, it can never occur. If the `exhaustive_patterns`
+/// feature is present this means we can exhaustively match on [`Result<T, !>`] by just taking the
+/// [`Ok`] variant. This illustrates another behaviour of `!` - it can be used to "delete" certain
+/// enum variants from generic types like `Result`.
+///
+/// ## Infinite loops
+///
+/// While [`Result<T, !>`] is very useful for removing errors, `!` can also be used to remove
+/// successes as well. If we think of [`Result<T, !>`] as "if this function returns, it has not
+/// errored," we get a very intuitive idea of [`Result<!, E>`] as well: if the function returns, it
+/// *has* errored.
+///
+/// For example, consider the case of a simple web server, which can be simplified to:
+///
+/// ```ignore (hypothetical-example)
+/// loop {
+///     let (client, request) = get_request().expect("disconnected");
+///     let response = request.process();
+///     response.send(client);
+/// }
+/// ```
+///
+/// Currently, this isn't ideal, because we simply panic whenever we fail to get a new connection.
+/// Instead, we'd like to keep track of this error, like this:
+///
+/// ```ignore (hypothetical-example)
+/// loop {
+///     match get_request() {
+///         Err(err) => break err,
+///         Ok((client, request)) => {
+///             let response = request.process();
+///             response.send(client);
+///         },
+///     }
+/// }
+/// ```
+///
+/// Now, when the server disconnects, we exit the loop with an error instead of panicking. While it
+/// might be intuitive to simply return the error, we might want to wrap it in a [`Result<!, E>`]
+/// instead:
+///
+/// ```ignore (hypothetical-example)
+/// fn server_loop() -> Result<!, ConnectionError> {
+///     loop {
+///         let (client, request) = get_request()?;
+///         let response = request.process();
+///         response.send(client);
+///     }
+/// }
+/// ```
+///
+/// Now, we can use `?` instead of `match`, and the return type makes a lot more sense: if the loop
+/// ever stops, it means that an error occurred. We don't even have to wrap the loop in an `Ok`
+/// because `!` coerces to `Result<!, ConnectionError>` automatically.
 ///
 /// [`String::from_str`]: str/trait.FromStr.html#tymethod.from_str
 /// [`Result<String, !>`]: result/enum.Result.html
 /// [`Result<T, !>`]: result/enum.Result.html
+/// [`Result<!, E>`]: result/enum.Result.html
 /// [`Ok`]: result/enum.Result.html#variant.Ok
 /// [`String`]: string/struct.String.html
 /// [`Err`]: result/enum.Result.html#variant.Err
@@ -154,7 +212,7 @@ mod prim_bool { }
 /// for example:
 ///
 /// ```
-/// # #![feature(never_type)]
+/// #![feature(never_type)]
 /// # use std::fmt;
 /// # trait Debug {
 /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result;
@@ -192,7 +250,6 @@ mod prim_bool { }
 /// [`Default`]: default/trait.Default.html
 /// [`default()`]: default/trait.Default.html#tymethod.default
 ///
-#[unstable(feature = "never_type", issue = "35121")]
 mod prim_never { }
 
 #[doc(primitive = "char")]
@@ -313,6 +370,8 @@ mod prim_unit { }
 //
 /// Raw, unsafe pointers, `*const T`, and `*mut T`.
 ///
+/// *[See also the `std::ptr` module](ptr/index.html).*
+///
 /// Working with raw pointers in Rust is uncommon,
 /// typically limited to a few patterns.
 ///
@@ -387,8 +446,6 @@ mod prim_unit { }
 /// but C APIs hand out a lot of pointers generally, so are a common source
 /// of raw pointers in Rust.
 ///
-/// *[See also the `std::ptr` module](ptr/index.html).*
-///
 /// [`null`]: ../std/ptr/fn.null.html
 /// [`null_mut`]: ../std/ptr/fn.null_mut.html
 /// [`is_null`]: ../std/primitive.pointer.html#method.is_null
@@ -500,9 +557,14 @@ mod prim_pointer { }
 mod prim_array { }
 
 #[doc(primitive = "slice")]
+#[doc(alias = "[")]
+#[doc(alias = "]")]
+#[doc(alias = "[]")]
 //
 /// A dynamically-sized view into a contiguous sequence, `[T]`.
 ///
+/// *[See also the `std::slice` module](slice/index.html).*
+///
 /// Slices are a view into a block of memory represented as a pointer and a
 /// length.
 ///
@@ -525,8 +587,6 @@ mod prim_array { }
 /// assert_eq!(x, &[1, 7, 3]);
 /// ```
 ///
-/// *[See also the `std::slice` module](slice/index.html).*
-///
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_slice { }
 
@@ -534,15 +594,13 @@ mod prim_slice { }
 //
 /// String slices.
 ///
+/// *[See also the `std::str` module](str/index.html).*
+///
 /// The `str` type, also called a 'string slice', is the most primitive string
 /// type. It is usually seen in its borrowed form, `&str`. It is also the type
 /// of string literals, `&'static str`.
 ///
-/// Strings slices are always valid UTF-8.
-///
-/// This documentation describes a number of methods and trait implementations
-/// on the `str` type. For technical reasons, there is additional, separate
-/// documentation in the [`std::str`](str/index.html) module as well.
+/// String slices are always valid UTF-8.
 ///
 /// # Examples
 ///
@@ -598,6 +656,9 @@ mod prim_slice { }
 mod prim_str { }
 
 #[doc(primitive = "tuple")]
+#[doc(alias = "(")]
+#[doc(alias = ")")]
+#[doc(alias = "()")]
 //
 /// A finite heterogeneous sequence, `(T, U, ..)`.
 ///
@@ -720,10 +781,6 @@ mod prim_f64 { }
 /// The 8-bit signed integer type.
 ///
 /// *[See also the `std::i8` module](i8/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `i64` in there.
-///
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_i8 { }
 
@@ -732,10 +789,6 @@ mod prim_i8 { }
 /// The 16-bit signed integer type.
 ///
 /// *[See also the `std::i16` module](i16/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `i32` in there.
-///
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_i16 { }
 
@@ -744,10 +797,6 @@ mod prim_i16 { }
 /// The 32-bit signed integer type.
 ///
 /// *[See also the `std::i32` module](i32/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `i16` in there.
-///
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_i32 { }
 
@@ -756,10 +805,6 @@ mod prim_i32 { }
 /// The 64-bit signed integer type.
 ///
 /// *[See also the `std::i64` module](i64/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `i8` in there.
-///
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_i64 { }
 
@@ -768,11 +813,7 @@ mod prim_i64 { }
 /// The 128-bit signed integer type.
 ///
 /// *[See also the `std::i128` module](i128/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `i8` in there.
-///
-#[unstable(feature = "i128", issue="35118")]
+#[stable(feature = "i128", since="1.26.0")]
 mod prim_i128 { }
 
 #[doc(primitive = "u8")]
@@ -780,10 +821,6 @@ mod prim_i128 { }
 /// The 8-bit unsigned integer type.
 ///
 /// *[See also the `std::u8` module](u8/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `u64` in there.
-///
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_u8 { }
 
@@ -792,10 +829,6 @@ mod prim_u8 { }
 /// The 16-bit unsigned integer type.
 ///
 /// *[See also the `std::u16` module](u16/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `u32` in there.
-///
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_u16 { }
 
@@ -804,10 +837,6 @@ mod prim_u16 { }
 /// The 32-bit unsigned integer type.
 ///
 /// *[See also the `std::u32` module](u32/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `u16` in there.
-///
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_u32 { }
 
@@ -816,10 +845,6 @@ mod prim_u32 { }
 /// The 64-bit unsigned integer type.
 ///
 /// *[See also the `std::u64` module](u64/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `u8` in there.
-///
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_u64 { }
 
@@ -828,26 +853,18 @@ mod prim_u64 { }
 /// The 128-bit unsigned integer type.
 ///
 /// *[See also the `std::u128` module](u128/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `u8` in there.
-///
-#[unstable(feature = "i128", issue="35118")]
+#[stable(feature = "i128", since="1.26.0")]
 mod prim_u128 { }
 
 #[doc(primitive = "isize")]
 //
 /// The pointer-sized signed integer type.
 ///
+/// *[See also the `std::isize` module](isize/index.html).*
+///
 /// The size of this primitive is how many bytes it takes to reference any
 /// location in memory. For example, on a 32 bit target, this is 4 bytes
 /// and on a 64 bit target, this is 8 bytes.
-///
-/// *[See also the `std::isize` module](isize/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `usize` in there.
-///
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_isize { }
 
@@ -855,19 +872,16 @@ mod prim_isize { }
 //
 /// The pointer-sized unsigned integer type.
 ///
+/// *[See also the `std::usize` module](usize/index.html).*
+///
 /// The size of this primitive is how many bytes it takes to reference any
 /// location in memory. For example, on a 32 bit target, this is 4 bytes
 /// and on a 64 bit target, this is 8 bytes.
-///
-/// *[See also the `std::usize` module](usize/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `isize` in there.
-///
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_usize { }
 
 #[doc(primitive = "reference")]
+#[doc(alias = "&")]
 //
 /// References, both shared and mutable.
 ///
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index 5c66ac6ddde..53babd449a9 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -381,6 +381,39 @@ impl fmt::Debug for ChildStderr {
 ///
 /// let hello = output.stdout;
 /// ```
+///
+/// `Command` can be reused to spawn multiple processes. The builder methods
+/// change the command without needing to immediately spawn the process.
+///
+/// ```no_run
+/// use std::process::Command;
+///
+/// let mut echo_hello = Command::new("sh");
+/// echo_hello.arg("-c")
+///           .arg("echo hello");
+/// let hello_1 = echo_hello.output().expect("failed to execute process");
+/// let hello_2 = echo_hello.output().expect("failed to execute process");
+/// ```
+///
+/// Similarly, you can call builder methods after spawning a process and then
+/// spawn a new process with the modified settings.
+///
+/// ```no_run
+/// use std::process::Command;
+///
+/// let mut list_dir = Command::new("ls");
+///
+/// // Execute `ls` in the current directory of the program.
+/// list_dir.status().expect("process failed to execute");
+///
+/// println!("");
+///
+/// // Change `ls` to execute in the root directory.
+/// list_dir.current_dir("/");
+///
+/// // And then execute `ls` again but in the root directory.
+/// list_dir.status().expect("process failed to execute");
+/// ```
 #[stable(feature = "process", since = "1.0.0")]
 pub struct Command {
     inner: imp::Command,
@@ -813,13 +846,13 @@ impl fmt::Debug for Output {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 
         let stdout_utf8 = str::from_utf8(&self.stdout);
-        let stdout_debug: &fmt::Debug = match stdout_utf8 {
+        let stdout_debug: &dyn fmt::Debug = match stdout_utf8 {
             Ok(ref str) => str,
             Err(_) => &self.stdout
         };
 
         let stderr_utf8 = str::from_utf8(&self.stderr);
-        let stderr_debug: &fmt::Debug = match stderr_utf8 {
+        let stderr_debug: &dyn fmt::Debug = match stderr_utf8 {
             Ok(ref str) => str,
             Err(_) => &self.stderr
         };
@@ -1080,9 +1113,54 @@ impl fmt::Display for ExitStatus {
     }
 }
 
+/// This type represents the status code a process can return to its
+/// parent under normal termination.
+///
+/// Numeric values used in this type don't have portable meanings, and
+/// different platforms may mask different amounts of them.
+///
+/// For the platform's canonical successful and unsuccessful codes, see
+/// the [`SUCCESS`] and [`FAILURE`] associated items.
+///
+/// [`SUCCESS`]: #associatedconstant.SUCCESS
+/// [`FAILURE`]: #associatedconstant.FAILURE
+///
+/// **Warning**: While various forms of this were discussed in [RFC #1937],
+/// it was ultimately cut from that RFC, and thus this type is more subject
+/// to change even than the usual unstable item churn.
+///
+/// [RFC #1937]: https://github.com/rust-lang/rfcs/pull/1937
+#[derive(Clone, Copy, Debug)]
+#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
+pub struct ExitCode(imp::ExitCode);
+
+#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
+impl ExitCode {
+    /// The canonical ExitCode for successful termination on this platform.
+    ///
+    /// Note that a `()`-returning `main` implicitly results in a successful
+    /// termination, so there's no need to return this from `main` unless
+    /// you're also returning other possible codes.
+    #[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
+    pub const SUCCESS: ExitCode = ExitCode(imp::ExitCode::SUCCESS);
+
+    /// The canonical ExitCode for unsuccessful termination on this platform.
+    ///
+    /// If you're only returning this and `SUCCESS` from `main`, consider
+    /// instead returning `Err(_)` and `Ok(())` respectively, which will
+    /// return the same codes (but will also `eprintln!` the error).
+    #[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
+    pub const FAILURE: ExitCode = ExitCode(imp::ExitCode::FAILURE);
+}
+
 impl Child {
-    /// Forces the child to exit. This is equivalent to sending a
-    /// SIGKILL on unix platforms.
+    /// Forces the child process to exit. If the child has already exited, an [`InvalidInput`]
+    /// error is returned.
+    ///
+    /// The mapping to [`ErrorKind`]s is not part of the compatibility contract of the function,
+    /// especially the [`Other`] kind might change to more specific kinds in the future.
+    ///
+    /// This is equivalent to sending a SIGKILL on Unix platforms.
     ///
     /// # Examples
     ///
@@ -1098,6 +1176,10 @@ impl Child {
     ///     println!("yes command didn't start");
     /// }
     /// ```
+    ///
+    /// [`ErrorKind`]: ../io/enum.ErrorKind.html
+    /// [`InvalidInput`]: ../io/enum.ErrorKind.html#variant.InvalidInput
+    /// [`Other`]: ../io/enum.ErrorKind.html#variant.Other
     #[stable(feature = "process", since = "1.0.0")]
     pub fn kill(&mut self) -> io::Result<()> {
         self.handle.kill()
@@ -1380,18 +1462,74 @@ pub fn abort() -> ! {
 /// Basic usage:
 ///
 /// ```no_run
-/// #![feature(getpid)]
 /// use std::process;
 ///
 /// println!("My pid is {}", process::id());
 /// ```
 ///
 ///
-#[unstable(feature = "getpid", issue = "44971", reason = "recently added")]
+#[stable(feature = "getpid", since = "1.26.0")]
 pub fn id() -> u32 {
     ::sys::os::getpid()
 }
 
+/// A trait for implementing arbitrary return types in the `main` function.
+///
+/// The c-main function only supports to return integers as return type.
+/// So, every type implementing the `Termination` trait has to be converted
+/// to an integer.
+///
+/// The default implementations are returning `libc::EXIT_SUCCESS` to indicate
+/// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned.
+#[cfg_attr(not(test), lang = "termination")]
+#[unstable(feature = "termination_trait_lib", issue = "43301")]
+#[rustc_on_unimplemented(
+  message="`main` has invalid return type `{Self}`",
+  label="`main` can only return types that implement `{Termination}`")]
+pub trait Termination {
+    /// Is called to get the representation of the value as status code.
+    /// This status code is returned to the operating system.
+    fn report(self) -> i32;
+}
+
+#[unstable(feature = "termination_trait_lib", issue = "43301")]
+impl Termination for () {
+    #[inline]
+    fn report(self) -> i32 { ExitCode::SUCCESS.report() }
+}
+
+#[unstable(feature = "termination_trait_lib", issue = "43301")]
+impl<E: fmt::Debug> Termination for Result<(), E> {
+    fn report(self) -> i32 {
+        match self {
+            Ok(()) => ().report(),
+            Err(err) => Err::<!, _>(err).report(),
+        }
+    }
+}
+
+#[unstable(feature = "termination_trait_lib", issue = "43301")]
+impl Termination for ! {
+    fn report(self) -> i32 { self }
+}
+
+#[unstable(feature = "termination_trait_lib", issue = "43301")]
+impl<E: fmt::Debug> Termination for Result<!, E> {
+    fn report(self) -> i32 {
+        let Err(err) = self;
+        eprintln!("Error: {:?}", err);
+        ExitCode::FAILURE.report()
+    }
+}
+
+#[unstable(feature = "termination_trait_lib", issue = "43301")]
+impl Termination for ExitCode {
+    #[inline]
+    fn report(self) -> i32 {
+        self.0.as_i32()
+    }
+}
+
 #[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
 mod tests {
     use io::prelude::*;
@@ -1843,4 +1981,10 @@ mod tests {
         }
         assert!(events > 0);
     }
+
+    #[test]
+    fn test_command_implements_send() {
+        fn take_send_type<T: Send>(_: T) {}
+        take_send_type(Command::new(""))
+    }
 }
diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs
index 9dbaf784f89..9e957bd87d7 100644
--- a/src/libstd/rt.rs
+++ b/src/libstd/rt.rs
@@ -29,7 +29,7 @@ pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count};
 // To reduce the generated code of the new `lang_start`, this function is doing
 // the real work.
 #[cfg(not(test))]
-fn lang_start_internal(main: &(Fn() -> i32 + Sync + ::panic::RefUnwindSafe),
+fn lang_start_internal(main: &(dyn Fn() -> i32 + Sync + ::panic::RefUnwindSafe),
                        argc: isize, argv: *const *const u8) -> isize {
     use panic;
     use sys;
@@ -68,8 +68,23 @@ fn lang_start_internal(main: &(Fn() -> i32 + Sync + ::panic::RefUnwindSafe),
 
 #[cfg(not(test))]
 #[lang = "start"]
-fn lang_start<T: ::termination::Termination + 'static>
+fn lang_start<T: ::process::Termination + 'static>
     (main: fn() -> T, argc: isize, argv: *const *const u8) -> isize
 {
     lang_start_internal(&move || main().report(), argc, argv)
 }
+
+/// Function used for reverting changes to the main stack before setrlimit().
+/// This is POSIX (non-Linux) specific and unlikely to be directly stabilized.
+#[unstable(feature = "rustc_stack_internals", issue = "0")]
+pub unsafe fn deinit_stack_guard() {
+    ::sys::thread::guard::deinit();
+}
+
+/// Function used for resetting the main stack guard address after setrlimit().
+/// This is POSIX specific and unlikely to be directly stabilized.
+#[unstable(feature = "rustc_stack_internals", issue = "0")]
+pub unsafe fn update_stack_guard() {
+    let main_guard = ::sys::thread::guard::init();
+    ::sys_common::thread_info::reset_guard(main_guard);
+}
diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs
index 56402175817..3014283da5b 100644
--- a/src/libstd/sync/condvar.rs
+++ b/src/libstd/sync/condvar.rs
@@ -14,7 +14,7 @@ use sync::{mutex, MutexGuard, PoisonError};
 use sys_common::condvar as sys;
 use sys_common::mutex as sys_mutex;
 use sys_common::poison::{self, LockResult};
-use time::Duration;
+use time::{Duration, Instant};
 
 /// A type indicating whether a timed wait on a condition variable returned
 /// due to a time out or not.
@@ -47,11 +47,13 @@ impl WaitTimeoutResult {
     ///
     /// thread::spawn(move|| {
     ///     let &(ref lock, ref cvar) = &*pair2;
+    ///
+    ///     // Let's wait 20 milliseconds before notifying the condvar.
+    ///     thread::sleep(Duration::from_millis(20));
+    ///
     ///     let mut started = lock.lock().unwrap();
     ///     // We update the boolean value.
     ///     *started = true;
-    ///     // Let's wait 20 milliseconds before notifying the condvar.
-    ///     thread::sleep(Duration::from_millis(20));
     ///     cvar.notify_one();
     /// });
     ///
@@ -219,6 +221,64 @@ impl Condvar {
         }
     }
 
+    /// Blocks the current thread until this condition variable receives a
+    /// notification and the required condition is met. Spurious wakeups are
+    /// ignored and this function will only return once the condition has been
+    /// met.
+    ///
+    /// This function will atomically unlock the mutex specified (represented by
+    /// `guard`) and block the current thread. This means that any calls
+    /// to [`notify_one`] or [`notify_all`] which happen logically after the
+    /// mutex is unlocked are candidates to wake this thread up. When this
+    /// function call returns, the lock specified will have been re-acquired.
+    ///
+    /// # Errors
+    ///
+    /// This function will return an error if the mutex being waited on is
+    /// poisoned when this thread re-acquires the lock. For more information,
+    /// see information about [poisoning] on the [`Mutex`] type.
+    ///
+    /// [`notify_one`]: #method.notify_one
+    /// [`notify_all`]: #method.notify_all
+    /// [poisoning]: ../sync/struct.Mutex.html#poisoning
+    /// [`Mutex`]: ../sync/struct.Mutex.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(wait_until)]
+    ///
+    /// use std::sync::{Arc, Mutex, Condvar};
+    /// use std::thread;
+    ///
+    /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
+    /// let pair2 = pair.clone();
+    ///
+    /// thread::spawn(move|| {
+    ///     let &(ref lock, ref cvar) = &*pair2;
+    ///     let mut started = lock.lock().unwrap();
+    ///     *started = true;
+    ///     // We notify the condvar that the value has changed.
+    ///     cvar.notify_one();
+    /// });
+    ///
+    /// // Wait for the thread to start up.
+    /// let &(ref lock, ref cvar) = &*pair;
+    /// // As long as the value inside the `Mutex` is false, we wait.
+    /// let _guard = cvar.wait_until(lock.lock().unwrap(), |started| { *started }).unwrap();
+    /// ```
+    #[unstable(feature = "wait_until", issue = "47960")]
+    pub fn wait_until<'a, T, F>(&self, mut guard: MutexGuard<'a, T>,
+                                mut condition: F)
+                                -> LockResult<MutexGuard<'a, T>>
+                                where F: FnMut(&mut T) -> bool {
+        while !condition(&mut *guard) {
+            guard = self.wait(guard)?;
+        }
+        Ok(guard)
+    }
+
+
     /// Waits on this condition variable for a notification, timing out after a
     /// specified duration.
     ///
@@ -293,7 +353,15 @@ impl Condvar {
     ///
     /// Note that the best effort is made to ensure that the time waited is
     /// measured with a monotonic clock, and not affected by the changes made to
-    /// the system time.
+    /// the system time.  This function is susceptible to spurious wakeups.
+    /// Condition variables normally have a boolean predicate associated with
+    /// them, and the predicate must always be checked each time this function
+    /// returns to protect against spurious wakeups.  Additionally, it is
+    /// typically desirable for the time-out to not exceed some duration in
+    /// spite of spurious wakes, thus the sleep-duration is decremented by the
+    /// amount slept.  Alternatively, use the `wait_timeout_until` method
+    /// to wait until a condition is met with a total time-out regardless
+    /// of spurious wakes.
     ///
     /// The returned [`WaitTimeoutResult`] value indicates if the timeout is
     /// known to have elapsed.
@@ -302,6 +370,7 @@ impl Condvar {
     /// returns, regardless of whether the timeout elapsed or not.
     ///
     /// [`wait`]: #method.wait
+    /// [`wait_timeout_until`]: #method.wait_timeout_until
     /// [`WaitTimeoutResult`]: struct.WaitTimeoutResult.html
     ///
     /// # Examples
@@ -353,6 +422,80 @@ impl Condvar {
         }
     }
 
+    /// Waits on this condition variable for a notification, timing out after a
+    /// specified duration.  Spurious wakes will not cause this function to
+    /// return.
+    ///
+    /// The semantics of this function are equivalent to [`wait_until`] except
+    /// that the thread will be blocked for roughly no longer than `dur`. This
+    /// method should not be used for precise timing due to anomalies such as
+    /// preemption or platform differences that may not cause the maximum
+    /// amount of time waited to be precisely `dur`.
+    ///
+    /// Note that the best effort is made to ensure that the time waited is
+    /// measured with a monotonic clock, and not affected by the changes made to
+    /// the system time.
+    ///
+    /// The returned [`WaitTimeoutResult`] value indicates if the timeout is
+    /// known to have elapsed without the condition being met.
+    ///
+    /// Like [`wait_until`], the lock specified will be re-acquired when this
+    /// function returns, regardless of whether the timeout elapsed or not.
+    ///
+    /// [`wait_until`]: #method.wait_until
+    /// [`wait_timeout`]: #method.wait_timeout
+    /// [`WaitTimeoutResult`]: struct.WaitTimeoutResult.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(wait_timeout_until)]
+    ///
+    /// use std::sync::{Arc, Mutex, Condvar};
+    /// use std::thread;
+    /// use std::time::Duration;
+    ///
+    /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
+    /// let pair2 = pair.clone();
+    ///
+    /// thread::spawn(move|| {
+    ///     let &(ref lock, ref cvar) = &*pair2;
+    ///     let mut started = lock.lock().unwrap();
+    ///     *started = true;
+    ///     // We notify the condvar that the value has changed.
+    ///     cvar.notify_one();
+    /// });
+    ///
+    /// // wait for the thread to start up
+    /// let &(ref lock, ref cvar) = &*pair;
+    /// let result = cvar.wait_timeout_until(
+    ///     lock.lock().unwrap(),
+    ///     Duration::from_millis(100),
+    ///     |&mut started| started,
+    /// ).unwrap();
+    /// if result.1.timed_out() {
+    ///     // timed-out without the condition ever evaluating to true.
+    /// }
+    /// // access the locked mutex via result.0
+    /// ```
+    #[unstable(feature = "wait_timeout_until", issue = "47960")]
+    pub fn wait_timeout_until<'a, T, F>(&self, mut guard: MutexGuard<'a, T>,
+                                        dur: Duration, mut condition: F)
+                                        -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)>
+                                        where F: FnMut(&mut T) -> bool {
+        let start = Instant::now();
+        loop {
+            if condition(&mut *guard) {
+                return Ok((guard, WaitTimeoutResult(false)));
+            }
+            let timeout = match dur.checked_sub(start.elapsed()) {
+                Some(timeout) => timeout,
+                None => return Ok((guard, WaitTimeoutResult(true))),
+            };
+            guard = self.wait_timeout(guard, timeout)?.0;
+        }
+    }
+
     /// Wakes up one blocked thread on this condvar.
     ///
     /// If there is a blocked thread on this condition variable, then it will
@@ -478,6 +621,7 @@ impl Drop for Condvar {
 
 #[cfg(test)]
 mod tests {
+    /// #![feature(wait_until)]
     use sync::mpsc::channel;
     use sync::{Condvar, Mutex, Arc};
     use sync::atomic::{AtomicBool, Ordering};
@@ -548,6 +692,29 @@ mod tests {
 
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
+    fn wait_until() {
+        let pair = Arc::new((Mutex::new(false), Condvar::new()));
+        let pair2 = pair.clone();
+
+        // Inside of our lock, spawn a new thread, and then wait for it to start.
+        thread::spawn(move|| {
+            let &(ref lock, ref cvar) = &*pair2;
+            let mut started = lock.lock().unwrap();
+            *started = true;
+            // We notify the condvar that the value has changed.
+            cvar.notify_one();
+        });
+
+        // Wait for the thread to start up.
+        let &(ref lock, ref cvar) = &*pair;
+        let guard = cvar.wait_until(lock.lock().unwrap(), |started| {
+            *started
+        });
+        assert!(*guard.unwrap());
+    }
+
+    #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn wait_timeout_wait() {
         let m = Arc::new(Mutex::new(()));
         let c = Arc::new(Condvar::new());
@@ -567,6 +734,53 @@ mod tests {
 
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
+    fn wait_timeout_until_wait() {
+        let m = Arc::new(Mutex::new(()));
+        let c = Arc::new(Condvar::new());
+
+        let g = m.lock().unwrap();
+        let (_g, wait) = c.wait_timeout_until(g, Duration::from_millis(1), |_| { false }).unwrap();
+        // no spurious wakeups. ensure it timed-out
+        assert!(wait.timed_out());
+    }
+
+    #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
+    fn wait_timeout_until_instant_satisfy() {
+        let m = Arc::new(Mutex::new(()));
+        let c = Arc::new(Condvar::new());
+
+        let g = m.lock().unwrap();
+        let (_g, wait) = c.wait_timeout_until(g, Duration::from_millis(0), |_| { true }).unwrap();
+        // ensure it didn't time-out even if we were not given any time.
+        assert!(!wait.timed_out());
+    }
+
+    #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
+    fn wait_timeout_until_wake() {
+        let pair = Arc::new((Mutex::new(false), Condvar::new()));
+        let pair_copy = pair.clone();
+
+        let &(ref m, ref c) = &*pair;
+        let g = m.lock().unwrap();
+        let _t = thread::spawn(move || {
+            let &(ref lock, ref cvar) = &*pair_copy;
+            let mut started = lock.lock().unwrap();
+            thread::sleep(Duration::from_millis(1));
+            *started = true;
+            cvar.notify_one();
+        });
+        let (g2, wait) = c.wait_timeout_until(g, Duration::from_millis(u64::MAX), |&mut notified| {
+            notified
+        }).unwrap();
+        // ensure it didn't time-out even if we were not given any time.
+        assert!(!wait.timed_out());
+        assert!(*g2);
+    }
+
+    #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn wait_timeout_wake() {
         let m = Arc::new(Mutex::new(()));
         let c = Arc::new(Condvar::new());
diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs
index 289b47b3484..e12ef8d9eda 100644
--- a/src/libstd/sync/mod.rs
+++ b/src/libstd/sync/mod.rs
@@ -18,7 +18,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::arc::{Arc, Weak};
+pub use alloc_crate::sync::{Arc, Weak};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::sync::atomic;
 
diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs
index 2dd3aebe610..59cf741487e 100644
--- a/src/libstd/sync/mpsc/mod.rs
+++ b/src/libstd/sync/mpsc/mod.rs
@@ -689,7 +689,7 @@ impl<T> UnsafeFlavor<T> for Receiver<T> {
 /// only one [`Receiver`] is supported.
 ///
 /// If the [`Receiver`] is disconnected while trying to [`send`] with the
-/// [`Sender`], the [`send`] method will return a [`SendError`]. Similarly, If the
+/// [`Sender`], the [`send`] method will return a [`SendError`]. Similarly, if the
 /// [`Sender`] is disconnected while trying to [`recv`], the [`recv`] method will
 /// return a [`RecvError`].
 ///
@@ -1247,6 +1247,34 @@ impl<T> Receiver<T> {
     /// [`SyncSender`]: struct.SyncSender.html
     /// [`Err`]: ../../../std/result/enum.Result.html#variant.Err
     ///
+    /// # Known Issues
+    ///
+    /// There is currently a known issue (see [`#39364`]) that causes `recv_timeout`
+    /// to panic unexpectedly with the following example:
+    ///
+    /// ```no_run
+    /// use std::sync::mpsc::channel;
+    /// use std::thread;
+    /// use std::time::Duration;
+    ///
+    /// let (tx, rx) = channel::<String>();
+    ///
+    /// thread::spawn(move || {
+    ///     let d = Duration::from_millis(10);
+    ///     loop {
+    ///         println!("recv");
+    ///         let _r = rx.recv_timeout(d);
+    ///     }
+    /// });
+    ///
+    /// thread::sleep(Duration::from_millis(100));
+    /// let _c1 = tx.clone();
+    ///
+    /// thread::sleep(Duration::from_secs(1));
+    /// ```
+    ///
+    /// [`#39364`]: https://github.com/rust-lang/rust/issues/39364
+    ///
     /// # Examples
     ///
     /// Successfully receiving value before encountering timeout:
@@ -1638,7 +1666,7 @@ impl<T: Send> error::Error for SendError<T> {
         "sending on a closed channel"
     }
 
-    fn cause(&self) -> Option<&error::Error> {
+    fn cause(&self) -> Option<&dyn error::Error> {
         None
     }
 }
@@ -1681,7 +1709,7 @@ impl<T: Send> error::Error for TrySendError<T> {
         }
     }
 
-    fn cause(&self) -> Option<&error::Error> {
+    fn cause(&self) -> Option<&dyn error::Error> {
         None
     }
 }
@@ -1709,7 +1737,7 @@ impl error::Error for RecvError {
         "receiving on a closed channel"
     }
 
-    fn cause(&self) -> Option<&error::Error> {
+    fn cause(&self) -> Option<&dyn error::Error> {
         None
     }
 }
@@ -1742,7 +1770,7 @@ impl error::Error for TryRecvError {
         }
     }
 
-    fn cause(&self) -> Option<&error::Error> {
+    fn cause(&self) -> Option<&dyn error::Error> {
         None
     }
 }
@@ -1783,7 +1811,7 @@ impl error::Error for RecvTimeoutError {
         }
     }
 
-    fn cause(&self) -> Option<&error::Error> {
+    fn cause(&self) -> Option<&dyn error::Error> {
         None
     }
 }
diff --git a/src/libstd/sync/mpsc/mpsc_queue.rs b/src/libstd/sync/mpsc/mpsc_queue.rs
index 296773d20f6..df945ac3859 100644
--- a/src/libstd/sync/mpsc/mpsc_queue.rs
+++ b/src/libstd/sync/mpsc/mpsc_queue.rs
@@ -23,10 +23,9 @@
 
 pub use self::PopResult::*;
 
-use alloc::boxed::Box;
 use core::ptr;
 use core::cell::UnsafeCell;
-
+use boxed::Box;
 use sync::atomic::{AtomicPtr, Ordering};
 
 /// A result of the `pop` function.
diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs
index a9f3cea243f..a7a284cfb79 100644
--- a/src/libstd/sync/mpsc/select.rs
+++ b/src/libstd/sync/mpsc/select.rs
@@ -93,7 +93,7 @@ pub struct Handle<'rx, T:Send+'rx> {
     next: *mut Handle<'static, ()>,
     prev: *mut Handle<'static, ()>,
     added: bool,
-    packet: &'rx (Packet+'rx),
+    packet: &'rx (dyn Packet+'rx),
 
     // due to our fun transmutes, we be sure to place this at the end. (nothing
     // previous relies on T)
@@ -518,6 +518,7 @@ mod tests {
         }
     }
 
+    #[allow(unused_must_use)]
     #[test]
     fn cloning() {
         let (tx1, rx1) = channel::<i32>();
@@ -540,6 +541,7 @@ mod tests {
         tx3.send(()).unwrap();
     }
 
+    #[allow(unused_must_use)]
     #[test]
     fn cloning2() {
         let (tx1, rx1) = channel::<i32>();
diff --git a/src/libstd/sync/mpsc/spsc_queue.rs b/src/libstd/sync/mpsc/spsc_queue.rs
index cc4be92276a..9482f6958b3 100644
--- a/src/libstd/sync/mpsc/spsc_queue.rs
+++ b/src/libstd/sync/mpsc/spsc_queue.rs
@@ -16,7 +16,7 @@
 
 // http://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue
 
-use alloc::boxed::Box;
+use boxed::Box;
 use core::ptr;
 use core::cell::UnsafeCell;
 
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index 3b4904c98e8..e5a410644b9 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -150,7 +150,7 @@ unsafe impl<T: ?Sized + Send> Sync for Mutex<T> { }
 /// [`lock`]: struct.Mutex.html#method.lock
 /// [`try_lock`]: struct.Mutex.html#method.try_lock
 /// [`Mutex`]: struct.Mutex.html
-#[must_use]
+#[must_use = "if unused the Mutex will immediately unlock"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct MutexGuard<'a, T: ?Sized + 'a> {
     // funny underscores due to how Deref/DerefMut currently work (they
@@ -227,7 +227,7 @@ impl<T: ?Sized> Mutex<T> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn lock(&self) -> LockResult<MutexGuard<T>> {
         unsafe {
-            self.inner.lock();
+            self.inner.raw_lock();
             MutexGuard::new(self)
         }
     }
@@ -454,7 +454,7 @@ impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> {
     fn drop(&mut self) {
         unsafe {
             self.__lock.poison.done(&self.__poison);
-            self.__lock.inner.unlock();
+            self.__lock.inner.raw_unlock();
         }
     }
 }
diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs
index 6fd8b6a5bba..f6cb8beae84 100644
--- a/src/libstd/sync/once.rs
+++ b/src/libstd/sync/once.rs
@@ -31,12 +31,10 @@
 // initialization closure panics, the Once enters a "poisoned" state which means
 // that all future calls will immediately panic as well.
 //
-// So to implement this, one might first reach for a `StaticMutex`, but those
-// unfortunately need to be deallocated (e.g. call `destroy()`) to free memory
-// on all OSes (some of the BSDs allocate memory for mutexes). It also gets a
-// lot harder with poisoning to figure out when the mutex needs to be
-// deallocated because it's not after the closure finishes, but after the first
-// successful closure finishes.
+// So to implement this, one might first reach for a `Mutex`, but those cannot
+// be put into a `static`. It also gets a lot harder with poisoning to figure
+// out when the mutex needs to be deallocated because it's not after the closure
+// finishes, but after the first successful closure finishes.
 //
 // All in all, this is instead implemented with atomics and lock-free
 // operations! Whee! Each `Once` has one word of atomic state, and this state is
@@ -73,16 +71,17 @@ use thread::{self, Thread};
 /// A synchronization primitive which can be used to run a one-time global
 /// initialization. Useful for one-time initialization for FFI or related
 /// functionality. This type can only be constructed with the [`ONCE_INIT`]
-/// value.
+/// value or the equivalent [`Once::new`] constructor.
 ///
 /// [`ONCE_INIT`]: constant.ONCE_INIT.html
+/// [`Once::new`]: struct.Once.html#method.new
 ///
 /// # Examples
 ///
 /// ```
-/// use std::sync::{Once, ONCE_INIT};
+/// use std::sync::Once;
 ///
-/// static START: Once = ONCE_INIT;
+/// static START: Once = Once::new();
 ///
 /// START.call_once(|| {
 ///     // run initialization here
@@ -148,9 +147,9 @@ struct Waiter {
 
 // Helper struct used to clean up after a closure call with a `Drop`
 // implementation to also run on panic.
-struct Finish {
+struct Finish<'a> {
     panicked: bool,
-    me: &'static Once,
+    me: &'a Once,
 }
 
 impl Once {
@@ -177,13 +176,17 @@ impl Once {
     /// happens-before relation between the closure and code executing after the
     /// return).
     ///
+    /// If the given closure recusively invokes `call_once` on the same `Once`
+    /// instance the exact behavior is not specified, allowed outcomes are
+    /// a panic or a deadlock.
+    ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::{Once, ONCE_INIT};
+    /// use std::sync::Once;
     ///
     /// static mut VAL: usize = 0;
-    /// static INIT: Once = ONCE_INIT;
+    /// static INIT: Once = Once::new();
     ///
     /// // Accessing a `static mut` is unsafe much of the time, but if we do so
     /// // in a synchronized fashion (e.g. write once or read all) then we're
@@ -217,9 +220,13 @@ impl Once {
     ///
     /// [poison]: struct.Mutex.html#poisoning
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn call_once<F>(&'static self, f: F) where F: FnOnce() {
+    pub fn call_once<F>(&self, f: F) where F: FnOnce() {
         // Fast path, just see if we've completed initialization.
-        if self.state.load(Ordering::SeqCst) == COMPLETE {
+        // An `Acquire` load is enough because that makes all the initialization
+        // operations visible to us. The cold path uses SeqCst consistently
+        // because the performance difference really does not matter there,
+        // and SeqCst minimizes the chances of something going wrong.
+        if self.state.load(Ordering::Acquire) == COMPLETE {
             return
         }
 
@@ -248,10 +255,10 @@ impl Once {
     /// ```
     /// #![feature(once_poison)]
     ///
-    /// use std::sync::{Once, ONCE_INIT};
+    /// use std::sync::Once;
     /// use std::thread;
     ///
-    /// static INIT: Once = ONCE_INIT;
+    /// static INIT: Once = Once::new();
     ///
     /// // poison the once
     /// let handle = thread::spawn(|| {
@@ -274,9 +281,13 @@ impl Once {
     /// INIT.call_once(|| {});
     /// ```
     #[unstable(feature = "once_poison", issue = "33577")]
-    pub fn call_once_force<F>(&'static self, f: F) where F: FnOnce(&OnceState) {
+    pub fn call_once_force<F>(&self, f: F) where F: FnOnce(&OnceState) {
         // same as above, just with a different parameter to `call_inner`.
-        if self.state.load(Ordering::SeqCst) == COMPLETE {
+        // An `Acquire` load is enough because that makes all the initialization
+        // operations visible to us. The cold path uses SeqCst consistently
+        // because the performance difference really does not matter there,
+        // and SeqCst minimizes the chances of something going wrong.
+        if self.state.load(Ordering::Acquire) == COMPLETE {
             return
         }
 
@@ -298,9 +309,9 @@ impl Once {
     // currently no way to take an `FnOnce` and call it via virtual dispatch
     // without some allocation overhead.
     #[cold]
-    fn call_inner(&'static self,
+    fn call_inner(&self,
                   ignore_poisoning: bool,
-                  init: &mut FnMut(bool)) {
+                  init: &mut dyn FnMut(bool)) {
         let mut state = self.state.load(Ordering::SeqCst);
 
         'outer: loop {
@@ -389,7 +400,7 @@ impl fmt::Debug for Once {
     }
 }
 
-impl Drop for Finish {
+impl<'a> Drop for Finish<'a> {
     fn drop(&mut self) {
         // Swap out our state with however we finished. We should only ever see
         // an old state which was RUNNING.
@@ -431,10 +442,10 @@ impl OnceState {
     /// ```
     /// #![feature(once_poison)]
     ///
-    /// use std::sync::{Once, ONCE_INIT};
+    /// use std::sync::Once;
     /// use std::thread;
     ///
-    /// static INIT: Once = ONCE_INIT;
+    /// static INIT: Once = Once::new();
     ///
     /// // poison the once
     /// let handle = thread::spawn(|| {
@@ -452,9 +463,9 @@ impl OnceState {
     /// ```
     /// #![feature(once_poison)]
     ///
-    /// use std::sync::{Once, ONCE_INIT};
+    /// use std::sync::Once;
     ///
-    /// static INIT: Once = ONCE_INIT;
+    /// static INIT: Once = Once::new();
     ///
     /// INIT.call_once_force(|state| {
     ///     assert!(!state.poisoned());
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
index 2edf02efc47..e3db60cff84 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -24,8 +24,8 @@ use sys_common::rwlock as sys;
 /// typically allows for read-only access (shared access).
 ///
 /// In comparison, a [`Mutex`] does not distinguish between readers or writers
-/// that aquire the lock, therefore blocking any threads waiting for the lock to
-/// become available. An `RwLock` will allow any number of readers to aquire the
+/// that acquire the lock, therefore blocking any threads waiting for the lock to
+/// become available. An `RwLock` will allow any number of readers to acquire the
 /// lock as long as a writer is not holding the lock.
 ///
 /// The priority policy of the lock is dependent on the underlying operating
@@ -94,7 +94,7 @@ unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {}
 /// [`read`]: struct.RwLock.html#method.read
 /// [`try_read`]: struct.RwLock.html#method.try_read
 /// [`RwLock`]: struct.RwLock.html
-#[must_use]
+#[must_use = "if unused the RwLock will immediately unlock"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
     __lock: &'a RwLock<T>,
@@ -115,7 +115,7 @@ unsafe impl<'a, T: ?Sized + Sync> Sync for RwLockReadGuard<'a, T> {}
 /// [`write`]: struct.RwLock.html#method.write
 /// [`try_write`]: struct.RwLock.html#method.try_write
 /// [`RwLock`]: struct.RwLock.html
-#[must_use]
+#[must_use = "if unused the RwLock will immediately unlock"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
     __lock: &'a RwLock<T>,
diff --git a/src/libstd/sys/cloudabi/abi/cloudabi.rs b/src/libstd/sys/cloudabi/abi/cloudabi.rs
index 2909db5098e..cd9a5ad448f 100644
--- a/src/libstd/sys/cloudabi/abi/cloudabi.rs
+++ b/src/libstd/sys/cloudabi/abi/cloudabi.rs
@@ -121,6 +121,7 @@ include!("bitflags.rs");
 /// File or memory access pattern advisory information.
 #[repr(u8)]
 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
 pub enum advice {
   /// The application expects that it will not access the
   /// specified data in the near future.
@@ -140,12 +141,12 @@ pub enum advice {
   /// The application expects to access the specified data
   /// in the near future.
   WILLNEED   = 6,
-  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
 }
 
 /// Enumeration describing the kind of value stored in [`auxv`](struct.auxv.html).
 #[repr(u32)]
 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
 pub enum auxtype {
   /// Base address of the binary argument data provided to
   /// [`proc_exec()`](fn.proc_exec.html).
@@ -210,12 +211,12 @@ pub enum auxtype {
   SYSINFO_EHDR = 262,
   /// Thread ID of the initial thread of the process.
   TID          = 261,
-  #[doc(hidden)] _NonExhaustive = -1 as isize as u32,
 }
 
 /// Identifiers for clocks.
 #[repr(u32)]
 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
 pub enum clockid {
   /// The system-wide monotonic clock, which is defined as a
   /// clock measuring real time, whose value cannot be
@@ -232,7 +233,6 @@ pub enum clockid {
   REALTIME           = 3,
   /// The CPU-time clock associated with the current thread.
   THREAD_CPUTIME_ID  = 4,
-  #[doc(hidden)] _NonExhaustive = -1 as isize as u32,
 }
 
 /// A userspace condition variable.
@@ -267,6 +267,7 @@ pub const DIRCOOKIE_START: dircookie = dircookie(0);
 /// exclusively or merely provided for alignment with POSIX.
 #[repr(u16)]
 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
 pub enum errno {
   /// No error occurred. System call completed successfully.
   SUCCESS        =  0,
@@ -422,7 +423,6 @@ pub enum errno {
   XDEV           = 75,
   /// Extension: Capabilities insufficient.
   NOTCAPABLE     = 76,
-  #[doc(hidden)] _NonExhaustive = -1 as isize as u16,
 }
 
 bitflags! {
@@ -438,6 +438,7 @@ bitflags! {
 /// Type of a subscription to an event or its occurrence.
 #[repr(u8)]
 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
 pub enum eventtype {
   /// The time value of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id)
   /// has reached timestamp [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout).
@@ -463,7 +464,6 @@ pub enum eventtype {
   /// The process associated with process descriptor
   /// [`subscription.union.proc_terminate.fd`](struct.subscription_proc_terminate.html#structfield.fd) has terminated.
   PROC_TERMINATE = 7,
-  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
 }
 
 /// Exit code generated by a process when exiting.
@@ -530,6 +530,7 @@ pub type filesize = u64;
 /// The type of a file descriptor or file.
 #[repr(u8)]
 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
 pub enum filetype {
   /// The type of the file descriptor or file is unknown or
   /// is different from any of the other types specified.
@@ -558,7 +559,6 @@ pub enum filetype {
   SOCKET_STREAM    = 130,
   /// The file refers to a symbolic link inode.
   SYMBOLIC_LINK    = 144,
-  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
 }
 
 bitflags! {
@@ -847,12 +847,12 @@ bitflags! {
 /// memory.
 #[repr(u8)]
 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
 pub enum scope {
   /// The object is stored in private memory.
   PRIVATE = 4,
   /// The object is stored in shared memory.
   SHARED  = 8,
-  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
 }
 
 bitflags! {
@@ -878,6 +878,7 @@ bitflags! {
 /// Signal condition.
 #[repr(u8)]
 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
 pub enum signal {
   /// Process abort signal.
   ///
@@ -983,7 +984,6 @@ pub enum signal {
   ///
   /// Action: Terminates the process.
   XFSZ   = 26,
-  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
 }
 
 bitflags! {
@@ -1049,6 +1049,7 @@ pub type userdata = u64;
 /// should be set.
 #[repr(u8)]
 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
 pub enum whence {
   /// Seek relative to current position.
   CUR = 1,
@@ -1056,7 +1057,6 @@ pub enum whence {
   END = 2,
   /// Seek relative to start-of-file.
   SET = 3,
-  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
 }
 
 /// Auxiliary vector entry.
diff --git a/src/libstd/sys/cloudabi/backtrace.rs b/src/libstd/sys/cloudabi/backtrace.rs
index 33d93179237..2c43b5937ce 100644
--- a/src/libstd/sys/cloudabi/backtrace.rs
+++ b/src/libstd/sys/cloudabi/backtrace.rs
@@ -64,6 +64,10 @@ extern "C" fn trace_fn(
     arg: *mut libc::c_void,
 ) -> uw::_Unwind_Reason_Code {
     let cx = unsafe { &mut *(arg as *mut Context) };
+    if cx.idx >= cx.frames.len() {
+        return uw::_URC_NORMAL_STOP;
+    }
+
     let mut ip_before_insn = 0;
     let mut ip = unsafe { uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void };
     if !ip.is_null() && ip_before_insn == 0 {
@@ -73,13 +77,12 @@ extern "C" fn trace_fn(
     }
 
     let symaddr = unsafe { uw::_Unwind_FindEnclosingFunction(ip) };
-    if cx.idx < cx.frames.len() {
-        cx.frames[cx.idx] = Frame {
-            symbol_addr: symaddr as *mut u8,
-            exact_position: ip as *mut u8,
-        };
-        cx.idx += 1;
-    }
+    cx.frames[cx.idx] = Frame {
+        symbol_addr: symaddr as *mut u8,
+        exact_position: ip as *mut u8,
+        inline_context: 0,
+    };
+    cx.idx += 1;
 
     uw::_URC_NO_REASON
 }
diff --git a/src/libstd/sys/cloudabi/shims/process.rs b/src/libstd/sys/cloudabi/shims/process.rs
index 52e8c82e2b2..fcd40c15c17 100644
--- a/src/libstd/sys/cloudabi/shims/process.rs
+++ b/src/libstd/sys/cloudabi/shims/process.rs
@@ -126,6 +126,18 @@ impl fmt::Display for ExitStatus {
     }
 }
 
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct ExitCode(bool);
+
+impl ExitCode {
+    pub const SUCCESS: ExitCode = ExitCode(false);
+    pub const FAILURE: ExitCode = ExitCode(true);
+
+    pub fn as_i32(&self) -> i32 {
+        self.0 as i32
+    }
+}
+
 pub struct Process(Void);
 
 impl Process {
diff --git a/src/libstd/sys/cloudabi/stdio.rs b/src/libstd/sys/cloudabi/stdio.rs
index 9519a926471..1d7344f921c 100644
--- a/src/libstd/sys/cloudabi/stdio.rs
+++ b/src/libstd/sys/cloudabi/stdio.rs
@@ -77,3 +77,7 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 }
 
 pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
+
+pub fn stderr_prints_nothing() -> bool {
+    false
+}
diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs
index c980ae75261..8cca47efd22 100644
--- a/src/libstd/sys/cloudabi/thread.rs
+++ b/src/libstd/sys/cloudabi/thread.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use alloc::boxed::FnBox;
+use boxed::FnBox;
 use cmp;
 use ffi::CStr;
 use io;
@@ -32,7 +32,7 @@ unsafe impl Send for Thread {}
 unsafe impl Sync for Thread {}
 
 impl Thread {
-    pub unsafe fn new<'a>(stack: usize, p: Box<FnBox() + 'a>) -> io::Result<Thread> {
+    pub unsafe fn new<'a>(stack: usize, p: Box<dyn FnBox() + 'a>) -> io::Result<Thread> {
         let p = box p;
         let mut native: libc::pthread_t = mem::zeroed();
         let mut attr: libc::pthread_attr_t = mem::zeroed();
@@ -111,12 +111,14 @@ impl Drop for Thread {
 
 #[cfg_attr(test, allow(dead_code))]
 pub mod guard {
-    pub unsafe fn current() -> Option<usize> {
+    pub type Guard = !;
+    pub unsafe fn current() -> Option<Guard> {
         None
     }
-    pub unsafe fn init() -> Option<usize> {
+    pub unsafe fn init() -> Option<Guard> {
         None
     }
+    pub unsafe fn deinit() {}
 }
 
 fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs
index 1231898ed7e..c44db3b1072 100644
--- a/src/libstd/sys/mod.rs
+++ b/src/libstd/sys/mod.rs
@@ -67,6 +67,7 @@ cfg_if! {
         // (missing things in `libc` which is empty) so just omit everything
         // with an empty module
         #[unstable(issue = "0", feature = "std_internals")]
+        #[allow(missing_docs)]
         pub mod unix_ext {}
     } else {
         // On other platforms like Windows document the bare bones of unix
@@ -80,11 +81,13 @@ cfg_if! {
 cfg_if! {
     if #[cfg(windows)] {
         // On windows we'll just be documenting what's already available
+        #[allow(missing_docs)]
         pub use self::ext as windows_ext;
     } else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32"))] {
         // On CloudABI and wasm right now the shim below doesn't compile, so
         // just omit it
         #[unstable(issue = "0", feature = "std_internals")]
+        #[allow(missing_docs)]
         pub mod windows_ext {}
     } else {
         // On all other platforms (aka linux/osx/etc) then pull in a "minimal"
diff --git a/src/libstd/sys/redox/args.rs b/src/libstd/sys/redox/args.rs
index 59ae2a74a6d..556ed77372e 100644
--- a/src/libstd/sys/redox/args.rs
+++ b/src/libstd/sys/redox/args.rs
@@ -73,17 +73,15 @@ mod imp {
             CStr::from_ptr(*argv.offset(i) as *const libc::c_char).to_bytes().to_vec()
         }).collect();
 
-        LOCK.lock();
+        let _guard = LOCK.lock();
         let ptr = get_global_ptr();
         assert!((*ptr).is_none());
         (*ptr) = Some(box args);
-        LOCK.unlock();
     }
 
     pub unsafe fn cleanup() {
-        LOCK.lock();
+        let _guard = LOCK.lock();
         *get_global_ptr() = None;
-        LOCK.unlock();
     }
 
     pub fn args() -> Args {
@@ -96,16 +94,14 @@ mod imp {
 
     fn clone() -> Option<Vec<Vec<u8>>> {
         unsafe {
-            LOCK.lock();
+            let _guard = LOCK.lock();
             let ptr = get_global_ptr();
-            let ret = (*ptr).as_ref().map(|s| (**s).clone());
-            LOCK.unlock();
-            return ret
+            (*ptr).as_ref().map(|s| (**s).clone())
         }
     }
 
-    fn get_global_ptr() -> *mut Option<Box<Vec<Vec<u8>>>> {
-        unsafe { mem::transmute(&GLOBAL_ARGS_PTR) }
+    unsafe fn get_global_ptr() -> *mut Option<Box<Vec<Vec<u8>>>> {
+        mem::transmute(&GLOBAL_ARGS_PTR)
     }
 
 }
diff --git a/src/libstd/sys/redox/backtrace/tracing.rs b/src/libstd/sys/redox/backtrace/tracing.rs
index 0a174b3c3f5..c0414b78f8d 100644
--- a/src/libstd/sys/redox/backtrace/tracing.rs
+++ b/src/libstd/sys/redox/backtrace/tracing.rs
@@ -68,6 +68,10 @@ pub fn unwind_backtrace(frames: &mut [Frame])
 extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
                    arg: *mut libc::c_void) -> uw::_Unwind_Reason_Code {
     let cx = unsafe { &mut *(arg as *mut Context) };
+    if cx.idx >= cx.frames.len() {
+        return uw::_URC_NORMAL_STOP;
+    }
+
     let mut ip_before_insn = 0;
     let mut ip = unsafe {
         uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void
@@ -94,13 +98,12 @@ extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
         unsafe { uw::_Unwind_FindEnclosingFunction(ip) }
     };
 
-    if cx.idx < cx.frames.len() {
-        cx.frames[cx.idx] = Frame {
-            symbol_addr: symaddr as *mut u8,
-            exact_position: ip as *mut u8,
-        };
-        cx.idx += 1;
-    }
+    cx.frames[cx.idx] = Frame {
+        symbol_addr: symaddr as *mut u8,
+        exact_position: ip as *mut u8,
+        inline_context: 0,
+    };
+    cx.idx += 1;
 
     uw::_URC_NO_REASON
 }
diff --git a/src/libstd/sys/redox/ext/ffi.rs b/src/libstd/sys/redox/ext/ffi.rs
index d59b4fc0b70..cd88c8f46b3 100644
--- a/src/libstd/sys/redox/ext/ffi.rs
+++ b/src/libstd/sys/redox/ext/ffi.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Unix-specific extension to the primitives in the `std::ffi` module
+//! Redox-specific extension to the primitives in the `std::ffi` module.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -17,7 +17,9 @@ use mem;
 use sys::os_str::Buf;
 use sys_common::{FromInner, IntoInner, AsInner};
 
-/// Unix-specific extensions to `OsString`.
+/// Redox-specific extensions to [`OsString`].
+///
+/// [`OsString`]: ../../../../std/ffi/struct.OsString.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait OsStringExt {
     /// Creates an `OsString` from a byte vector.
@@ -39,7 +41,9 @@ impl OsStringExt for OsString {
     }
 }
 
-/// Unix-specific extensions to `OsStr`.
+/// Redox-specific extensions to [`OsStr`].
+///
+/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait OsStrExt {
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libstd/sys/redox/ext/fs.rs b/src/libstd/sys/redox/ext/fs.rs
index 5d4edc2cf92..c1dba6edda4 100644
--- a/src/libstd/sys/redox/ext/fs.rs
+++ b/src/libstd/sys/redox/ext/fs.rs
@@ -18,7 +18,9 @@ use path::Path;
 use sys;
 use sys_common::{FromInner, AsInner, AsInnerMut};
 
-/// Redox-specific extensions to `Permissions`
+/// Redox-specific extensions to [`fs::Permissions`].
+///
+/// [`fs::Permissions`]: ../../../../std/fs/struct.Permissions.html
 #[stable(feature = "fs_ext", since = "1.1.0")]
 pub trait PermissionsExt {
     /// Returns the underlying raw `mode_t` bits that are the standard Redox
@@ -30,13 +32,14 @@ pub trait PermissionsExt {
     /// use std::fs::File;
     /// use std::os::redox::fs::PermissionsExt;
     ///
-    /// # fn run() -> std::io::Result<()> {
-    /// let f = File::create("foo.txt")?;
-    /// let metadata = f.metadata()?;
-    /// let permissions = metadata.permissions();
+    /// fn main() -> std::io::Result<()> {
+    ///     let f = File::create("foo.txt")?;
+    ///     let metadata = f.metadata()?;
+    ///     let permissions = metadata.permissions();
     ///
-    /// println!("permissions: {}", permissions.mode());
-    /// # Ok(()) }
+    ///     println!("permissions: {}", permissions.mode());
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "fs_ext", since = "1.1.0")]
     fn mode(&self) -> u32;
@@ -49,14 +52,15 @@ pub trait PermissionsExt {
     /// use std::fs::File;
     /// use std::os::redox::fs::PermissionsExt;
     ///
-    /// # fn run() -> std::io::Result<()> {
-    /// let f = File::create("foo.txt")?;
-    /// let metadata = f.metadata()?;
-    /// let mut permissions = metadata.permissions();
+    /// fn main() -> std::io::Result<()> {
+    ///     let f = File::create("foo.txt")?;
+    ///     let metadata = f.metadata()?;
+    ///     let mut permissions = metadata.permissions();
     ///
-    /// permissions.set_mode(0o644); // Read/write for owner and read for others.
-    /// assert_eq!(permissions.mode(), 0o644);
-    /// # Ok(()) }
+    ///     permissions.set_mode(0o644); // Read/write for owner and read for others.
+    ///     assert_eq!(permissions.mode(), 0o644);
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "fs_ext", since = "1.1.0")]
     fn set_mode(&mut self, mode: u32);
@@ -93,7 +97,9 @@ impl PermissionsExt for Permissions {
     }
 }
 
-/// Redox-specific extensions to `OpenOptions`
+/// Redox-specific extensions to [`fs::OpenOptions`].
+///
+/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html
 #[stable(feature = "fs_ext", since = "1.1.0")]
 pub trait OpenOptionsExt {
     /// Sets the mode bits that a new file will be created with.
@@ -161,13 +167,9 @@ impl OpenOptionsExt for OpenOptions {
     }
 }
 
-// Hm, why are there casts here to the returned type, shouldn't the types always
-// be the same? Right you are! Turns out, however, on android at least the types
-// in the raw `stat` structure are not the same as the types being returned. Who
-// knew!
-//
-// As a result to make sure this compiles for all platforms we do the manual
-// casts and rely on manual lowering to `stat` if the raw type is desired.
+/// Redox-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     #[stable(feature = "metadata_ext", since = "1.1.0")]
@@ -202,6 +204,13 @@ pub trait MetadataExt {
     fn blocks(&self) -> u64;
 }
 
+// Hm, why are there casts here to the returned type, shouldn't the types always
+// be the same? Right you are! Turns out, however, on android at least the types
+// in the raw `stat` structure are not the same as the types being returned. Who
+// knew!
+//
+// As a result to make sure this compiles for all platforms we do the manual
+// casts and rely on manual lowering to `stat` if the raw type is desired.
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 impl MetadataExt for fs::Metadata {
     fn dev(&self) -> u64 {
@@ -251,7 +260,12 @@ impl MetadataExt for fs::Metadata {
     }
 }
 
-/// Add special Redox types (block/char device, fifo and socket)
+/// Redox-specific extensions for [`FileType`].
+///
+/// Adds support for special Unix file types such as block/character devices,
+/// pipes, and sockets.
+///
+/// [`FileType`]: ../../../../std/fs/struct.FileType.html
 #[stable(feature = "file_type_ext", since = "1.5.0")]
 pub trait FileTypeExt {
     /// Returns whether this file type is a block device.
@@ -291,13 +305,13 @@ impl FileTypeExt for fs::FileType {
 ///
 /// # Examples
 ///
-/// ```
+/// ```no_run
 /// use std::os::redox::fs;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::symlink("a.txt", "b.txt")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     fs::symlink("a.txt", "b.txt")?;
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "symlink", since = "1.1.0")]
 pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
@@ -305,8 +319,10 @@ pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
     sys::fs::symlink(src.as_ref(), dst.as_ref())
 }
 
+/// Redox-specific extensions to [`fs::DirBuilder`].
+///
+/// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html
 #[stable(feature = "dir_builder", since = "1.6.0")]
-/// An extension trait for `fs::DirBuilder` for Redox-specific options.
 pub trait DirBuilderExt {
     /// Sets the mode to create new directories with. This option defaults to
     /// 0o777.
diff --git a/src/libstd/sys/redox/ext/mod.rs b/src/libstd/sys/redox/ext/mod.rs
index 9fd8d6c9186..cb2c75ae0bf 100644
--- a/src/libstd/sys/redox/ext/mod.rs
+++ b/src/libstd/sys/redox/ext/mod.rs
@@ -33,6 +33,7 @@
 pub mod ffi;
 pub mod fs;
 pub mod io;
+pub mod net;
 pub mod process;
 pub mod thread;
 
diff --git a/src/libstd/sys/redox/ext/net.rs b/src/libstd/sys/redox/ext/net.rs
new file mode 100644
index 00000000000..2ab77703242
--- /dev/null
+++ b/src/libstd/sys/redox/ext/net.rs
@@ -0,0 +1,769 @@
+// 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 = "unix_socket_redox", since = "1.29")]
+
+//! Unix-specific networking functionality
+
+use fmt;
+use io::{self, Error, ErrorKind, Initializer};
+use net::Shutdown;
+use os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd};
+use path::Path;
+use time::Duration;
+use sys::{cvt, fd::FileDesc, syscall};
+
+/// An address associated with a Unix socket.
+///
+/// # Examples
+///
+/// ```
+/// use std::os::unix::net::UnixListener;
+///
+/// let socket = match UnixListener::bind("/tmp/sock") {
+///     Ok(sock) => sock,
+///     Err(e) => {
+///         println!("Couldn't bind: {:?}", e);
+///         return
+///     }
+/// };
+/// let addr = socket.local_addr().expect("Couldn't get local address");
+/// ```
+#[derive(Clone)]
+#[stable(feature = "unix_socket_redox", since = "1.29")]
+pub struct SocketAddr(());
+
+impl SocketAddr {
+    /// Returns the contents of this address if it is a `pathname` address.
+    ///
+    /// # Examples
+    ///
+    /// With a pathname:
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    /// use std::path::Path;
+    ///
+    /// let socket = UnixListener::bind("/tmp/sock").unwrap();
+    /// let addr = socket.local_addr().expect("Couldn't get local address");
+    /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock")));
+    /// ```
+    ///
+    /// Without a pathname:
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let socket = UnixDatagram::unbound().unwrap();
+    /// let addr = socket.local_addr().expect("Couldn't get local address");
+    /// assert_eq!(addr.as_pathname(), None);
+    /// ```
+    #[stable(feature = "unix_socket_redox", since = "1.29")]
+    pub fn as_pathname(&self) -> Option<&Path> {
+        None
+    }
+
+    /// Returns true if and only if the address is unnamed.
+    ///
+    /// # Examples
+    ///
+    /// A named address:
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let socket = UnixListener::bind("/tmp/sock").unwrap();
+    /// let addr = socket.local_addr().expect("Couldn't get local address");
+    /// assert_eq!(addr.is_unnamed(), false);
+    /// ```
+    ///
+    /// An unnamed address:
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let socket = UnixDatagram::unbound().unwrap();
+    /// let addr = socket.local_addr().expect("Couldn't get local address");
+    /// assert_eq!(addr.is_unnamed(), true);
+    /// ```
+    #[stable(feature = "unix_socket_redox", since = "1.29")]
+    pub fn is_unnamed(&self) -> bool {
+        false
+    }
+}
+#[stable(feature = "unix_socket_redox", since = "1.29")]
+impl fmt::Debug for SocketAddr {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        write!(fmt, "SocketAddr")
+    }
+}
+
+/// A Unix stream socket.
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::os::unix::net::UnixStream;
+/// use std::io::prelude::*;
+///
+/// let mut stream = UnixStream::connect("/path/to/my/socket").unwrap();
+/// stream.write_all(b"hello world").unwrap();
+/// let mut response = String::new();
+/// stream.read_to_string(&mut response).unwrap();
+/// println!("{}", response);
+/// ```
+#[stable(feature = "unix_socket_redox", since = "1.29")]
+pub struct UnixStream(FileDesc);
+
+#[stable(feature = "unix_socket_redox", since = "1.29")]
+impl fmt::Debug for UnixStream {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        let mut builder = fmt.debug_struct("UnixStream");
+        builder.field("fd", &self.0.raw());
+        if let Ok(addr) = self.local_addr() {
+            builder.field("local", &addr);
+        }
+        if let Ok(addr) = self.peer_addr() {
+            builder.field("peer", &addr);
+        }
+        builder.finish()
+    }
+}
+
+impl UnixStream {
+    /// Connects to the socket named by `path`.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let socket = match UnixStream::connect("/tmp/sock") {
+    ///     Ok(sock) => sock,
+    ///     Err(e) => {
+    ///         println!("Couldn't connect: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
+    #[stable(feature = "unix_socket_redox", since = "1.29")]
+    pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<UnixStream> {
+        if let Some(s) = path.as_ref().to_str() {
+            cvt(syscall::open(format!("chan:{}", s), syscall::O_CLOEXEC))
+                .map(FileDesc::new)
+                .map(UnixStream)
+        } else {
+            Err(Error::new(
+                ErrorKind::Other,
+                "UnixStream::connect: non-utf8 paths not supported on redox"
+            ))
+        }
+    }
+
+    /// Creates an unnamed pair of connected sockets.
+    ///
+    /// Returns two `UnixStream`s which are connected to each other.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let (sock1, sock2) = match UnixStream::pair() {
+    ///     Ok((sock1, sock2)) => (sock1, sock2),
+    ///     Err(e) => {
+    ///         println!("Couldn't create a pair of sockets: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
+    #[stable(feature = "unix_socket_redox", since = "1.29")]
+    pub fn pair() -> io::Result<(UnixStream, UnixStream)> {
+        let server = cvt(syscall::open("chan:", syscall::O_CREAT | syscall::O_CLOEXEC))
+            .map(FileDesc::new)?;
+        let client = server.duplicate_path(b"connect")?;
+        let stream = server.duplicate_path(b"listen")?;
+        Ok((UnixStream(client), UnixStream(stream)))
+    }
+
+    /// Creates a new independently owned handle to the underlying socket.
+    ///
+    /// The returned `UnixStream` is a reference to the same stream that this
+    /// object references. Both handles will read and write the same stream of
+    /// data, and options set on one stream will be propagated to the other
+    /// stream.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// let sock_copy = socket.try_clone().expect("Couldn't clone socket");
+    /// ```
+    #[stable(feature = "unix_socket_redox", since = "1.29")]
+    pub fn try_clone(&self) -> io::Result<UnixStream> {
+        self.0.duplicate().map(UnixStream)
+    }
+
+    /// Returns the socket address of the local half of this connection.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// let addr = socket.local_addr().expect("Couldn't get local address");
+    /// ```
+    #[stable(feature = "unix_socket_redox", since = "1.29")]
+    pub fn local_addr(&self) -> io::Result<SocketAddr> {
+        Err(Error::new(ErrorKind::Other, "UnixStream::local_addr unimplemented on redox"))
+    }
+
+    /// Returns the socket address of the remote half of this connection.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// let addr = socket.peer_addr().expect("Couldn't get peer address");
+    /// ```
+    #[stable(feature = "unix_socket_redox", since = "1.29")]
+    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+        Err(Error::new(ErrorKind::Other, "UnixStream::peer_addr unimplemented on redox"))
+    }
+
+    /// Sets the read timeout for the socket.
+    ///
+    /// If the provided value is [`None`], then [`read`] calls will block
+    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method.
+    ///
+    /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+    /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err
+    /// [`read`]: ../../../../std/io/trait.Read.html#tymethod.read
+    /// [`Duration`]: ../../../../std/time/struct.Duration.html
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
+    /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::os::unix::net::UnixStream;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
+    #[stable(feature = "unix_socket_redox", since = "1.29")]
+    pub fn set_read_timeout(&self, _timeout: Option<Duration>) -> io::Result<()> {
+        Err(Error::new(ErrorKind::Other, "UnixStream::set_read_timeout unimplemented on redox"))
+    }
+
+    /// Sets the write timeout for the socket.
+    ///
+    /// If the provided value is [`None`], then [`write`] calls will block
+    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
+    /// passed to this method.
+    ///
+    /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+    /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err
+    /// [`write`]: ../../../../std/io/trait.Write.html#tymethod.write
+    /// [`Duration`]: ../../../../std/time/struct.Duration.html
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout");
+    /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::net::UdpSocket;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap();
+    /// let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
+    #[stable(feature = "unix_socket_redox", since = "1.29")]
+    pub fn set_write_timeout(&self, _timeout: Option<Duration>) -> io::Result<()> {
+        Err(Error::new(ErrorKind::Other, "UnixStream::set_write_timeout unimplemented on redox"))
+    }
+
+    /// Returns the read timeout of this socket.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
+    /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0)));
+    /// ```
+    #[stable(feature = "unix_socket_redox", since = "1.29")]
+    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
+        Err(Error::new(ErrorKind::Other, "UnixStream::read_timeout unimplemented on redox"))
+    }
+
+    /// Returns the write timeout of this socket.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout");
+    /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0)));
+    /// ```
+    #[stable(feature = "unix_socket_redox", since = "1.29")]
+    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
+        Err(Error::new(ErrorKind::Other, "UnixStream::write_timeout unimplemented on redox"))
+    }
+
+    /// Moves the socket into or out of nonblocking mode.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// socket.set_nonblocking(true).expect("Couldn't set nonblocking");
+    /// ```
+    #[stable(feature = "unix_socket_redox", since = "1.29")]
+    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
+        self.0.set_nonblocking(nonblocking)
+    }
+
+    /// Returns the value of the `SO_ERROR` option.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// if let Ok(Some(err)) = socket.take_error() {
+    ///     println!("Got error: {:?}", err);
+    /// }
+    /// ```
+    ///
+    /// # Platform specific
+    /// On Redox this always returns None.
+    #[stable(feature = "unix_socket_redox", since = "1.29")]
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        Ok(None)
+    }
+
+    /// Shuts down the read, write, or both halves of this connection.
+    ///
+    /// This function will cause all pending and future I/O calls on the
+    /// specified portions to immediately return with an appropriate value
+    /// (see the documentation of [`Shutdown`]).
+    ///
+    /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    /// use std::net::Shutdown;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// socket.shutdown(Shutdown::Both).expect("shutdown function failed");
+    /// ```
+    #[stable(feature = "unix_socket_redox", since = "1.29")]
+    pub fn shutdown(&self, _how: Shutdown) -> io::Result<()> {
+        Err(Error::new(ErrorKind::Other, "UnixStream::shutdown unimplemented on redox"))
+    }
+}
+
+#[stable(feature = "unix_socket_redox", since = "1.29")]
+impl io::Read for UnixStream {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        io::Read::read(&mut &*self, buf)
+    }
+
+    #[inline]
+    unsafe fn initializer(&self) -> Initializer {
+        Initializer::nop()
+    }
+}
+
+#[stable(feature = "unix_socket_redox", since = "1.29")]
+impl<'a> io::Read for &'a UnixStream {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        self.0.read(buf)
+    }
+
+    #[inline]
+    unsafe fn initializer(&self) -> Initializer {
+        Initializer::nop()
+    }
+}
+
+#[stable(feature = "unix_socket_redox", since = "1.29")]
+impl io::Write for UnixStream {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        io::Write::write(&mut &*self, buf)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        io::Write::flush(&mut &*self)
+    }
+}
+
+#[stable(feature = "unix_socket_redox", since = "1.29")]
+impl<'a> io::Write for &'a UnixStream {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        self.0.write(buf)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+#[stable(feature = "unix_socket_redox", since = "1.29")]
+impl AsRawFd for UnixStream {
+    fn as_raw_fd(&self) -> RawFd {
+        self.0.raw()
+    }
+}
+
+#[stable(feature = "unix_socket_redox", since = "1.29")]
+impl FromRawFd for UnixStream {
+    unsafe fn from_raw_fd(fd: RawFd) -> UnixStream {
+        UnixStream(FileDesc::new(fd))
+    }
+}
+
+#[stable(feature = "unix_socket_redox", since = "1.29")]
+impl IntoRawFd for UnixStream {
+    fn into_raw_fd(self) -> RawFd {
+        self.0.into_raw()
+    }
+}
+
+/// A structure representing a Unix domain socket server.
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::thread;
+/// use std::os::unix::net::{UnixStream, UnixListener};
+///
+/// fn handle_client(stream: UnixStream) {
+///     // ...
+/// }
+///
+/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+///
+/// // accept connections and process them, spawning a new thread for each one
+/// for stream in listener.incoming() {
+///     match stream {
+///         Ok(stream) => {
+///             /* connection succeeded */
+///             thread::spawn(|| handle_client(stream));
+///         }
+///         Err(err) => {
+///             /* connection failed */
+///             break;
+///         }
+///     }
+/// }
+/// ```
+#[stable(feature = "unix_socket_redox", since = "1.29")]
+pub struct UnixListener(FileDesc);
+
+#[stable(feature = "unix_socket_redox", since = "1.29")]
+impl fmt::Debug for UnixListener {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        let mut builder = fmt.debug_struct("UnixListener");
+        builder.field("fd", &self.0.raw());
+        if let Ok(addr) = self.local_addr() {
+            builder.field("local", &addr);
+        }
+        builder.finish()
+    }
+}
+
+impl UnixListener {
+    /// Creates a new `UnixListener` bound to the specified socket.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let listener = match UnixListener::bind("/path/to/the/socket") {
+    ///     Ok(sock) => sock,
+    ///     Err(e) => {
+    ///         println!("Couldn't connect: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
+    #[stable(feature = "unix_socket_redox", since = "1.29")]
+    pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixListener> {
+        if let Some(s) = path.as_ref().to_str() {
+            cvt(syscall::open(format!("chan:{}", s), syscall::O_CREAT | syscall::O_CLOEXEC))
+                .map(FileDesc::new)
+                .map(UnixListener)
+        } else {
+            Err(Error::new(
+                ErrorKind::Other,
+                "UnixListener::bind: non-utf8 paths not supported on redox"
+            ))
+        }
+    }
+
+    /// Accepts a new incoming connection to this listener.
+    ///
+    /// This function will block the calling thread until a new Unix connection
+    /// is established. When established, the corresponding [`UnixStream`] and
+    /// the remote peer's address will be returned.
+    ///
+    /// [`UnixStream`]: ../../../../std/os/unix/net/struct.UnixStream.html
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+    ///
+    /// match listener.accept() {
+    ///     Ok((socket, addr)) => println!("Got a client: {:?}", addr),
+    ///     Err(e) => println!("accept function failed: {:?}", e),
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket_redox", since = "1.29")]
+    pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> {
+        self.0.duplicate_path(b"listen").map(|fd| (UnixStream(fd), SocketAddr(())))
+    }
+
+    /// Creates a new independently owned handle to the underlying socket.
+    ///
+    /// The returned `UnixListener` is a reference to the same socket that this
+    /// object references. Both handles can be used to accept incoming
+    /// connections and options set on one listener will affect the other.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+    ///
+    /// let listener_copy = listener.try_clone().expect("try_clone failed");
+    /// ```
+    #[stable(feature = "unix_socket_redox", since = "1.29")]
+    pub fn try_clone(&self) -> io::Result<UnixListener> {
+        self.0.duplicate().map(UnixListener)
+    }
+
+    /// Returns the local socket address of this listener.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+    ///
+    /// let addr = listener.local_addr().expect("Couldn't get local address");
+    /// ```
+    #[stable(feature = "unix_socket_redox", since = "1.29")]
+    pub fn local_addr(&self) -> io::Result<SocketAddr> {
+        Err(Error::new(ErrorKind::Other, "UnixListener::local_addr unimplemented on redox"))
+    }
+
+    /// Moves the socket into or out of nonblocking mode.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+    ///
+    /// listener.set_nonblocking(true).expect("Couldn't set non blocking");
+    /// ```
+    #[stable(feature = "unix_socket_redox", since = "1.29")]
+    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
+        self.0.set_nonblocking(nonblocking)
+    }
+
+    /// Returns the value of the `SO_ERROR` option.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let listener = UnixListener::bind("/tmp/sock").unwrap();
+    ///
+    /// if let Ok(Some(err)) = listener.take_error() {
+    ///     println!("Got error: {:?}", err);
+    /// }
+    /// ```
+    ///
+    /// # Platform specific
+    /// On Redox this always returns None.
+    #[stable(feature = "unix_socket_redox", since = "1.29")]
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        Ok(None)
+    }
+
+    /// Returns an iterator over incoming connections.
+    ///
+    /// The iterator will never return [`None`] and will also not yield the
+    /// peer's [`SocketAddr`] structure.
+    ///
+    /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+    /// [`SocketAddr`]: struct.SocketAddr.html
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::thread;
+    /// use std::os::unix::net::{UnixStream, UnixListener};
+    ///
+    /// fn handle_client(stream: UnixStream) {
+    ///     // ...
+    /// }
+    ///
+    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+    ///
+    /// for stream in listener.incoming() {
+    ///     match stream {
+    ///         Ok(stream) => {
+    ///             thread::spawn(|| handle_client(stream));
+    ///         }
+    ///         Err(err) => {
+    ///             break;
+    ///         }
+    ///     }
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket_redox", since = "1.29")]
+    pub fn incoming<'a>(&'a self) -> Incoming<'a> {
+        Incoming { listener: self }
+    }
+}
+
+#[stable(feature = "unix_socket_redox", since = "1.29")]
+impl AsRawFd for UnixListener {
+    fn as_raw_fd(&self) -> RawFd {
+        self.0.raw()
+    }
+}
+
+#[stable(feature = "unix_socket_redox", since = "1.29")]
+impl FromRawFd for UnixListener {
+    unsafe fn from_raw_fd(fd: RawFd) -> UnixListener {
+        UnixListener(FileDesc::new(fd))
+    }
+}
+
+#[stable(feature = "unix_socket_redox", since = "1.29")]
+impl IntoRawFd for UnixListener {
+    fn into_raw_fd(self) -> RawFd {
+        self.0.into_raw()
+    }
+}
+
+#[stable(feature = "unix_socket_redox", since = "1.29")]
+impl<'a> IntoIterator for &'a UnixListener {
+    type Item = io::Result<UnixStream>;
+    type IntoIter = Incoming<'a>;
+
+    fn into_iter(self) -> Incoming<'a> {
+        self.incoming()
+    }
+}
+
+/// An iterator over incoming connections to a [`UnixListener`].
+///
+/// It will never return [`None`].
+///
+/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+/// [`UnixListener`]: struct.UnixListener.html
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::thread;
+/// use std::os::unix::net::{UnixStream, UnixListener};
+///
+/// fn handle_client(stream: UnixStream) {
+///     // ...
+/// }
+///
+/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+///
+/// for stream in listener.incoming() {
+///     match stream {
+///         Ok(stream) => {
+///             thread::spawn(|| handle_client(stream));
+///         }
+///         Err(err) => {
+///             break;
+///         }
+///     }
+/// }
+/// ```
+#[derive(Debug)]
+#[stable(feature = "unix_socket_redox", since = "1.29")]
+pub struct Incoming<'a> {
+    listener: &'a UnixListener,
+}
+
+#[stable(feature = "unix_socket_redox", since = "1.29")]
+impl<'a> Iterator for Incoming<'a> {
+    type Item = io::Result<UnixStream>;
+
+    fn next(&mut self) -> Option<io::Result<UnixStream>> {
+        Some(self.listener.accept().map(|s| s.0))
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (usize::max_value(), None)
+    }
+}
diff --git a/src/libstd/sys/redox/ext/process.rs b/src/libstd/sys/redox/ext/process.rs
index e68e180acf1..cfb6d5fc703 100644
--- a/src/libstd/sys/redox/ext/process.rs
+++ b/src/libstd/sys/redox/ext/process.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Unix-specific extensions to primitives in the `std::process` module.
+//! Redox-specific extensions to primitives in the `std::process` module.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -18,7 +18,9 @@ use process;
 use sys;
 use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner};
 
-/// Unix-specific extensions to the `std::process::Command` builder
+/// Redox-specific extensions to the [`process::Command`] builder,
+///
+/// [`process::Command`]: ../../../../std/process/struct.Command.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait CommandExt {
     /// Sets the child process's user id. This translates to a
@@ -107,7 +109,9 @@ impl CommandExt for process::Command {
     }
 }
 
-/// Unix-specific extensions to `std::process::ExitStatus`
+/// Redox-specific extensions to [`process::ExitStatus`].
+///
+/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait ExitStatusExt {
     /// Creates a new `ExitStatus` from the raw underlying `i32` return value of
diff --git a/src/libstd/sys/redox/ext/thread.rs b/src/libstd/sys/redox/ext/thread.rs
index 52be2ccd9f9..71ff0d46b91 100644
--- a/src/libstd/sys/redox/ext/thread.rs
+++ b/src/libstd/sys/redox/ext/thread.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Unix-specific extensions to primitives in the `std::thread` module.
+//! Redox-specific extensions to primitives in the `std::thread` module.
 
 #![stable(feature = "thread_extensions", since = "1.9.0")]
 
@@ -19,7 +19,9 @@ use thread::JoinHandle;
 #[allow(deprecated)]
 pub type RawPthread = usize;
 
-/// Unix-specific extensions to `std::thread::JoinHandle`
+/// Redox-specific extensions to [`thread::JoinHandle`].
+///
+/// [`thread::JoinHandle`]: ../../../../std/thread/struct.JoinHandle.html
 #[stable(feature = "thread_extensions", since = "1.9.0")]
 pub trait JoinHandleExt {
     /// Extracts the raw pthread_t without taking ownership
diff --git a/src/libstd/sys/redox/fd.rs b/src/libstd/sys/redox/fd.rs
index ba7bbdc657f..e04e2791b23 100644
--- a/src/libstd/sys/redox/fd.rs
+++ b/src/libstd/sys/redox/fd.rs
@@ -47,7 +47,10 @@ impl FileDesc {
     }
 
     pub fn duplicate(&self) -> io::Result<FileDesc> {
-        let new_fd = cvt(syscall::dup(self.fd, &[]))?;
+        self.duplicate_path(&[])
+    }
+    pub fn duplicate_path(&self, path: &[u8]) -> io::Result<FileDesc> {
+        let new_fd = cvt(syscall::dup(self.fd, path))?;
         Ok(FileDesc::new(new_fd))
     }
 
diff --git a/src/libstd/sys/redox/net/mod.rs b/src/libstd/sys/redox/net/mod.rs
index 0291d7f0e92..67f22231d5f 100644
--- a/src/libstd/sys/redox/net/mod.rs
+++ b/src/libstd/sys/redox/net/mod.rs
@@ -41,12 +41,12 @@ impl Iterator for LookupHost {
 pub fn lookup_host(host: &str) -> Result<LookupHost> {
     let mut ip_string = String::new();
     File::open("/etc/net/ip")?.read_to_string(&mut ip_string)?;
-    let ip: Vec<u8> = ip_string.trim().split(".").map(|part| part.parse::<u8>()
+    let ip: Vec<u8> = ip_string.trim().split('.').map(|part| part.parse::<u8>()
                                .unwrap_or(0)).collect();
 
     let mut dns_string = String::new();
     File::open("/etc/net/dns")?.read_to_string(&mut dns_string)?;
-    let dns: Vec<u8> = dns_string.trim().split(".").map(|part| part.parse::<u8>()
+    let dns: Vec<u8> = dns_string.trim().split('.').map(|part| part.parse::<u8>()
                                  .unwrap_or(0)).collect();
 
     if ip.len() == 4 && dns.len() == 4 {
diff --git a/src/libstd/sys/redox/net/netc.rs b/src/libstd/sys/redox/net/netc.rs
index d443a4d68a1..b6d9f456295 100644
--- a/src/libstd/sys/redox/net/netc.rs
+++ b/src/libstd/sys/redox/net/netc.rs
@@ -24,10 +24,10 @@ pub struct in_addr {
 }
 
 #[derive(Copy, Clone)]
+#[repr(align(4))]
 #[repr(C)]
 pub struct in6_addr {
     pub s6_addr: [u8; 16],
-    __align: [u32; 0],
 }
 
 #[derive(Copy, Clone)]
diff --git a/src/libstd/sys/redox/net/tcp.rs b/src/libstd/sys/redox/net/tcp.rs
index 319965ab396..b5664908479 100644
--- a/src/libstd/sys/redox/net/tcp.rs
+++ b/src/libstd/sys/redox/net/tcp.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use cmp;
-use io::{Error, ErrorKind, Result};
+use io::{self, Error, ErrorKind, Result};
 use mem;
 use net::{SocketAddr, Shutdown};
 use path::Path;
@@ -130,6 +130,10 @@ impl TcpStream {
     pub fn set_read_timeout(&self, duration_option: Option<Duration>) -> Result<()> {
         let file = self.0.dup(b"read_timeout")?;
         if let Some(duration) = duration_option {
+            if duration.as_secs() == 0 && duration.subsec_nanos() == 0 {
+                return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                          "cannot set a 0 duration timeout"));
+            }
             file.write(&TimeSpec {
                 tv_sec: duration.as_secs() as i64,
                 tv_nsec: duration.subsec_nanos() as i32
@@ -143,6 +147,10 @@ impl TcpStream {
     pub fn set_write_timeout(&self, duration_option: Option<Duration>) -> Result<()> {
         let file = self.0.dup(b"write_timeout")?;
         if let Some(duration) = duration_option {
+            if duration.as_secs() == 0 && duration.subsec_nanos() == 0 {
+                return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                          "cannot set a 0 duration timeout"));
+            }
             file.write(&TimeSpec {
                 tv_sec: duration.as_secs() as i64,
                 tv_nsec: duration.subsec_nanos() as i32
diff --git a/src/libstd/sys/redox/net/udp.rs b/src/libstd/sys/redox/net/udp.rs
index 7e7666e7ef3..22af02079e7 100644
--- a/src/libstd/sys/redox/net/udp.rs
+++ b/src/libstd/sys/redox/net/udp.rs
@@ -10,7 +10,7 @@
 
 use cell::UnsafeCell;
 use cmp;
-use io::{Error, ErrorKind, Result};
+use io::{self, Error, ErrorKind, Result};
 use mem;
 use net::{SocketAddr, Ipv4Addr, Ipv6Addr};
 use path::Path;
@@ -58,7 +58,7 @@ impl UdpSocket {
 
     pub fn recv(&self, buf: &mut [u8]) -> Result<usize> {
         if let Some(addr) = *self.get_conn() {
-            let from = self.0.dup(format!("{}", addr).as_bytes())?;
+            let from = self.0.dup(addr.to_string().as_bytes())?;
             from.read(buf)
         } else {
             Err(Error::new(ErrorKind::Other, "UdpSocket::recv not connected"))
@@ -179,6 +179,10 @@ impl UdpSocket {
     pub fn set_read_timeout(&self, duration_option: Option<Duration>) -> Result<()> {
         let file = self.0.dup(b"read_timeout")?;
         if let Some(duration) = duration_option {
+            if duration.as_secs() == 0 && duration.subsec_nanos() == 0 {
+                return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                          "cannot set a 0 duration timeout"));
+            }
             file.write(&TimeSpec {
                 tv_sec: duration.as_secs() as i64,
                 tv_nsec: duration.subsec_nanos() as i32
@@ -192,6 +196,10 @@ impl UdpSocket {
     pub fn set_write_timeout(&self, duration_option: Option<Duration>) -> Result<()> {
         let file = self.0.dup(b"write_timeout")?;
         if let Some(duration) = duration_option {
+            if duration.as_secs() == 0 && duration.subsec_nanos() == 0 {
+                return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                          "cannot set a 0 duration timeout"));
+            }
             file.write(&TimeSpec {
                 tv_sec: duration.as_secs() as i64,
                 tv_nsec: duration.subsec_nanos() as i32
diff --git a/src/libstd/sys/redox/os.rs b/src/libstd/sys/redox/os.rs
index 480765b77a0..5822216779b 100644
--- a/src/libstd/sys/redox/os.rs
+++ b/src/libstd/sys/redox/os.rs
@@ -30,9 +30,6 @@ use sys_common::mutex::Mutex;
 use sys::{cvt, fd, syscall};
 use vec;
 
-const TMPBUF_SZ: usize = 128;
-static ENV_LOCK: Mutex = Mutex::new();
-
 extern {
     #[link_name = "__errno_location"]
     fn errno_location() -> *mut i32;
diff --git a/src/libstd/sys/redox/os_str.rs b/src/libstd/sys/redox/os_str.rs
index 655bfdb9167..eb3a1ead58c 100644
--- a/src/libstd/sys/redox/os_str.rs
+++ b/src/libstd/sys/redox/os_str.rs
@@ -19,7 +19,7 @@ use rc::Rc;
 use sync::Arc;
 use sys_common::{AsInner, IntoInner};
 use sys_common::bytestring::debug_fmt_bytestring;
-use std_unicode::lossy::Utf8Lossy;
+use core::str::lossy::Utf8Lossy;
 
 #[derive(Clone, Hash)]
 pub struct Buf {
@@ -104,6 +104,11 @@ impl Buf {
         self.inner.shrink_to_fit()
     }
 
+    #[inline]
+    pub fn shrink_to(&mut self, min_capacity: usize) {
+        self.inner.shrink_to(min_capacity)
+    }
+
     pub fn as_slice(&self) -> &Slice {
         unsafe { mem::transmute(&*self.inner) }
     }
diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs
index 3fd54973896..2037616e6ac 100644
--- a/src/libstd/sys/redox/process.rs
+++ b/src/libstd/sys/redox/process.rs
@@ -13,6 +13,8 @@ use ffi::OsStr;
 use os::unix::ffi::OsStrExt;
 use fmt;
 use io::{self, Error, ErrorKind};
+use iter;
+use libc::{EXIT_SUCCESS, EXIT_FAILURE};
 use path::{Path, PathBuf};
 use sys::fd::FileDesc;
 use sys::fs::{File, OpenOptions};
@@ -50,7 +52,7 @@ pub struct Command {
     uid: Option<u32>,
     gid: Option<u32>,
     saw_nul: bool,
-    closures: Vec<Box<FnMut() -> io::Result<()> + Send + Sync>>,
+    closures: Vec<Box<dyn FnMut() -> io::Result<()> + Send + Sync>>,
     stdin: Option<Stdio>,
     stdout: Option<Stdio>,
     stderr: Option<Stdio>,
@@ -121,7 +123,7 @@ impl Command {
     }
 
     pub fn before_exec(&mut self,
-                       f: Box<FnMut() -> io::Result<()> + Send + Sync>) {
+                       f: Box<dyn FnMut() -> io::Result<()> + Send + Sync>) {
         self.closures.push(f);
     }
 
@@ -295,11 +297,11 @@ impl Command {
             t!(callback());
         }
 
-        let mut args: Vec<[usize; 2]> = Vec::new();
-        args.push([self.program.as_ptr() as usize, self.program.len()]);
-        for arg in self.args.iter() {
-            args.push([arg.as_ptr() as usize, arg.len()]);
-        }
+        let args: Vec<[usize; 2]> = iter::once(
+            [self.program.as_ptr() as usize, self.program.len()]
+        ).chain(
+            self.args.iter().map(|arg| [arg.as_ptr() as usize, arg.len()])
+        ).collect();
 
         self.env.apply();
 
@@ -480,6 +482,18 @@ impl fmt::Display for ExitStatus {
     }
 }
 
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct ExitCode(u8);
+
+impl ExitCode {
+    pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _);
+    pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _);
+
+    pub fn as_i32(&self) -> i32 {
+        self.0 as i32
+    }
+}
+
 /// The unique id of the process (this should never be negative).
 pub struct Process {
     pid: usize,
diff --git a/src/libstd/sys/redox/stdio.rs b/src/libstd/sys/redox/stdio.rs
index 3abb094ac34..7a4d11b0ecb 100644
--- a/src/libstd/sys/redox/stdio.rs
+++ b/src/libstd/sys/redox/stdio.rs
@@ -75,3 +75,7 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 }
 
 pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
+
+pub fn stderr_prints_nothing() -> bool {
+    false
+}
diff --git a/src/libstd/sys/redox/syscall/error.rs b/src/libstd/sys/redox/syscall/error.rs
index d8d78d55016..1ef79547431 100644
--- a/src/libstd/sys/redox/syscall/error.rs
+++ b/src/libstd/sys/redox/syscall/error.rs
@@ -48,13 +48,13 @@ impl Error {
 }
 
 impl fmt::Debug for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str(self.text())
     }
 }
 
 impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str(self.text())
     }
 }
diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs
index c4aad8d86f8..f4177087d77 100644
--- a/src/libstd/sys/redox/thread.rs
+++ b/src/libstd/sys/redox/thread.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use alloc::boxed::FnBox;
+use boxed::FnBox;
 use ffi::CStr;
 use io;
 use mem;
@@ -28,7 +28,7 @@ unsafe impl Send for Thread {}
 unsafe impl Sync for Thread {}
 
 impl Thread {
-    pub unsafe fn new<'a>(_stack: usize, p: Box<FnBox() + 'a>) -> io::Result<Thread> {
+    pub unsafe fn new<'a>(_stack: usize, p: Box<dyn FnBox() + 'a>) -> io::Result<Thread> {
         let p = box p;
 
         let id = cvt(syscall::clone(syscall::CLONE_VM | syscall::CLONE_FS | syscall::CLONE_FILES))?;
@@ -88,6 +88,8 @@ impl Thread {
 }
 
 pub mod guard {
-    pub unsafe fn current() -> Option<usize> { None }
-    pub unsafe fn init() -> Option<usize> { None }
+    pub type Guard = !;
+    pub unsafe fn current() -> Option<Guard> { None }
+    pub unsafe fn init() -> Option<Guard> { None }
+    pub unsafe fn deinit() {}
 }
diff --git a/src/libstd/sys/redox/time.rs b/src/libstd/sys/redox/time.rs
index cf798500b7f..5c491115c55 100644
--- a/src/libstd/sys/redox/time.rs
+++ b/src/libstd/sys/redox/time.rs
@@ -144,7 +144,7 @@ impl Instant {
 
     pub fn sub_instant(&self, other: &Instant) -> Duration {
         self.t.sub_timespec(&other.t).unwrap_or_else(|_| {
-            panic!("other was less than the current instant")
+            panic!("specified instant was later than self")
         })
     }
 
diff --git a/src/libstd/sys/unix/args.rs b/src/libstd/sys/unix/args.rs
index e1c7ffc19e5..c3c033dfbc7 100644
--- a/src/libstd/sys/unix/args.rs
+++ b/src/libstd/sys/unix/args.rs
@@ -66,7 +66,8 @@ impl DoubleEndedIterator for Args {
           target_os = "emscripten",
           target_os = "haiku",
           target_os = "l4re",
-          target_os = "fuchsia"))]
+          target_os = "fuchsia",
+          target_os = "hermit"))]
 mod imp {
     use os::unix::prelude::*;
     use ptr;
@@ -79,20 +80,20 @@ mod imp {
 
     static mut ARGC: isize = 0;
     static mut ARGV: *const *const u8 = ptr::null();
+    // We never call `ENV_LOCK.init()`, so it is UB to attempt to
+    // acquire this mutex reentrantly!
     static LOCK: Mutex = Mutex::new();
 
     pub unsafe fn init(argc: isize, argv: *const *const u8) {
-        LOCK.lock();
+        let _guard = LOCK.lock();
         ARGC = argc;
         ARGV = argv;
-        LOCK.unlock();
     }
 
     pub unsafe fn cleanup() {
-        LOCK.lock();
+        let _guard = LOCK.lock();
         ARGC = 0;
         ARGV = ptr::null();
-        LOCK.unlock();
     }
 
     pub fn args() -> Args {
@@ -104,13 +105,11 @@ mod imp {
 
     fn clone() -> Vec<OsString> {
         unsafe {
-            LOCK.lock();
-            let ret = (0..ARGC).map(|i| {
+            let _guard = LOCK.lock();
+            (0..ARGC).map(|i| {
                 let cstr = CStr::from_ptr(*ARGV.offset(i) as *const libc::c_char);
                 OsStringExt::from_vec(cstr.to_bytes().to_vec())
-            }).collect();
-            LOCK.unlock();
-            return ret
+            }).collect()
         }
     }
 }
diff --git a/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs b/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs
index 400d39cd4bd..6293eeb4ed6 100644
--- a/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs
+++ b/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs
@@ -38,6 +38,7 @@ pub fn unwind_backtrace(frames: &mut [Frame])
         *to = Frame {
             exact_position: *from as *mut u8,
             symbol_addr: *from as *mut u8,
+            inline_context: 0,
         };
     }
     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 000c08d2e0d..6e841568679 100644
--- a/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs
+++ b/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs
@@ -68,6 +68,10 @@ pub fn unwind_backtrace(frames: &mut [Frame])
 extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
                    arg: *mut libc::c_void) -> uw::_Unwind_Reason_Code {
     let cx = unsafe { &mut *(arg as *mut Context) };
+    if cx.idx >= cx.frames.len() {
+        return uw::_URC_NORMAL_STOP;
+    }
+
     let mut ip_before_insn = 0;
     let mut ip = unsafe {
         uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void
@@ -94,13 +98,12 @@ extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
         unsafe { uw::_Unwind_FindEnclosingFunction(ip) }
     };
 
-    if cx.idx < cx.frames.len() {
-        cx.frames[cx.idx] = Frame {
-            symbol_addr: symaddr as *mut u8,
-            exact_position: ip as *mut u8,
-        };
-        cx.idx += 1;
-    }
+    cx.frames[cx.idx] = Frame {
+        symbol_addr: symaddr as *mut u8,
+        exact_position: ip as *mut u8,
+        inline_context: 0,
+    };
+    cx.idx += 1;
 
     uw::_URC_NO_REASON
 }
diff --git a/src/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs
index 4f878d8ad1f..2007da7b1f6 100644
--- a/src/libstd/sys/unix/condvar.rs
+++ b/src/libstd/sys/unix/condvar.rs
@@ -41,13 +41,15 @@ impl Condvar {
     #[cfg(any(target_os = "macos",
               target_os = "ios",
               target_os = "l4re",
-              target_os = "android"))]
+              target_os = "android",
+              target_os = "hermit"))]
     pub unsafe fn init(&mut self) {}
 
     #[cfg(not(any(target_os = "macos",
                   target_os = "ios",
                   target_os = "l4re",
-                  target_os = "android")))]
+                  target_os = "android",
+                  target_os = "hermit")))]
     pub unsafe fn init(&mut self) {
         use mem;
         let mut attr: libc::pthread_condattr_t = mem::uninitialized();
@@ -83,7 +85,10 @@ impl Condvar {
     // where we configure condition variable to use monotonic clock (instead of
     // default system clock). This approach avoids all problems that result
     // from changes made to the system time.
-    #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "android")))]
+    #[cfg(not(any(target_os = "macos",
+                  target_os = "ios",
+                  target_os = "android",
+                  target_os = "hermit")))]
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
         use mem;
 
@@ -113,7 +118,7 @@ impl Condvar {
     // This implementation is modeled after libcxx's condition_variable
     // https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46
     // https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367
-    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android"))]
+    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android", target_os = "hermit"))]
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool {
         use ptr;
         use time::Instant;
diff --git a/src/libstd/sys/unix/env.rs b/src/libstd/sys/unix/env.rs
index 00cf7eca75d..ad116c57f55 100644
--- a/src/libstd/sys/unix/env.rs
+++ b/src/libstd/sys/unix/env.rs
@@ -172,3 +172,14 @@ pub mod os {
     pub const EXE_SUFFIX: &'static str = "";
     pub const EXE_EXTENSION: &'static str = "";
 }
+
+#[cfg(target_os = "hermit")]
+pub mod os {
+    pub const FAMILY: &'static str = "unix";
+    pub const OS: &'static str = "hermit";
+    pub const DLL_PREFIX: &'static str = "lib";
+    pub const DLL_SUFFIX: &'static str = ".so";
+    pub const DLL_EXTENSION: &'static str = "so";
+    pub const EXE_SUFFIX: &'static str = "";
+    pub const EXE_EXTENSION: &'static str = "";
+}
diff --git a/src/libstd/sys/unix/ext/ffi.rs b/src/libstd/sys/unix/ext/ffi.rs
index fb9984ccbdd..8347145db5a 100644
--- a/src/libstd/sys/unix/ext/ffi.rs
+++ b/src/libstd/sys/unix/ext/ffi.rs
@@ -17,7 +17,9 @@ use mem;
 use sys::os_str::Buf;
 use sys_common::{FromInner, IntoInner, AsInner};
 
-/// Unix-specific extensions to `OsString`.
+/// Unix-specific extensions to [`OsString`].
+///
+/// [`OsString`]: ../../../../std/ffi/struct.OsString.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait OsStringExt {
     /// Creates an [`OsString`] from a byte vector.
@@ -66,7 +68,9 @@ impl OsStringExt for OsString {
     }
 }
 
-/// Unix-specific extensions to `OsStr`.
+/// Unix-specific extensions to [`OsStr`].
+///
+/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait OsStrExt {
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs
index 2e17fd58e0a..507e9d88171 100644
--- a/src/libstd/sys/unix/ext/fs.rs
+++ b/src/libstd/sys/unix/ext/fs.rs
@@ -41,24 +41,96 @@ pub trait FileExt {
     ///
     /// # Examples
     ///
-    /// ```
-    /// use std::os::unix::prelude::FileExt;
+    /// ```no_run
+    /// use std::io;
     /// use std::fs::File;
+    /// use std::os::unix::prelude::FileExt;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let mut buf = [0u8; 8];
-    /// let file = File::open("foo.txt")?;
+    /// fn main() -> 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(())
-    /// # }
+    ///     // 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>;
 
+    /// Reads the exact number of byte required to fill `buf` from the given offset.
+    ///
+    /// The offset is relative to the start of the file and thus independent
+    /// from the current cursor.
+    ///
+    /// The current file cursor is not affected by this function.
+    ///
+    /// Similar to [`Read::read_exact`] but uses [`read_at`] instead of `read`.
+    ///
+    /// [`Read::read_exact`]: ../../../../std/io/trait.Read.html#method.read_exact
+    /// [`read_at`]: #tymethod.read_at
+    ///
+    /// # Errors
+    ///
+    /// If this function encounters an error of the kind
+    /// [`ErrorKind::Interrupted`] then the error is ignored and the operation
+    /// will continue.
+    ///
+    /// If this function encounters an "end of file" before completely filling
+    /// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`].
+    /// The contents of `buf` are unspecified in this case.
+    ///
+    /// If any other read error is encountered then this function immediately
+    /// returns. The contents of `buf` are unspecified in this case.
+    ///
+    /// If this function returns an error, it is unspecified how many bytes it
+    /// has read, but it will never read more than would be necessary to
+    /// completely fill the buffer.
+    ///
+    /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
+    /// [`ErrorKind::UnexpectedEof`]: ../../../../std/io/enum.ErrorKind.html#variant.UnexpectedEof
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(rw_exact_all_at)]
+    /// use std::io;
+    /// use std::fs::File;
+    /// use std::os::unix::prelude::FileExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let mut buf = [0u8; 8];
+    ///     let file = File::open("foo.txt")?;
+    ///
+    ///     // We now read exactly 8 bytes from the offset 10.
+    ///     file.read_exact_at(&mut buf, 10)?;
+    ///     println!("read {} bytes: {:?}", buf.len(), buf);
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "rw_exact_all_at", issue = "51984")]
+    fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
+        while !buf.is_empty() {
+            match self.read_at(buf, offset) {
+                Ok(0) => break,
+                Ok(n) => {
+                    let tmp = buf;
+                    buf = &mut tmp[n..];
+                    offset += n as u64;
+                }
+                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
+                Err(e) => return Err(e),
+            }
+        }
+        if !buf.is_empty() {
+            Err(io::Error::new(io::ErrorKind::UnexpectedEof,
+                               "failed to fill whole buffer"))
+        } else {
+            Ok(())
+        }
+    }
+
     /// Writes a number of bytes starting from a given offset.
     ///
     /// Returns the number of bytes written.
@@ -78,21 +150,76 @@ pub trait FileExt {
     ///
     /// # Examples
     ///
-    /// ```
-    /// use std::os::unix::prelude::FileExt;
+    /// ```no_run
     /// use std::fs::File;
+    /// use std::io;
+    /// use std::os::unix::prelude::FileExt;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let file = File::open("foo.txt")?;
+    /// fn main() -> io::Result<()> {
+    ///     let file = File::open("foo.txt")?;
     ///
-    /// // We now write at the offset 10.
-    /// file.write_at(b"sushi", 10)?;
-    /// # Ok(())
-    /// # }
+    ///     // 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>;
+
+    /// Attempts to write an entire buffer starting from a given offset.
+    ///
+    /// The offset is relative to the start of the file and thus independent
+    /// from the current cursor.
+    ///
+    /// The current file cursor is not affected by this function.
+    ///
+    /// This method will continuously call [`write_at`] until there is no more data
+    /// to be written or an error of non-[`ErrorKind::Interrupted`] kind is
+    /// returned. This method will not return until the entire buffer has been
+    /// successfully written or such an error occurs. The first error that is
+    /// not of [`ErrorKind::Interrupted`] kind generated from this method will be
+    /// returned.
+    ///
+    /// # Errors
+    ///
+    /// This function will return the first error of
+    /// non-[`ErrorKind::Interrupted`] kind that [`write_at`] returns.
+    ///
+    /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
+    /// [`write_at`]: #tymethod.write_at
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(rw_exact_all_at)]
+    /// use std::fs::File;
+    /// use std::io;
+    /// use std::os::unix::prelude::FileExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let file = File::open("foo.txt")?;
+    ///
+    ///     // We now write at the offset 10.
+    ///     file.write_all_at(b"sushi", 10)?;
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "rw_exact_all_at", issue = "51984")]
+    fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
+        while !buf.is_empty() {
+            match self.write_at(buf, offset) {
+                Ok(0) => return Err(io::Error::new(io::ErrorKind::WriteZero,
+                                                   "failed to write whole buffer")),
+                Ok(n) => {
+                    buf = &buf[n..];
+                    offset += n as u64
+                }
+                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
+                Err(e) => return Err(e),
+            }
+        }
+        Ok(())
+    }
 }
 
 #[stable(feature = "file_offset", since = "1.15.0")]
@@ -105,7 +232,9 @@ impl FileExt for fs::File {
     }
 }
 
-/// Unix-specific extensions to `Permissions`
+/// Unix-specific extensions to [`fs::Permissions`].
+///
+/// [`fs::Permissions`]: ../../../../std/fs/struct.Permissions.html
 #[stable(feature = "fs_ext", since = "1.1.0")]
 pub trait PermissionsExt {
     /// Returns the underlying raw `st_mode` bits that contain the standard
@@ -117,13 +246,13 @@ pub trait PermissionsExt {
     /// use std::fs::File;
     /// use std::os::unix::fs::PermissionsExt;
     ///
-    /// # fn run() -> std::io::Result<()> {
-    /// let f = File::create("foo.txt")?;
-    /// let metadata = f.metadata()?;
-    /// let permissions = metadata.permissions();
+    /// fn main() -> std::io::Result<()> {
+    ///     let f = File::create("foo.txt")?;
+    ///     let metadata = f.metadata()?;
+    ///     let permissions = metadata.permissions();
     ///
-    /// println!("permissions: {}", permissions.mode());
-    /// # Ok(()) }
+    ///     println!("permissions: {}", permissions.mode());
+    ///     Ok(()) }
     /// ```
     #[stable(feature = "fs_ext", since = "1.1.0")]
     fn mode(&self) -> u32;
@@ -136,14 +265,14 @@ pub trait PermissionsExt {
     /// use std::fs::File;
     /// use std::os::unix::fs::PermissionsExt;
     ///
-    /// # fn run() -> std::io::Result<()> {
-    /// let f = File::create("foo.txt")?;
-    /// let metadata = f.metadata()?;
-    /// let mut permissions = metadata.permissions();
+    /// fn main() -> std::io::Result<()> {
+    ///     let f = File::create("foo.txt")?;
+    ///     let metadata = f.metadata()?;
+    ///     let mut permissions = metadata.permissions();
     ///
-    /// permissions.set_mode(0o644); // Read/write for owner and read for others.
-    /// assert_eq!(permissions.mode(), 0o644);
-    /// # Ok(()) }
+    ///     permissions.set_mode(0o644); // Read/write for owner and read for others.
+    ///     assert_eq!(permissions.mode(), 0o644);
+    ///     Ok(()) }
     /// ```
     #[stable(feature = "fs_ext", since = "1.1.0")]
     fn set_mode(&mut self, mode: u32);
@@ -180,7 +309,9 @@ impl PermissionsExt for Permissions {
     }
 }
 
-/// Unix-specific extensions to `OpenOptions`
+/// Unix-specific extensions to [`fs::OpenOptions`].
+///
+/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html
 #[stable(feature = "fs_ext", since = "1.1.0")]
 pub trait OpenOptionsExt {
     /// Sets the mode bits that a new file will be created with.
@@ -246,13 +377,9 @@ impl OpenOptionsExt for OpenOptions {
     }
 }
 
-// Hm, why are there casts here to the returned type, shouldn't the types always
-// be the same? Right you are! Turns out, however, on android at least the types
-// in the raw `stat` structure are not the same as the types being returned. Who
-// knew!
-//
-// As a result to make sure this compiles for all platforms we do the manual
-// casts and rely on manual lowering to `stat` if the raw type is desired.
+/// Unix-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Returns the ID of the device containing the file.
@@ -260,15 +387,15 @@ pub trait MetadataExt {
     /// # Examples
     ///
     /// ```no_run
+    /// use std::io;
     /// 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(())
-    /// # }
+    /// fn main() -> 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;
@@ -279,13 +406,13 @@ pub trait MetadataExt {
     /// ```no_run
     /// use std::fs;
     /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// let inode = meta.ino();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -296,17 +423,17 @@ pub trait MetadataExt {
     /// ```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(())
-    /// # }
+    /// use std::io;
+    ///
+    /// fn main() -> 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;
@@ -317,13 +444,13 @@ pub trait MetadataExt {
     /// ```no_run
     /// use std::fs;
     /// use std::os::unix::fs::MetadataExt;
+    ///  use std::io;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// let nb_hard_links = meta.nlink();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -334,13 +461,13 @@ pub trait MetadataExt {
     /// ```no_run
     /// use std::fs;
     /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// let user_id = meta.uid();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -351,13 +478,13 @@ pub trait MetadataExt {
     /// ```no_run
     /// use std::fs;
     /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// let group_id = meta.gid();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -368,13 +495,13 @@ pub trait MetadataExt {
     /// ```no_run
     /// use std::fs;
     /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// let device_id = meta.rdev();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -385,13 +512,13 @@ pub trait MetadataExt {
     /// ```no_run
     /// use std::fs;
     /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// let file_size = meta.size();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -402,13 +529,13 @@ pub trait MetadataExt {
     /// ```no_run
     /// use std::fs;
     /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// let last_access_time = meta.atime();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -419,13 +546,13 @@ pub trait MetadataExt {
     /// ```no_run
     /// use std::fs;
     /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// let nano_last_access_time = meta.atime_nsec();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -436,13 +563,13 @@ pub trait MetadataExt {
     /// ```no_run
     /// use std::fs;
     /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// let last_modification_time = meta.mtime();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -453,13 +580,13 @@ pub trait MetadataExt {
     /// ```no_run
     /// use std::fs;
     /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// let nano_last_modification_time = meta.mtime_nsec();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -470,13 +597,13 @@ pub trait MetadataExt {
     /// ```no_run
     /// use std::fs;
     /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// let last_status_change_time = meta.ctime();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -487,13 +614,13 @@ pub trait MetadataExt {
     /// ```no_run
     /// use std::fs;
     /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// let nano_last_status_change_time = meta.ctime_nsec();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -504,13 +631,13 @@ pub trait MetadataExt {
     /// ```no_run
     /// use std::fs;
     /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// let blocksize = meta.blksize();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -523,13 +650,13 @@ pub trait MetadataExt {
     /// ```no_run
     /// use std::fs;
     /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
     ///
-    /// # use std::io;
-    /// # fn f() -> io::Result<()> {
-    /// let meta = fs::metadata("some_file")?;
-    /// let blocks = meta.blocks();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> 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;
@@ -555,24 +682,29 @@ impl MetadataExt for fs::Metadata {
     fn blocks(&self) -> u64 { self.st_blocks() }
 }
 
-/// Add support for special unix types (block/char device, fifo and socket).
+/// Unix-specific extensions for [`FileType`].
+///
+/// Adds support for special Unix file types such as block/character devices,
+/// pipes, and sockets.
+///
+/// [`FileType`]: ../../../../std/fs/struct.FileType.html
 #[stable(feature = "file_type_ext", since = "1.5.0")]
 pub trait FileTypeExt {
     /// Returns whether this file type is a block device.
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
     /// use std::os::unix::fs::FileTypeExt;
+    /// use std::io;
     ///
-    /// # 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(())
-    /// # }
+    /// fn main() -> 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;
@@ -580,17 +712,17 @@ pub trait FileTypeExt {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
     /// use std::os::unix::fs::FileTypeExt;
+    /// use std::io;
     ///
-    /// # 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(())
-    /// # }
+    /// fn main() -> 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;
@@ -598,17 +730,17 @@ pub trait FileTypeExt {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
     /// use std::os::unix::fs::FileTypeExt;
+    /// use std::io;
     ///
-    /// # 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(())
-    /// # }
+    /// fn main() -> 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;
@@ -616,17 +748,17 @@ pub trait FileTypeExt {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```no_run
     /// use std::fs;
     /// use std::os::unix::fs::FileTypeExt;
+    /// use std::io;
     ///
-    /// # 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(())
-    /// # }
+    /// fn main() -> 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;
@@ -687,13 +819,13 @@ impl DirEntryExt for fs::DirEntry {
 ///
 /// # Examples
 ///
-/// ```
+/// ```no_run
 /// use std::os::unix::fs;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::symlink("a.txt", "b.txt")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     fs::symlink("a.txt", "b.txt")?;
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "symlink", since = "1.1.0")]
 pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
@@ -701,10 +833,10 @@ pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
     sys::fs::symlink(src.as_ref(), dst.as_ref())
 }
 
-#[stable(feature = "dir_builder", since = "1.6.0")]
-/// An extension trait for [`fs::DirBuilder`] for unix-specific options.
+/// Unix-specific extensions to [`fs::DirBuilder`].
 ///
 /// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html
+#[stable(feature = "dir_builder", since = "1.6.0")]
 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 c221f7c8cfe..88e4237f8e2 100644
--- a/src/libstd/sys/unix/ext/mod.rs
+++ b/src/libstd/sys/unix/ext/mod.rs
@@ -35,6 +35,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(cfg(unix))]
+#![allow(missing_docs)]
 
 pub mod io;
 pub mod ffi;
diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs
index 86b0f35be92..55f43ccd7db 100644
--- a/src/libstd/sys/unix/ext/net.rs
+++ b/src/libstd/sys/unix/ext/net.rs
@@ -51,13 +51,11 @@ use libc::MSG_NOSIGNAL;
 const MSG_NOSIGNAL: libc::c_int = 0x0;
 
 fn sun_path_offset() -> usize {
-    unsafe {
-        // Work with an actual instance of the type since using a null pointer is UB
-        let addr: libc::sockaddr_un = mem::uninitialized();
-        let base = &addr as *const _ as usize;
-        let path = &addr.sun_path as *const _ as usize;
-        path - base
-    }
+    // Work with an actual instance of the type since using a null pointer is UB
+    let addr: libc::sockaddr_un = unsafe { mem::uninitialized() };
+    let base = &addr as *const _ as usize;
+    let path = &addr.sun_path as *const _ as usize;
+    path - base
 }
 
 unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> {
@@ -216,7 +214,10 @@ impl SocketAddr {
         let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) };
 
         // macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses
-        if len == 0 || (cfg!(not(target_os = "linux")) && self.addr.sun_path[0] == 0) {
+        if len == 0
+            || (cfg!(not(any(target_os = "linux", target_os = "android")))
+                && self.addr.sun_path[0] == 0)
+        {
             AddressKind::Unnamed
         } else if self.addr.sun_path[0] == 0 {
             AddressKind::Abstract(&path[1..len])
@@ -387,10 +388,11 @@ impl UnixStream {
     /// Sets the read timeout for the socket.
     ///
     /// If the provided value is [`None`], then [`read`] calls will block
-    /// indefinitely. It is an error to pass the zero [`Duration`] to this
+    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this
     /// method.
     ///
     /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+    /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err
     /// [`read`]: ../../../../std/io/trait.Read.html#tymethod.read
     /// [`Duration`]: ../../../../std/time/struct.Duration.html
     ///
@@ -403,6 +405,20 @@ impl UnixStream {
     /// let socket = UnixStream::connect("/tmp/sock").unwrap();
     /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
     /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::os::unix::net::UnixStream;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
         self.0.set_timeout(timeout, libc::SO_RCVTIMEO)
@@ -411,11 +427,12 @@ impl UnixStream {
     /// Sets the write timeout for the socket.
     ///
     /// If the provided value is [`None`], then [`write`] calls will block
-    /// indefinitely. It is an error to pass the zero [`Duration`] to this
-    /// method.
+    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
+    /// passed to this method.
     ///
     /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
-    /// [`read`]: ../../../../std/io/trait.Write.html#tymethod.write
+    /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err
+    /// [`write`]: ../../../../std/io/trait.Write.html#tymethod.write
     /// [`Duration`]: ../../../../std/time/struct.Duration.html
     ///
     /// # Examples
@@ -427,6 +444,20 @@ impl UnixStream {
     /// let socket = UnixStream::connect("/tmp/sock").unwrap();
     /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout");
     /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::net::UdpSocket;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap();
+    /// let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
         self.0.set_timeout(timeout, libc::SO_SNDTIMEO)
@@ -493,6 +524,9 @@ impl UnixStream {
     ///     println!("Got error: {:?}", err);
     /// }
     /// ```
+    ///
+    /// # Platform specific
+    /// On Redox this always returns None.
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
         self.0.take_error()
@@ -815,6 +849,9 @@ impl UnixListener {
     ///     println!("Got error: {:?}", err);
     /// }
     /// ```
+    ///
+    /// # Platform specific
+    /// On Redox this always returns None.
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
         self.0.take_error()
@@ -1250,10 +1287,11 @@ impl UnixDatagram {
     /// Sets the read timeout for the socket.
     ///
     /// If the provided value is [`None`], then [`recv`] and [`recv_from`] calls will
-    /// block indefinitely. It is an error to pass the zero [`Duration`] to this
-    /// method.
+    /// block indefinitely. An [`Err`] is returned if the zero [`Duration`]
+    /// is passed to this method.
     ///
     /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+    /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err
     /// [`recv`]: #method.recv
     /// [`recv_from`]: #method.recv_from
     /// [`Duration`]: ../../../../std/time/struct.Duration.html
@@ -1267,6 +1305,20 @@ impl UnixDatagram {
     /// let sock = UnixDatagram::unbound().unwrap();
     /// sock.set_read_timeout(Some(Duration::new(1, 0))).expect("set_read_timeout function failed");
     /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixDatagram::unbound().unwrap();
+    /// let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
         self.0.set_timeout(timeout, libc::SO_RCVTIMEO)
@@ -1275,7 +1327,7 @@ impl UnixDatagram {
     /// Sets the write timeout for the socket.
     ///
     /// If the provided value is [`None`], then [`send`] and [`send_to`] calls will
-    /// block indefinitely. It is an error to pass the zero [`Duration`] to this
+    /// block indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this
     /// method.
     ///
     /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
@@ -1293,6 +1345,20 @@ impl UnixDatagram {
     /// sock.set_write_timeout(Some(Duration::new(1, 0)))
     ///     .expect("set_write_timeout function failed");
     /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixDatagram::unbound().unwrap();
+    /// let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
         self.0.set_timeout(timeout, libc::SO_SNDTIMEO)
@@ -1410,7 +1476,7 @@ impl IntoRawFd for UnixDatagram {
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod test {
     use thread;
-    use io;
+    use io::{self, ErrorKind};
     use io::prelude::*;
     use time::Duration;
     use sys_common::io::test::tmpdir;
@@ -1613,6 +1679,27 @@ mod test {
         assert!(kind == io::ErrorKind::WouldBlock || kind == io::ErrorKind::TimedOut);
     }
 
+    // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors
+    // when passed zero Durations
+    #[test]
+    fn test_unix_stream_timeout_zero_duration() {
+        let dir = tmpdir();
+        let socket_path = dir.path().join("sock");
+
+        let listener = or_panic!(UnixListener::bind(&socket_path));
+        let stream = or_panic!(UnixStream::connect(&socket_path));
+
+        let result = stream.set_write_timeout(Some(Duration::new(0, 0)));
+        let err = result.unwrap_err();
+        assert_eq!(err.kind(), ErrorKind::InvalidInput);
+
+        let result = stream.set_read_timeout(Some(Duration::new(0, 0)));
+        let err = result.unwrap_err();
+        assert_eq!(err.kind(), ErrorKind::InvalidInput);
+
+        drop(listener);
+    }
+
     #[test]
     fn test_unix_datagram() {
         let dir = tmpdir();
@@ -1712,6 +1799,24 @@ mod test {
         thread.join().unwrap();
     }
 
+    // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors
+    // when passed zero Durations
+    #[test]
+    fn test_unix_datagram_timeout_zero_duration() {
+        let dir = tmpdir();
+        let path = dir.path().join("sock");
+
+        let datagram = or_panic!(UnixDatagram::bind(&path));
+
+        let result = datagram.set_write_timeout(Some(Duration::new(0, 0)));
+        let err = result.unwrap_err();
+        assert_eq!(err.kind(), ErrorKind::InvalidInput);
+
+        let result = datagram.set_read_timeout(Some(Duration::new(0, 0)));
+        let err = result.unwrap_err();
+        assert_eq!(err.kind(), ErrorKind::InvalidInput);
+    }
+
     #[test]
     fn abstract_namespace_not_allowed() {
         assert!(UnixStream::connect("\0asdf").is_err());
diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs
index 60309bec6d4..21630ae9746 100644
--- a/src/libstd/sys/unix/ext/process.rs
+++ b/src/libstd/sys/unix/ext/process.rs
@@ -18,7 +18,9 @@ use process;
 use sys;
 use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner};
 
-/// Unix-specific extensions to the `std::process::Command` builder
+/// Unix-specific extensions to the [`process::Command`] builder.
+///
+/// [`process::Command`]: ../../../../std/process/struct.Command.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait CommandExt {
     /// Sets the child process's user id. This translates to a
@@ -117,7 +119,9 @@ impl CommandExt for process::Command {
     }
 }
 
-/// Unix-specific extensions to `std::process::ExitStatus`
+/// Unix-specific extensions to [`process::ExitStatus`].
+///
+/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait ExitStatusExt {
     /// Creates a new `ExitStatus` from the raw underlying `i32` return value of
@@ -193,7 +197,7 @@ impl IntoRawFd for process::ChildStderr {
 }
 
 /// Returns the OS-assigned process identifier associated with this process's parent.
-#[unstable(feature = "unix_ppid", issue = "46104")]
+#[stable(feature = "unix_ppid", since = "1.27.0")]
 pub fn parent_id() -> u32 {
     ::sys::os::getppid()
 }
diff --git a/src/libstd/sys/unix/ext/thread.rs b/src/libstd/sys/unix/ext/thread.rs
index fe2a48764dc..8dadf29945c 100644
--- a/src/libstd/sys/unix/ext/thread.rs
+++ b/src/libstd/sys/unix/ext/thread.rs
@@ -21,7 +21,9 @@ use thread::JoinHandle;
 #[allow(deprecated)]
 pub type RawPthread = pthread_t;
 
-/// Unix-specific extensions to `std::thread::JoinHandle`
+/// Unix-specific extensions to [`thread::JoinHandle`].
+///
+/// [`thread::JoinHandle`]: ../../../../std/thread/struct.JoinHandle.html
 #[stable(feature = "thread_extensions", since = "1.9.0")]
 pub trait JoinHandleExt {
     /// Extracts the raw pthread_t without taking ownership
diff --git a/src/libstd/sys/unix/fast_thread_local.rs b/src/libstd/sys/unix/fast_thread_local.rs
index 6cdbe5df75d..c13a0fea1e0 100644
--- a/src/libstd/sys/unix/fast_thread_local.rs
+++ b/src/libstd/sys/unix/fast_thread_local.rs
@@ -20,7 +20,7 @@
 // fallback implementation to use as well.
 //
 // Due to rust-lang/rust#18804, make sure this is not generic!
-#[cfg(target_os = "linux")]
+#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "hermit"))]
 pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
     use libc;
     use mem;
@@ -55,11 +55,6 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
     _tlv_atexit(dtor, t);
 }
 
-// Just use the thread_local fallback implementation, at least until there's
-// a more direct implementation.
-#[cfg(target_os = "fuchsia")]
-pub use sys_common::thread_local::register_dtor_fallback as register_dtor;
-
 pub fn requires_move_before_drop() -> bool {
     // The macOS implementation of TLS apparently had an odd aspect to it
     // where the pointer we have may be overwritten while this destructor
diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs
index 5dafc3251e7..4830e38d6a9 100644
--- a/src/libstd/sys/unix/fd.rs
+++ b/src/libstd/sys/unix/fd.rs
@@ -75,8 +75,15 @@ impl FileDesc {
         unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: usize, offset: i64)
             -> io::Result<isize>
         {
+            use convert::TryInto;
             use libc::pread64;
-            cvt(pread64(fd, buf, count, offset as i32))
+            // pread64 on emscripten actually takes a 32 bit offset
+            if let Ok(o) = offset.try_into() {
+                cvt(pread64(fd, buf, count, o))
+            } else {
+                Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                   "cannot pread >2GB"))
+            }
         }
 
         #[cfg(not(any(target_os = "android", target_os = "emscripten")))]
@@ -116,8 +123,15 @@ impl FileDesc {
         unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: usize, offset: i64)
             -> io::Result<isize>
         {
+            use convert::TryInto;
             use libc::pwrite64;
-            cvt(pwrite64(fd, buf, count, offset as i32))
+            // pwrite64 on emscripten actually takes a 32 bit offset
+            if let Ok(o) = offset.try_into() {
+                cvt(pwrite64(fd, buf, count, o))
+            } else {
+                Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                   "cannot pwrite >2GB"))
+            }
         }
 
         #[cfg(not(any(target_os = "android", target_os = "emscripten")))]
@@ -140,6 +154,13 @@ impl FileDesc {
         }
     }
 
+    #[cfg(target_os = "linux")]
+    pub fn get_cloexec(&self) -> io::Result<bool> {
+        unsafe {
+            Ok((cvt(libc::fcntl(self.fd, libc::F_GETFD))? & libc::FD_CLOEXEC) != 0)
+        }
+    }
+
     #[cfg(not(any(target_env = "newlib",
                   target_os = "solaris",
                   target_os = "emscripten",
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index a1ca839dc18..7a89d9857bb 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -25,8 +25,12 @@ use sys_common::{AsInner, FromInner};
 
 #[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "l4re"))]
 use libc::{stat64, fstat64, lstat64, off64_t, ftruncate64, lseek64, dirent64, readdir64_r, open64};
+#[cfg(any(target_os = "linux", target_os = "emscripten"))]
+use libc::fstatat64;
+#[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))]
+use libc::dirfd;
 #[cfg(target_os = "android")]
-use libc::{stat as stat64, fstat as fstat64, lstat as lstat64, lseek64,
+use libc::{stat as stat64, fstat as fstat64, fstatat as fstatat64, lstat as lstat64, lseek64,
            dirent as dirent64, open as open64};
 #[cfg(not(any(target_os = "linux",
               target_os = "emscripten",
@@ -48,9 +52,16 @@ pub struct FileAttr {
     stat: stat64,
 }
 
-pub struct ReadDir {
+// all DirEntry's will have a reference to this struct
+struct InnerReadDir {
     dirp: Dir,
-    root: Arc<PathBuf>,
+    root: PathBuf,
+}
+
+#[derive(Clone)]
+pub struct ReadDir {
+    inner: Arc<InnerReadDir>,
+    end_of_stream: bool,
 }
 
 struct Dir(*mut libc::DIR);
@@ -60,8 +71,8 @@ unsafe impl Sync for Dir {}
 
 pub struct DirEntry {
     entry: dirent64,
-    root: Arc<PathBuf>,
-    // We need to store an owned copy of the directory name
+    dir: ReadDir,
+    // We need to store an owned copy of the entry name
     // on Solaris and Fuchsia because a) it uses a zero-length
     // array to store the name, b) its lifetime between readdir
     // calls is not guaranteed.
@@ -207,7 +218,7 @@ impl fmt::Debug for ReadDir {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         // This will only be called from std::fs::ReadDir, which will add a "ReadDir()" frame.
         // Thus the result will be e g 'ReadDir("/home")'
-        fmt::Debug::fmt(&*self.root, f)
+        fmt::Debug::fmt(&*self.inner.root, f)
     }
 }
 
@@ -223,7 +234,7 @@ impl Iterator for ReadDir {
                 // is safe to use in threaded applications and it is generally preferred
                 // over the readdir_r(3C) function.
                 super::os::set_errno(0);
-                let entry_ptr = libc::readdir(self.dirp.0);
+                let entry_ptr = libc::readdir(self.inner.dirp.0);
                 if entry_ptr.is_null() {
                     // NULL can mean either the end is reached or an error occurred.
                     // So we had to clear errno beforehand to check for an error now.
@@ -240,7 +251,7 @@ impl Iterator for ReadDir {
                     entry: *entry_ptr,
                     name: ::slice::from_raw_parts(name as *const u8,
                                                   namelen as usize).to_owned().into_boxed_slice(),
-                    root: self.root.clone()
+                    dir: self.clone()
                 };
                 if ret.name_bytes() != b"." && ret.name_bytes() != b".." {
                     return Some(Ok(ret))
@@ -251,14 +262,25 @@ impl Iterator for ReadDir {
 
     #[cfg(not(any(target_os = "solaris", target_os = "fuchsia")))]
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
+        if self.end_of_stream {
+            return None;
+        }
+
         unsafe {
             let mut ret = DirEntry {
                 entry: mem::zeroed(),
-                root: self.root.clone()
+                dir: self.clone(),
             };
             let mut entry_ptr = ptr::null_mut();
             loop {
-                if readdir64_r(self.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 {
+                if readdir64_r(self.inner.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 {
+                    if entry_ptr.is_null() {
+                        // We encountered an error (which will be returned in this iteration), but
+                        // we also reached the end of the directory stream. The `end_of_stream`
+                        // flag is enabled to make sure that we return `None` in the next iteration
+                        // (instead of looping forever)
+                        self.end_of_stream = true;
+                    }
                     return Some(Err(Error::last_os_error()))
                 }
                 if entry_ptr.is_null() {
@@ -281,23 +303,34 @@ impl Drop for Dir {
 
 impl DirEntry {
     pub fn path(&self) -> PathBuf {
-        self.root.join(OsStr::from_bytes(self.name_bytes()))
+        self.dir.inner.root.join(OsStr::from_bytes(self.name_bytes()))
     }
 
     pub fn file_name(&self) -> OsString {
         OsStr::from_bytes(self.name_bytes()).to_os_string()
     }
 
+    #[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))]
+    pub fn metadata(&self) -> io::Result<FileAttr> {
+        let fd = cvt(unsafe {dirfd(self.dir.inner.dirp.0)})?;
+        let mut stat: stat64 = unsafe { mem::zeroed() };
+        cvt(unsafe {
+            fstatat64(fd, self.entry.d_name.as_ptr(), &mut stat, libc::AT_SYMLINK_NOFOLLOW)
+        })?;
+        Ok(FileAttr { stat: stat })
+    }
+
+    #[cfg(not(any(target_os = "linux", target_os = "emscripten", target_os = "android")))]
     pub fn metadata(&self) -> io::Result<FileAttr> {
         lstat(&self.path())
     }
 
-    #[cfg(any(target_os = "solaris", target_os = "haiku"))]
+    #[cfg(any(target_os = "solaris", target_os = "haiku", target_os = "hermit"))]
     pub fn file_type(&self) -> io::Result<FileType> {
         lstat(&self.path()).map(|m| m.file_type())
     }
 
-    #[cfg(not(any(target_os = "solaris", target_os = "haiku")))]
+    #[cfg(not(any(target_os = "solaris", target_os = "haiku", target_os = "hermit")))]
     pub fn file_type(&self) -> io::Result<FileType> {
         match self.entry.d_type {
             libc::DT_CHR => Ok(FileType { mode: libc::S_IFCHR }),
@@ -319,7 +352,8 @@ impl DirEntry {
               target_os = "solaris",
               target_os = "haiku",
               target_os = "l4re",
-              target_os = "fuchsia"))]
+              target_os = "fuchsia",
+              target_os = "hermit"))]
     pub fn ino(&self) -> u64 {
         self.entry.d_ino as u64
     }
@@ -350,7 +384,8 @@ impl DirEntry {
               target_os = "linux",
               target_os = "emscripten",
               target_os = "l4re",
-              target_os = "haiku"))]
+              target_os = "haiku",
+              target_os = "hermit"))]
     fn name_bytes(&self) -> &[u8] {
         unsafe {
             CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes()
@@ -441,15 +476,48 @@ impl File {
 
         // Currently the standard library supports Linux 2.6.18 which did not
         // have the O_CLOEXEC flag (passed above). If we're running on an older
-        // Linux kernel then the flag is just ignored by the OS, so we continue
-        // to explicitly ask for a CLOEXEC fd here.
+        // Linux kernel then the flag is just ignored by the OS. After we open
+        // the first file, we check whether it has CLOEXEC set. If it doesn't,
+        // we will explicitly ask for a CLOEXEC fd for every further file we
+        // open, if it does, we will skip that step.
         //
         // The CLOEXEC flag, however, is supported on versions of macOS/BSD/etc
         // that we support, so we only do this on Linux currently.
-        if cfg!(target_os = "linux") {
-            fd.set_cloexec()?;
+        #[cfg(target_os = "linux")]
+        fn ensure_cloexec(fd: &FileDesc) -> io::Result<()> {
+            use sync::atomic::{AtomicUsize, Ordering};
+
+            const OPEN_CLOEXEC_UNKNOWN: usize = 0;
+            const OPEN_CLOEXEC_SUPPORTED: usize = 1;
+            const OPEN_CLOEXEC_NOTSUPPORTED: usize = 2;
+            static OPEN_CLOEXEC: AtomicUsize = AtomicUsize::new(OPEN_CLOEXEC_UNKNOWN);
+
+            let need_to_set;
+            match OPEN_CLOEXEC.load(Ordering::Relaxed) {
+                OPEN_CLOEXEC_UNKNOWN => {
+                    need_to_set = !fd.get_cloexec()?;
+                    OPEN_CLOEXEC.store(if need_to_set {
+                        OPEN_CLOEXEC_NOTSUPPORTED
+                    } else {
+                        OPEN_CLOEXEC_SUPPORTED
+                    }, Ordering::Relaxed);
+                },
+                OPEN_CLOEXEC_SUPPORTED => need_to_set = false,
+                OPEN_CLOEXEC_NOTSUPPORTED => need_to_set = true,
+                _ => unreachable!(),
+            }
+            if need_to_set {
+                fd.set_cloexec()?;
+            }
+            Ok(())
+        }
+
+        #[cfg(not(target_os = "linux"))]
+        fn ensure_cloexec(_: &FileDesc) -> io::Result<()> {
+            Ok(())
         }
 
+        ensure_cloexec(&fd)?;
         Ok(File(fd))
     }
 
@@ -631,14 +699,18 @@ impl fmt::Debug for File {
 }
 
 pub fn readdir(p: &Path) -> io::Result<ReadDir> {
-    let root = Arc::new(p.to_path_buf());
+    let root = p.to_path_buf();
     let p = cstr(p)?;
     unsafe {
         let ptr = libc::opendir(p.as_ptr());
         if ptr.is_null() {
             Err(Error::last_os_error())
         } else {
-            Ok(ReadDir { dirp: Dir(ptr), root: root })
+            let inner = InnerReadDir { dirp: Dir(ptr), root };
+            Ok(ReadDir{
+                inner: Arc::new(inner),
+                end_of_stream: false,
+            })
         }
     }
 }
@@ -733,7 +805,7 @@ pub fn stat(p: &Path) -> io::Result<FileAttr> {
     let p = cstr(p)?;
     let mut stat: stat64 = unsafe { mem::zeroed() };
     cvt(unsafe {
-        stat64(p.as_ptr(), &mut stat as *mut _ as *mut _)
+        stat64(p.as_ptr(), &mut stat)
     })?;
     Ok(FileAttr { stat: stat })
 }
@@ -742,7 +814,7 @@ pub fn lstat(p: &Path) -> io::Result<FileAttr> {
     let p = cstr(p)?;
     let mut stat: stat64 = unsafe { mem::zeroed() };
     cvt(unsafe {
-        lstat64(p.as_ptr(), &mut stat as *mut _ as *mut _)
+        lstat64(p.as_ptr(), &mut stat)
     })?;
     Ok(FileAttr { stat: stat })
 }
@@ -761,8 +833,9 @@ pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
     Ok(PathBuf::from(OsString::from_vec(buf)))
 }
 
+#[cfg(not(any(target_os = "linux", target_os = "android")))]
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
-    use fs::{File, set_permissions};
+    use fs::File;
     if !from.is_file() {
         return Err(Error::new(ErrorKind::InvalidInput,
                               "the source path is not an existing regular file"))
@@ -773,6 +846,100 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
     let perm = reader.metadata()?.permissions();
 
     let ret = io::copy(&mut reader, &mut writer)?;
-    set_permissions(to, perm)?;
+    writer.set_permissions(perm)?;
     Ok(ret)
 }
+
+#[cfg(any(target_os = "linux", target_os = "android"))]
+pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
+    use cmp;
+    use fs::File;
+    use sync::atomic::{AtomicBool, Ordering};
+
+    // Kernel prior to 4.5 don't have copy_file_range
+    // We store the availability in a global to avoid unneccessary syscalls
+    static HAS_COPY_FILE_RANGE: AtomicBool = AtomicBool::new(true);
+
+    unsafe fn copy_file_range(
+        fd_in: libc::c_int,
+        off_in: *mut libc::loff_t,
+        fd_out: libc::c_int,
+        off_out: *mut libc::loff_t,
+        len: libc::size_t,
+        flags: libc::c_uint,
+    ) -> libc::c_long {
+        libc::syscall(
+            libc::SYS_copy_file_range,
+            fd_in,
+            off_in,
+            fd_out,
+            off_out,
+            len,
+            flags,
+        )
+    }
+
+    if !from.is_file() {
+        return Err(Error::new(ErrorKind::InvalidInput,
+                              "the source path is not an existing regular file"))
+    }
+
+    let mut reader = File::open(from)?;
+    let mut writer = File::create(to)?;
+    let (perm, len) = {
+        let metadata = reader.metadata()?;
+        (metadata.permissions(), metadata.size())
+    };
+
+    let has_copy_file_range = HAS_COPY_FILE_RANGE.load(Ordering::Relaxed);
+    let mut written = 0u64;
+    while written < len {
+        let copy_result = if has_copy_file_range {
+            let bytes_to_copy = cmp::min(len - written, usize::max_value() as u64) as usize;
+            let copy_result = unsafe {
+                // We actually don't have to adjust the offsets,
+                // because copy_file_range adjusts the file offset automatically
+                cvt(copy_file_range(reader.as_raw_fd(),
+                                    ptr::null_mut(),
+                                    writer.as_raw_fd(),
+                                    ptr::null_mut(),
+                                    bytes_to_copy,
+                                    0)
+                    )
+            };
+            if let Err(ref copy_err) = copy_result {
+                match copy_err.raw_os_error() {
+                    Some(libc::ENOSYS) | Some(libc::EPERM) => {
+                        HAS_COPY_FILE_RANGE.store(false, Ordering::Relaxed);
+                    }
+                    _ => {}
+                }
+            }
+            copy_result
+        } else {
+            Err(io::Error::from_raw_os_error(libc::ENOSYS))
+        };
+        match copy_result {
+            Ok(ret) => written += ret as u64,
+            Err(err) => {
+                match err.raw_os_error() {
+                    Some(os_err) if os_err == libc::ENOSYS
+                                 || os_err == libc::EXDEV
+                                 || os_err == libc::EPERM => {
+                        // Try fallback io::copy if either:
+                        // - Kernel version is < 4.5 (ENOSYS)
+                        // - Files are mounted on different fs (EXDEV)
+                        // - copy_file_range is disallowed, for example by seccomp (EPERM)
+                        assert_eq!(written, 0);
+                        let ret = io::copy(&mut reader, &mut writer)?;
+                        writer.set_permissions(perm)?;
+                        return Ok(ret)
+                    },
+                    _ => return Err(err),
+                }
+            }
+        }
+    }
+    writer.set_permissions(perm)?;
+    Ok(written)
+}
diff --git a/src/libstd/sys/unix/l4re.rs b/src/libstd/sys/unix/l4re.rs
index c3e8d0b7d95..21218489679 100644
--- a/src/libstd/sys/unix/l4re.rs
+++ b/src/libstd/sys/unix/l4re.rs
@@ -437,9 +437,5 @@ 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 9bdea945ea4..c738003caf1 100644
--- a/src/libstd/sys/unix/mod.rs
+++ b/src/libstd/sys/unix/mod.rs
@@ -28,6 +28,7 @@ use libc;
 #[cfg(all(not(dox), target_os = "emscripten"))] pub use os::emscripten as platform;
 #[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;
+#[cfg(all(not(dox), target_os = "hermit"))]    pub use os::hermit as platform;
 
 pub use self::rand::hashmap_random_keys;
 pub use libc::strlen;
@@ -80,11 +81,11 @@ pub fn init() {
         reset_sigpipe();
     }
 
-    #[cfg(not(any(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 = "emscripten", target_os="fuchsia"))]
+    #[cfg(any(target_os = "emscripten", target_os = "fuchsia"))]
     unsafe fn reset_sigpipe() {}
 }
 
diff --git a/src/libstd/sys/unix/mutex.rs b/src/libstd/sys/unix/mutex.rs
index 52cf3f97c5c..1d447de1134 100644
--- a/src/libstd/sys/unix/mutex.rs
+++ b/src/libstd/sys/unix/mutex.rs
@@ -25,8 +25,10 @@ unsafe impl Sync for Mutex {}
 #[allow(dead_code)] // sys isn't exported yet
 impl Mutex {
     pub const fn new() -> Mutex {
-        // Might be moved and address is changing it is better to avoid
-        // initialization of potentially opaque OS data before it landed
+        // Might be moved to a different address, so it is better to avoid
+        // initialization of potentially opaque OS data before it landed.
+        // Be very careful using this newly constructed `Mutex`, reentrant
+        // locking is undefined behavior until `init` is called!
         Mutex { inner: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER) }
     }
     #[inline]
@@ -49,9 +51,6 @@ impl Mutex {
         // references, we instead create the mutex with type
         // PTHREAD_MUTEX_NORMAL which is guaranteed to deadlock if we try to
         // re-lock it from the same thread, thus avoiding undefined behavior.
-        //
-        // We can't do anything for StaticMutex, but that type is deprecated
-        // anyways.
         let mut attr: libc::pthread_mutexattr_t = mem::uninitialized();
         let r = libc::pthread_mutexattr_init(&mut attr);
         debug_assert_eq!(r, 0);
diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs
index e775f857f2b..04d9f0b06d3 100644
--- a/src/libstd/sys/unix/net.rs
+++ b/src/libstd/sys/unix/net.rs
@@ -51,6 +51,10 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> {
     if err == 0 {
         return Ok(())
     }
+
+    // We may need to trigger a glibc workaround. See on_resolver_failure() for details.
+    on_resolver_failure();
+
     if err == EAI_SYSTEM {
         return Err(io::Error::last_os_error())
     }
@@ -377,43 +381,22 @@ impl IntoInner<c_int> for Socket {
 // 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<()> {
+#[cfg(target_env = "gnu")]
+fn on_resolver_failure() {
+    use sys;
+
     // 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());
-                }
-            }
+    if let Some(version) = sys::os::glibc_version() {
+        if version < (2, 26) {
+            unsafe { libc::res_init() };
         }
     }
-    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(not(target_env = "gnu"))]
+fn on_resolver_failure() {}
 
-#[cfg(test)]
+#[cfg(all(test, taget_env = "gnu"))]
 mod test {
     use super::*;
 
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
index a46e855b4a6..f8f0bbd5bc2 100644
--- a/src/libstd/sys/unix/os.rs
+++ b/src/libstd/sys/unix/os.rs
@@ -33,6 +33,8 @@ use sys::fd;
 use vec;
 
 const TMPBUF_SZ: usize = 128;
+// We never call `ENV_LOCK.init()`, so it is UB to attempt to
+// acquire this mutex reentrantly!
 static ENV_LOCK: Mutex = Mutex::new();
 
 
@@ -47,6 +49,7 @@ extern {
                    target_os = "netbsd",
                    target_os = "openbsd",
                    target_os = "android",
+                   target_os = "hermit",
                    target_env = "newlib"),
                link_name = "__errno")]
     #[cfg_attr(target_os = "solaris", link_name = "___errno")]
@@ -376,7 +379,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
     }
 }
 
-#[cfg(any(target_os = "fuchsia", target_os = "l4re"))]
+#[cfg(any(target_os = "fuchsia", target_os = "l4re", target_os = "hermit"))]
 pub fn current_exe() -> io::Result<PathBuf> {
     use io::ErrorKind;
     Err(io::Error::new(ErrorKind::Other, "Not yet implemented!"))
@@ -409,26 +412,19 @@ pub unsafe fn environ() -> *mut *const *const c_char {
 /// environment variables of the current process.
 pub fn env() -> Env {
     unsafe {
-        ENV_LOCK.lock();
+        let _guard = ENV_LOCK.lock();
         let mut environ = *environ();
-        if environ == ptr::null() {
-            ENV_LOCK.unlock();
-            panic!("os::env() failure getting env string from OS: {}",
-                   io::Error::last_os_error());
-        }
         let mut result = Vec::new();
-        while *environ != ptr::null() {
+        while environ != ptr::null() && *environ != ptr::null() {
             if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
                 result.push(key_value);
             }
             environ = environ.offset(1);
         }
-        let ret = Env {
+        return Env {
             iter: result.into_iter(),
             _dont_send_or_sync_me: PhantomData,
-        };
-        ENV_LOCK.unlock();
-        return ret
+        }
     }
 
     fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
@@ -452,15 +448,14 @@ pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> {
     // always None as well
     let k = CString::new(k.as_bytes())?;
     unsafe {
-        ENV_LOCK.lock();
+        let _guard = ENV_LOCK.lock();
         let s = libc::getenv(k.as_ptr()) as *const libc::c_char;
         let ret = if s.is_null() {
             None
         } else {
             Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec()))
         };
-        ENV_LOCK.unlock();
-        return Ok(ret)
+        Ok(ret)
     }
 }
 
@@ -469,10 +464,8 @@ pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
     let v = CString::new(v.as_bytes())?;
 
     unsafe {
-        ENV_LOCK.lock();
-        let ret = cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ());
-        ENV_LOCK.unlock();
-        return ret
+        let _guard = ENV_LOCK.lock();
+        cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ())
     }
 }
 
@@ -480,10 +473,8 @@ pub fn unsetenv(n: &OsStr) -> io::Result<()> {
     let nbuf = CString::new(n.as_bytes())?;
 
     unsafe {
-        ENV_LOCK.lock();
-        let ret = cvt(libc::unsetenv(nbuf.as_ptr())).map(|_| ());
-        ENV_LOCK.unlock();
-        return ret
+        let _guard = ENV_LOCK.lock();
+        cvt(libc::unsetenv(nbuf.as_ptr())).map(|_| ())
     }
 }
 
@@ -546,3 +537,35 @@ pub fn getpid() -> u32 {
 pub fn getppid() -> u32 {
     unsafe { libc::getppid() as u32 }
 }
+
+#[cfg(target_env = "gnu")]
+pub fn glibc_version() -> Option<(usize, usize)> {
+    if let Some(Ok(version_str)) = glibc_version_cstr().map(CStr::to_str) {
+        parse_glibc_version(version_str)
+    } else {
+        None
+    }
+}
+
+#[cfg(target_env = "gnu")]
+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.
+#[cfg(target_env = "gnu")]
+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
+    }
+}
diff --git a/src/libstd/sys/unix/os_str.rs b/src/libstd/sys/unix/os_str.rs
index e0349387998..01c0fb830aa 100644
--- a/src/libstd/sys/unix/os_str.rs
+++ b/src/libstd/sys/unix/os_str.rs
@@ -19,7 +19,7 @@ use rc::Rc;
 use sync::Arc;
 use sys_common::{AsInner, IntoInner};
 use sys_common::bytestring::debug_fmt_bytestring;
-use std_unicode::lossy::Utf8Lossy;
+use core::str::lossy::Utf8Lossy;
 
 #[derive(Clone, Hash)]
 pub struct Buf {
@@ -104,6 +104,11 @@ impl Buf {
         self.inner.shrink_to_fit()
     }
 
+    #[inline]
+    pub fn shrink_to(&mut self, min_capacity: usize) {
+        self.inner.shrink_to(min_capacity)
+    }
+
     pub fn as_slice(&self) -> &Slice {
         unsafe { mem::transmute(&*self.inner) }
     }
diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs
index ec9b6f17dca..0a5dccdddda 100644
--- a/src/libstd/sys/unix/pipe.rs
+++ b/src/libstd/sys/unix/pipe.rs
@@ -100,24 +100,6 @@ pub fn read2(p1: AnonPipe,
         // wait for either pipe to become readable using `poll`
         cvt_r(|| unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) })?;
 
-        // Read as much as we can from each pipe, ignoring EWOULDBLOCK or
-        // EAGAIN. If we hit EOF, then this will happen because the underlying
-        // reader will return Ok(0), in which case we'll see `Ok` ourselves. In
-        // this case we flip the other fd back into blocking mode and read
-        // whatever's leftover on that file descriptor.
-        let read = |fd: &FileDesc, dst: &mut Vec<u8>| {
-            match fd.read_to_end(dst) {
-                Ok(_) => Ok(true),
-                Err(e) => {
-                    if e.raw_os_error() == Some(libc::EWOULDBLOCK) ||
-                       e.raw_os_error() == Some(libc::EAGAIN) {
-                        Ok(false)
-                    } else {
-                        Err(e)
-                    }
-                }
-            }
-        };
         if fds[0].revents != 0 && read(&p1, v1)? {
             p2.set_nonblocking(false)?;
             return p2.read_to_end(v2).map(|_| ());
@@ -127,4 +109,23 @@ pub fn read2(p1: AnonPipe,
             return p1.read_to_end(v1).map(|_| ());
         }
     }
+
+    // Read as much as we can from each pipe, ignoring EWOULDBLOCK or
+    // EAGAIN. If we hit EOF, then this will happen because the underlying
+    // reader will return Ok(0), in which case we'll see `Ok` ourselves. In
+    // this case we flip the other fd back into blocking mode and read
+    // whatever's leftover on that file descriptor.
+    fn read(fd: &FileDesc, dst: &mut Vec<u8>) -> Result<bool, io::Error> {
+        match fd.read_to_end(dst) {
+            Ok(_) => Ok(true),
+            Err(e) => {
+                if e.raw_os_error() == Some(libc::EWOULDBLOCK) ||
+                   e.raw_os_error() == Some(libc::EAGAIN) {
+                    Ok(false)
+                } else {
+                    Err(e)
+                }
+            }
+        }
+    }
 }
diff --git a/src/libstd/sys/unix/process/mod.rs b/src/libstd/sys/unix/process/mod.rs
index 2a331069bc2..d8ac26c45b1 100644
--- a/src/libstd/sys/unix/process/mod.rs
+++ b/src/libstd/sys/unix/process/mod.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub use self::process_common::{Command, ExitStatus, Stdio, StdioPipes};
+pub use self::process_common::{Command, ExitStatus, ExitCode, Stdio, StdioPipes};
 pub use self::process_inner::Process;
 
 mod process_common;
diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs
index c53bcdbf8e3..77f125f3c5b 100644
--- a/src/libstd/sys/unix/process/process_common.rs
+++ b/src/libstd/sys/unix/process/process_common.rs
@@ -13,7 +13,7 @@ use os::unix::prelude::*;
 use ffi::{OsString, OsStr, CString, CStr};
 use fmt;
 use io;
-use libc::{self, c_int, gid_t, uid_t, c_char};
+use libc::{self, c_int, gid_t, uid_t, c_char, EXIT_SUCCESS, EXIT_FAILURE};
 use ptr;
 use sys::fd::FileDesc;
 use sys::fs::{File, OpenOptions};
@@ -45,19 +45,25 @@ pub struct Command {
     // other keys.
     program: CString,
     args: Vec<CString>,
-    argv: Vec<*const c_char>,
+    argv: Argv,
     env: CommandEnv<DefaultEnvKey>,
 
     cwd: Option<CString>,
     uid: Option<uid_t>,
     gid: Option<gid_t>,
     saw_nul: bool,
-    closures: Vec<Box<FnMut() -> io::Result<()> + Send + Sync>>,
+    closures: Vec<Box<dyn FnMut() -> io::Result<()> + Send + Sync>>,
     stdin: Option<Stdio>,
     stdout: Option<Stdio>,
     stderr: Option<Stdio>,
 }
 
+// Create a new type for argv, so that we can make it `Send`
+struct Argv(Vec<*const c_char>);
+
+// It is safe to make Argv Send, because it contains pointers to memory owned by `Command.args`
+unsafe impl Send for Argv {}
+
 // passed back to std::process with the pipes connected to the child, if any
 // were requested
 pub struct StdioPipes {
@@ -92,7 +98,7 @@ impl Command {
         let mut saw_nul = false;
         let program = os2c(program, &mut saw_nul);
         Command {
-            argv: vec![program.as_ptr(), ptr::null()],
+            argv: Argv(vec![program.as_ptr(), ptr::null()]),
             program,
             args: Vec::new(),
             env: Default::default(),
@@ -111,8 +117,8 @@ impl Command {
         // Overwrite the trailing NULL pointer in `argv` and then add a new null
         // pointer.
         let arg = os2c(arg, &mut self.saw_nul);
-        self.argv[self.args.len() + 1] = arg.as_ptr();
-        self.argv.push(ptr::null());
+        self.argv.0[self.args.len() + 1] = arg.as_ptr();
+        self.argv.0.push(ptr::null());
 
         // Also make sure we keep track of the owned value to schedule a
         // destructor for this memory.
@@ -133,7 +139,7 @@ impl Command {
         self.saw_nul
     }
     pub fn get_argv(&self) -> &Vec<*const c_char> {
-        &self.argv
+        &self.argv.0
     }
 
     #[allow(dead_code)]
@@ -149,12 +155,12 @@ impl Command {
         self.gid
     }
 
-    pub fn get_closures(&mut self) -> &mut Vec<Box<FnMut() -> io::Result<()> + Send + Sync>> {
+    pub fn get_closures(&mut self) -> &mut Vec<Box<dyn FnMut() -> io::Result<()> + Send + Sync>> {
         &mut self.closures
     }
 
     pub fn before_exec(&mut self,
-                       f: Box<FnMut() -> io::Result<()> + Send + Sync>) {
+                       f: Box<dyn FnMut() -> io::Result<()> + Send + Sync>) {
         self.closures.push(f);
     }
 
@@ -178,6 +184,10 @@ impl Command {
         let maybe_env = self.env.capture_if_changed();
         maybe_env.map(|env| construct_envp(env, &mut self.saw_nul))
     }
+    #[allow(dead_code)]
+    pub fn env_saw_path(&self) -> bool {
+        self.env.have_changed_path()
+    }
 
     pub fn setup_io(&self, default: Stdio, needs_stdin: bool)
                 -> io::Result<(StdioPipes, ChildPipes)> {
@@ -387,6 +397,19 @@ impl fmt::Display for ExitStatus {
     }
 }
 
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct ExitCode(u8);
+
+impl ExitCode {
+    pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _);
+    pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _);
+
+    #[inline]
+    pub fn as_i32(&self) -> i32 {
+        self.0 as i32
+    }
+}
+
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use super::*;
diff --git a/src/libstd/sys/unix/process/process_fuchsia.rs b/src/libstd/sys/unix/process/process_fuchsia.rs
index 06c0540fec0..fa48001179e 100644
--- a/src/libstd/sys/unix/process/process_fuchsia.rs
+++ b/src/libstd/sys/unix/process/process_fuchsia.rs
@@ -56,68 +56,49 @@ impl Command {
                       -> io::Result<zx_handle_t> {
         use sys::process::zircon::*;
 
-        let job_handle = zx_job_default();
         let envp = match maybe_envp {
             Some(envp) => envp.as_ptr(),
             None => ptr::null(),
         };
 
-        // To make sure launchpad_destroy gets called on the launchpad if this function fails
-        struct LaunchpadDestructor(*mut launchpad_t);
-        impl Drop for LaunchpadDestructor {
-            fn drop(&mut self) { unsafe { launchpad_destroy(self.0); } }
-        }
-
-        // Duplicate the job handle
-        let mut job_copy: zx_handle_t = ZX_HANDLE_INVALID;
-        zx_cvt(zx_handle_duplicate(job_handle, ZX_RIGHT_SAME_RIGHTS, &mut job_copy))?;
-        // Create a launchpad
-        let mut launchpad: *mut launchpad_t = ptr::null_mut();
-        zx_cvt(launchpad_create(job_copy, self.get_argv()[0], &mut launchpad))?;
-        let launchpad_destructor = LaunchpadDestructor(launchpad);
-
-        // Set the process argv
-        zx_cvt(launchpad_set_args(launchpad, self.get_argv().len() as i32 - 1,
-                                  self.get_argv().as_ptr()))?;
-        // Setup the environment vars
-        zx_cvt(launchpad_set_environ(launchpad, envp))?;
-        zx_cvt(launchpad_add_vdso_vmo(launchpad))?;
-        // Load the executable
-        zx_cvt(launchpad_elf_load(launchpad, launchpad_vmo_from_file(self.get_argv()[0])))?;
-        zx_cvt(launchpad_load_vdso(launchpad, ZX_HANDLE_INVALID))?;
-        zx_cvt(launchpad_clone(launchpad, LP_CLONE_FDIO_NAMESPACE | LP_CLONE_FDIO_CWD))?;
+        let transfer_or_clone = |opt_fd, target_fd| if let Some(local_fd) = opt_fd {
+            fdio_spawn_action_t {
+                action: FDIO_SPAWN_ACTION_TRANSFER_FD,
+                local_fd,
+                target_fd,
+                ..Default::default()
+            }
+        } else {
+            fdio_spawn_action_t {
+                action: FDIO_SPAWN_ACTION_CLONE_FD,
+                local_fd: target_fd,
+                target_fd,
+                ..Default::default()
+            }
+        };
 
         // Clone stdin, stdout, and stderr
-        if let Some(fd) = stdio.stdin.fd() {
-            zx_cvt(launchpad_transfer_fd(launchpad, fd, 0))?;
-        } else {
-            zx_cvt(launchpad_clone_fd(launchpad, 0, 0))?;
-        }
-        if let Some(fd) = stdio.stdout.fd() {
-            zx_cvt(launchpad_transfer_fd(launchpad, fd, 1))?;
-        } else {
-            zx_cvt(launchpad_clone_fd(launchpad, 1, 1))?;
-        }
-        if let Some(fd) = stdio.stderr.fd() {
-            zx_cvt(launchpad_transfer_fd(launchpad, fd, 2))?;
-        } else {
-            zx_cvt(launchpad_clone_fd(launchpad, 2, 2))?;
-        }
+        let action1 = transfer_or_clone(stdio.stdin.fd(), 0);
+        let action2 = transfer_or_clone(stdio.stdout.fd(), 1);
+        let action3 = transfer_or_clone(stdio.stderr.fd(), 2);
+        let actions = [action1, action2, action3];
 
-        // We don't want FileDesc::drop to be called on any stdio. It would close their fds. The
-        // fds will be closed once the child process finishes.
+        // We don't want FileDesc::drop to be called on any stdio. fdio_spawn_etc
+        // always consumes transferred file descriptors.
         mem::forget(stdio);
 
         for callback in self.get_closures().iter_mut() {
             callback()?;
         }
 
-        // `launchpad_go` destroys the launchpad, so we must not
-        mem::forget(launchpad_destructor);
-
         let mut process_handle: zx_handle_t = 0;
-        let mut err_msg: *const libc::c_char = ptr::null();
-        zx_cvt(launchpad_go(launchpad, &mut process_handle, &mut err_msg))?;
+        zx_cvt(fdio_spawn_etc(
+            0,
+            FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_LDSVC | FDIO_SPAWN_CLONE_NAMESPACE,
+            self.get_argv()[0], self.get_argv().as_ptr(), envp, 3, actions.as_ptr(),
+            &mut process_handle,
+            ptr::null_mut(),
+        ))?;
         // FIXME: See if we want to do something with that err_msg
 
         Ok(process_handle)
diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs
index 189280a4ba9..9d6d607e3f3 100644
--- a/src/libstd/sys/unix/process/process_unix.rs
+++ b/src/libstd/sys/unix/process/process_unix.rs
@@ -34,6 +34,11 @@ impl Command {
         }
 
         let (ours, theirs) = self.setup_io(default, needs_stdin)?;
+
+        if let Some(ret) = self.posix_spawn(&theirs, envp.as_ref())? {
+            return Ok((ret, ours))
+        }
+
         let (input, output) = sys::pipe::anon_pipe()?;
 
         let pid = unsafe {
@@ -229,6 +234,119 @@ impl Command {
         libc::execvp(self.get_argv()[0], self.get_argv().as_ptr());
         io::Error::last_os_error()
     }
+
+    #[cfg(not(any(target_os = "macos", target_os = "freebsd",
+                  all(target_os = "linux", target_env = "gnu"))))]
+    fn posix_spawn(&mut self, _: &ChildPipes, _: Option<&CStringArray>)
+        -> io::Result<Option<Process>>
+    {
+        Ok(None)
+    }
+
+    // Only support platforms for which posix_spawn() can return ENOENT
+    // directly.
+    #[cfg(any(target_os = "macos", target_os = "freebsd",
+              all(target_os = "linux", target_env = "gnu")))]
+    fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>)
+        -> io::Result<Option<Process>>
+    {
+        use mem;
+        use sys;
+
+        if self.get_cwd().is_some() ||
+            self.get_gid().is_some() ||
+            self.get_uid().is_some() ||
+            self.env_saw_path() ||
+            self.get_closures().len() != 0 {
+            return Ok(None)
+        }
+
+        // Only glibc 2.24+ posix_spawn() supports returning ENOENT directly.
+        #[cfg(all(target_os = "linux", target_env = "gnu"))]
+        {
+            if let Some(version) = sys::os::glibc_version() {
+                if version < (2, 24) {
+                    return Ok(None)
+                }
+            } else {
+                return Ok(None)
+            }
+        }
+
+        let mut p = Process { pid: 0, status: None };
+
+        struct PosixSpawnFileActions(libc::posix_spawn_file_actions_t);
+
+        impl Drop for PosixSpawnFileActions {
+            fn drop(&mut self) {
+                unsafe {
+                    libc::posix_spawn_file_actions_destroy(&mut self.0);
+                }
+            }
+        }
+
+        struct PosixSpawnattr(libc::posix_spawnattr_t);
+
+        impl Drop for PosixSpawnattr {
+            fn drop(&mut self) {
+                unsafe {
+                    libc::posix_spawnattr_destroy(&mut self.0);
+                }
+            }
+        }
+
+        unsafe {
+            let mut file_actions = PosixSpawnFileActions(mem::uninitialized());
+            let mut attrs = PosixSpawnattr(mem::uninitialized());
+
+            libc::posix_spawnattr_init(&mut attrs.0);
+            libc::posix_spawn_file_actions_init(&mut file_actions.0);
+
+            if let Some(fd) = stdio.stdin.fd() {
+                cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0,
+                                                           fd,
+                                                           libc::STDIN_FILENO))?;
+            }
+            if let Some(fd) = stdio.stdout.fd() {
+                cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0,
+                                                           fd,
+                                                           libc::STDOUT_FILENO))?;
+            }
+            if let Some(fd) = stdio.stderr.fd() {
+                cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0,
+                                                           fd,
+                                                           libc::STDERR_FILENO))?;
+            }
+
+            let mut set: libc::sigset_t = mem::uninitialized();
+            cvt(libc::sigemptyset(&mut set))?;
+            cvt(libc::posix_spawnattr_setsigmask(&mut attrs.0,
+                                                 &set))?;
+            cvt(libc::sigaddset(&mut set, libc::SIGPIPE))?;
+            cvt(libc::posix_spawnattr_setsigdefault(&mut attrs.0,
+                                                    &set))?;
+
+            let flags = libc::POSIX_SPAWN_SETSIGDEF |
+                libc::POSIX_SPAWN_SETSIGMASK;
+            cvt(libc::posix_spawnattr_setflags(&mut attrs.0, flags as _))?;
+
+            let envp = envp.map(|c| c.as_ptr())
+                .unwrap_or(*sys::os::environ() as *const _);
+            let ret = libc::posix_spawnp(
+                &mut p.pid,
+                self.get_argv()[0],
+                &file_actions.0,
+                &attrs.0,
+                self.get_argv().as_ptr() as *const _,
+                envp as *const _,
+            );
+            if ret == 0 {
+                Ok(Some(p))
+            } else {
+                Err(io::Error::from_raw_os_error(ret))
+            }
+        }
+    }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libstd/sys/unix/process/zircon.rs b/src/libstd/sys/unix/process/zircon.rs
index 90864e6ef3f..a06c73ee263 100644
--- a/src/libstd/sys/unix/process/zircon.rs
+++ b/src/libstd/sys/unix/process/zircon.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(non_camel_case_types)]
+#![allow(non_camel_case_types, unused)]
 
 use convert::TryInto;
 use io;
@@ -117,75 +117,36 @@ extern {
                               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
-// HND_SEGMENTS_VMAR = 2
-const HND_SPECIAL_COUNT: c_int = 3;
-
+#[derive(Default)]
 #[repr(C)]
-pub struct launchpad_t {
-    argc: u32,
-    envc: u32,
-    args: *const c_char,
-    args_len: size_t,
-    env: *const c_char,
-    env_len: size_t,
-
-    handles: *mut zx_handle_t,
-    handles_info: *mut u32,
-    handle_count: size_t,
-    handle_alloc: size_t,
-
-    entry: zx_vaddr_t,
-    base: zx_vaddr_t,
-    vdso_base: zx_vaddr_t,
-
-    stack_size: size_t,
-
-    special_handles: [zx_handle_t; HND_SPECIAL_COUNT as usize],
-    loader_message: bool,
+pub struct fdio_spawn_action_t {
+    pub action: u32,
+    pub reserved0: u32,
+    pub local_fd: i32,
+    pub target_fd: i32,
+    pub reserved1: u64,
 }
 
 extern {
-    pub fn launchpad_create(job: zx_handle_t, name: *const c_char,
-                            lp: *mut *mut launchpad_t) -> zx_status_t;
-
-    pub fn launchpad_go(lp: *mut launchpad_t,
-                        proc_handle: *mut zx_handle_t,
-                        err_msg: *mut *const c_char) -> zx_status_t;
-
-    pub fn launchpad_destroy(lp: *mut launchpad_t);
-
-    pub fn launchpad_set_args(lp: *mut launchpad_t, argc: c_int,
-                               argv: *const *const c_char) -> zx_status_t;
-
-    pub fn launchpad_set_environ(lp: *mut launchpad_t, envp: *const *const c_char) -> zx_status_t;
-
-    pub fn launchpad_clone(lp: *mut launchpad_t, what: u32) -> zx_status_t;
-
-    pub fn launchpad_clone_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> zx_status_t;
-
-    pub fn launchpad_transfer_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> zx_status_t;
-
-    pub fn launchpad_elf_load(lp: *mut launchpad_t, vmo: zx_handle_t) -> zx_status_t;
-
-    pub fn launchpad_add_vdso_vmo(lp: *mut launchpad_t) -> zx_status_t;
+    pub fn fdio_spawn_etc(job: zx_handle_t, flags: u32, path: *const c_char,
+                          argv: *const *const c_char, envp: *const *const c_char,
+                          action_count: u64, actions: *const fdio_spawn_action_t,
+                          process: *mut zx_handle_t, err_msg: *mut c_char) -> zx_status_t;
+}
 
-    pub fn launchpad_load_vdso(lp: *mut launchpad_t, vmo: zx_handle_t) -> zx_status_t;
+// fdio_spawn_etc flags
 
-    pub fn launchpad_vmo_from_file(filename: *const c_char) -> zx_handle_t;
-}
+pub const FDIO_SPAWN_CLONE_JOB: u32 = 0x0001;
+pub const FDIO_SPAWN_CLONE_LDSVC: u32 = 0x0002;
+pub const FDIO_SPAWN_CLONE_NAMESPACE: u32 = 0x0004;
+pub const FDIO_SPAWN_CLONE_STDIO: u32 = 0x0008;
+pub const FDIO_SPAWN_CLONE_ENVIRON: u32 = 0x0010;
+pub const FDIO_SPAWN_CLONE_ALL: u32 = 0xFFFF;
 
-// Launchpad clone constants
+// fdio_spawn_etc actions
 
-pub const LP_CLONE_FDIO_NAMESPACE: u32 = 0x0001;
-pub const LP_CLONE_FDIO_CWD: u32 = 0x0002;
-// LP_CLONE_FDIO_STDIO = 0x0004
-// LP_CLONE_FDIO_ALL = 0x00FF
-// LP_CLONE_ENVIRON = 0x0100
-// LP_CLONE_DEFAULT_JOB = 0x0200
-// LP_CLONE_ALL = 0xFFFF
+pub const FDIO_SPAWN_ACTION_CLONE_FD: u32 = 0x0001;
+pub const FDIO_SPAWN_ACTION_TRANSFER_FD: u32 = 0x0002;
 
 // Errors
 
diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs
index caa18945765..01c0ada4ffb 100644
--- a/src/libstd/sys/unix/rand.rs
+++ b/src/libstd/sys/unix/rand.rs
@@ -183,35 +183,10 @@ mod imp {
 mod imp {
     #[link(name = "zircon")]
     extern {
-        fn zx_cprng_draw(buffer: *mut u8, len: usize, actual: *mut usize) -> i32;
-    }
-
-    fn getrandom(buf: &mut [u8]) -> Result<usize, i32> {
-        unsafe {
-            let mut actual = 0;
-            let status = zx_cprng_draw(buf.as_mut_ptr(), buf.len(), &mut actual);
-            if status == 0 {
-                Ok(actual)
-            } else {
-                Err(status)
-            }
-        }
+        fn zx_cprng_draw(buffer: *mut u8, len: 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)..];
-                }
-            }
-        }
+        unsafe { zx_cprng_draw(v.as_mut_ptr(), v.len()) }
     }
 }
diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs
index 51adbc24ae0..40453f9b8a1 100644
--- a/src/libstd/sys/unix/stack_overflow.rs
+++ b/src/libstd/sys/unix/stack_overflow.rs
@@ -57,9 +57,6 @@ mod imp {
     use sys_common::thread_info;
 
 
-    // This is initialized in init() and only read from after
-    static mut PAGE_SIZE: usize = 0;
-
     #[cfg(any(target_os = "linux", target_os = "android"))]
     unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize {
         #[repr(C)]
@@ -102,12 +99,12 @@ mod imp {
                                     _data: *mut libc::c_void) {
         use sys_common::util::report_overflow;
 
-        let guard = thread_info::stack_guard().unwrap_or(0);
+        let guard = thread_info::stack_guard().unwrap_or(0..0);
         let addr = siginfo_si_addr(info);
 
         // If the faulting address is within the guard page, then we print a
         // message saying so and abort.
-        if guard != 0 && guard - PAGE_SIZE <= addr && addr < guard {
+        if guard.start <= addr && addr < guard.end {
             report_overflow();
             rtabort!("stack overflow");
         } else {
@@ -123,8 +120,6 @@ mod imp {
     static mut MAIN_ALTSTACK: *mut libc::c_void = ptr::null_mut();
 
     pub unsafe fn init() {
-        PAGE_SIZE = ::sys::os::page_size();
-
         let mut action: sigaction = mem::zeroed();
         action.sa_flags = SA_SIGINFO | SA_ONSTACK;
         action.sa_sigaction = signal_handler as sighandler_t;
diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs
index e9b3d4affc7..87ba2aef4f1 100644
--- a/src/libstd/sys/unix/stdio.rs
+++ b/src/libstd/sys/unix/stdio.rs
@@ -75,3 +75,7 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 }
 
 pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
+
+pub fn stderr_prints_nothing() -> bool {
+    false
+}
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index cb249af4254..f3a45d24657 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use alloc::boxed::FnBox;
+use boxed::FnBox;
 use cmp;
 use ffi::CStr;
 use io;
@@ -49,7 +49,7 @@ unsafe fn pthread_attr_setstacksize(_attr: *mut libc::pthread_attr_t,
 }
 
 impl Thread {
-    pub unsafe fn new<'a>(stack: usize, p: Box<FnBox() + 'a>)
+    pub unsafe fn new<'a>(stack: usize, p: Box<dyn FnBox() + 'a>)
                           -> io::Result<Thread> {
         let p = box p;
         let mut native: libc::pthread_t = mem::zeroed();
@@ -138,7 +138,8 @@ impl Thread {
               target_os = "solaris",
               target_os = "haiku",
               target_os = "l4re",
-              target_os = "emscripten"))]
+              target_os = "emscripten",
+              target_os = "hermit"))]
     pub fn set_name(_name: &CStr) {
         // Newlib, Illumos, Haiku, and Emscripten have no way to set a thread name.
     }
@@ -205,8 +206,11 @@ impl Drop for Thread {
           not(target_os = "solaris")))]
 #[cfg_attr(test, allow(dead_code))]
 pub mod guard {
-    pub unsafe fn current() -> Option<usize> { None }
-    pub unsafe fn init() -> Option<usize> { None }
+    use ops::Range;
+    pub type Guard = Range<usize>;
+    pub unsafe fn current() -> Option<Guard> { None }
+    pub unsafe fn init() -> Option<Guard> { None }
+    pub unsafe fn deinit() {}
 }
 
 
@@ -220,16 +224,45 @@ pub mod guard {
 #[cfg_attr(test, allow(dead_code))]
 pub mod guard {
     use libc;
-    use libc::mmap;
-    use libc::{PROT_NONE, MAP_PRIVATE, MAP_ANON, MAP_FAILED, MAP_FIXED};
+    use libc::{mmap, mprotect};
+    use libc::{PROT_NONE, PROT_READ, PROT_WRITE, MAP_PRIVATE, MAP_ANON, MAP_FAILED, MAP_FIXED};
+    use ops::Range;
     use sys::os;
 
-    #[cfg(any(target_os = "macos",
-              target_os = "bitrig",
-              target_os = "openbsd",
-              target_os = "solaris"))]
+    // This is initialized in init() and only read from after
+    static mut PAGE_SIZE: usize = 0;
+
+    pub type Guard = Range<usize>;
+
+    #[cfg(target_os = "solaris")]
+    unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
+        let mut current_stack: libc::stack_t = ::mem::zeroed();
+        assert_eq!(libc::stack_getbounds(&mut current_stack), 0);
+        Some(current_stack.ss_sp)
+    }
+
+    #[cfg(target_os = "macos")]
+    unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
+        let stackaddr = libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize -
+             libc::pthread_get_stacksize_np(libc::pthread_self());
+        Some(stackaddr as *mut libc::c_void)
+    }
+
+    #[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
     unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
-        current().map(|s| s as *mut libc::c_void)
+        let mut current_stack: libc::stack_t = ::mem::zeroed();
+        assert_eq!(libc::pthread_stackseg_np(libc::pthread_self(),
+                                             &mut current_stack), 0);
+
+        let extra = if cfg!(target_os = "bitrig") {3} else {1} * PAGE_SIZE;
+        let stackaddr = if libc::pthread_main_np() == 1 {
+            // main thread
+            current_stack.ss_sp as usize - current_stack.ss_size + extra
+        } else {
+            // new thread
+            current_stack.ss_sp as usize - current_stack.ss_size
+        };
+        Some(stackaddr as *mut libc::c_void)
     }
 
     #[cfg(any(target_os = "android", target_os = "freebsd",
@@ -253,9 +286,10 @@ pub mod guard {
         ret
     }
 
-    pub unsafe fn init() -> Option<usize> {
-        let psize = os::page_size();
-        let mut stackaddr = get_stack_start()?;
+    // Precondition: PAGE_SIZE is initialized.
+    unsafe fn get_stack_start_aligned() -> Option<*mut libc::c_void> {
+        assert!(PAGE_SIZE != 0);
+        let stackaddr = get_stack_start()?;
 
         // Ensure stackaddr is page aligned! A parent process might
         // have reset RLIMIT_STACK to be non-page aligned. The
@@ -263,11 +297,18 @@ pub mod guard {
         // stackaddr < stackaddr + stacksize, so if stackaddr is not
         // page-aligned, calculate the fix such that stackaddr <
         // new_page_aligned_stackaddr < stackaddr + stacksize
-        let remainder = (stackaddr as usize) % psize;
-        if remainder != 0 {
-            stackaddr = ((stackaddr as usize) + psize - remainder)
-                as *mut libc::c_void;
-        }
+        let remainder = (stackaddr as usize) % PAGE_SIZE;
+        Some(if remainder == 0 {
+            stackaddr
+        } else {
+            ((stackaddr as usize) + PAGE_SIZE - remainder) as *mut libc::c_void
+        })
+    }
+
+    pub unsafe fn init() -> Option<Guard> {
+        PAGE_SIZE = os::page_size();
+
+        let stackaddr = get_stack_start_aligned()?;
 
         if cfg!(target_os = "linux") {
             // Linux doesn't allocate the whole stack right away, and
@@ -280,60 +321,71 @@ pub mod guard {
             // Instead, we'll just note where we expect rlimit to start
             // faulting, so our handler can report "stack overflow", and
             // trust that the kernel's own stack guard will work.
-            Some(stackaddr as usize)
+            let stackaddr = stackaddr as usize;
+            Some(stackaddr - PAGE_SIZE..stackaddr)
         } else {
             // Reallocate the last page of the stack.
             // This ensures SIGBUS will be raised on
             // stack overflow.
-            let result = mmap(stackaddr, psize, PROT_NONE,
+            // Systems which enforce strict PAX MPROTECT do not allow
+            // to mprotect() a mapping with less restrictive permissions
+            // than the initial mmap() used, so we mmap() here with
+            // read/write permissions and only then mprotect() it to
+            // no permissions at all. See issue #50313.
+            let result = mmap(stackaddr, PAGE_SIZE, PROT_READ | PROT_WRITE,
                               MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
-
             if result != stackaddr || result == MAP_FAILED {
                 panic!("failed to allocate a guard page");
             }
 
+            let result = mprotect(stackaddr, PAGE_SIZE, PROT_NONE);
+            if result != 0 {
+                panic!("failed to protect the guard page");
+            }
+
+            let guardaddr = stackaddr as usize;
             let offset = if cfg!(target_os = "freebsd") {
                 2
             } else {
                 1
             };
 
-            Some(stackaddr as usize + offset * psize)
+            Some(guardaddr..guardaddr + offset * PAGE_SIZE)
         }
     }
 
-    #[cfg(target_os = "solaris")]
-    pub unsafe fn current() -> Option<usize> {
-        let mut current_stack: libc::stack_t = ::mem::zeroed();
-        assert_eq!(libc::stack_getbounds(&mut current_stack), 0);
-        Some(current_stack.ss_sp as usize)
-    }
-
-    #[cfg(target_os = "macos")]
-    pub unsafe fn current() -> Option<usize> {
-        Some((libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize -
-              libc::pthread_get_stacksize_np(libc::pthread_self())))
+    pub unsafe fn deinit() {
+        if !cfg!(target_os = "linux") {
+            if let Some(stackaddr) = get_stack_start_aligned() {
+                // Remove the protection on the guard page.
+                // FIXME: we cannot unmap the page, because when we mmap()
+                // above it may be already mapped by the OS, which we can't
+                // detect from mmap()'s return value. If we unmap this page,
+                // it will lead to failure growing stack size on platforms like
+                // macOS. Instead, just restore the page to a writable state.
+                // This ain't Linux, so we probably don't need to care about
+                // execstack.
+                let result = mprotect(stackaddr, PAGE_SIZE, PROT_READ | PROT_WRITE);
+
+                if result != 0 {
+                    panic!("unable to reset the guard page");
+                }
+            }
+        }
     }
 
-    #[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
-    pub unsafe fn current() -> Option<usize> {
-        let mut current_stack: libc::stack_t = ::mem::zeroed();
-        assert_eq!(libc::pthread_stackseg_np(libc::pthread_self(),
-                                             &mut current_stack), 0);
-
-        let extra = if cfg!(target_os = "bitrig") {3} else {1} * os::page_size();
-        Some(if libc::pthread_main_np() == 1 {
-            // main thread
-            current_stack.ss_sp as usize - current_stack.ss_size + extra
-        } else {
-            // new thread
-            current_stack.ss_sp as usize - current_stack.ss_size
-        })
+    #[cfg(any(target_os = "macos",
+              target_os = "bitrig",
+              target_os = "openbsd",
+              target_os = "solaris"))]
+    pub unsafe fn current() -> Option<Guard> {
+        let stackaddr = get_stack_start()? as usize;
+        Some(stackaddr - PAGE_SIZE..stackaddr)
     }
 
     #[cfg(any(target_os = "android", target_os = "freebsd",
               target_os = "linux", target_os = "netbsd", target_os = "l4re"))]
-    pub unsafe fn current() -> Option<usize> {
+    pub unsafe fn current() -> Option<Guard> {
         let mut ret = None;
         let mut attr: libc::pthread_attr_t = ::mem::zeroed();
         assert_eq!(libc::pthread_attr_init(&mut attr), 0);
@@ -352,12 +404,23 @@ pub mod guard {
             assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr,
                                                    &mut size), 0);
 
+            let stackaddr = stackaddr as usize;
             ret = if cfg!(target_os = "freebsd") {
-                Some(stackaddr as usize - guardsize)
+                // FIXME does freebsd really fault *below* the guard addr?
+                let guardaddr = stackaddr - guardsize;
+                Some(guardaddr - PAGE_SIZE..guardaddr)
             } else if cfg!(target_os = "netbsd") {
-                Some(stackaddr as usize)
+                Some(stackaddr - guardsize..stackaddr)
+            } else if cfg!(all(target_os = "linux", target_env = "gnu")) {
+                // glibc used to include the guard area within the stack, as noted in the BUGS
+                // section of `man pthread_attr_getguardsize`.  This has been corrected starting
+                // with glibc 2.27, and in some distro backports, so the guard is now placed at the
+                // end (below) the stack.  There's no easy way for us to know which we have at
+                // runtime, so we'll just match any fault in the range right above or below the
+                // stack base to call that fault a stack overflow.
+                Some(stackaddr - guardsize..stackaddr + guardsize)
             } else {
-                Some(stackaddr as usize + guardsize)
+                Some(stackaddr..stackaddr + guardsize)
             };
         }
         assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs
index 83127935909..0b1fb726357 100644
--- a/src/libstd/sys/unix/time.rs
+++ b/src/libstd/sys/unix/time.rs
@@ -289,7 +289,7 @@ mod inner {
 
         pub fn sub_instant(&self, other: &Instant) -> Duration {
             self.t.sub_timespec(&other.t).unwrap_or_else(|_| {
-                panic!("other was less than the current instant")
+                panic!("specified instant was later than self")
             })
         }
 
@@ -345,9 +345,9 @@ mod inner {
         }
     }
 
-    #[cfg(not(target_os = "dragonfly"))]
+    #[cfg(not(any(target_os = "dragonfly", target_os = "hermit")))]
     pub type clock_t = libc::c_int;
-    #[cfg(target_os = "dragonfly")]
+    #[cfg(any(target_os = "dragonfly", target_os = "hermit"))]
     pub type clock_t = libc::c_ulong;
 
     fn now(clock: clock_t) -> Timespec {
diff --git a/src/libstd/sys/wasm/args.rs b/src/libstd/sys/wasm/args.rs
index d2a4a7b19d5..b3c6b671e80 100644
--- a/src/libstd/sys/wasm/args.rs
+++ b/src/libstd/sys/wasm/args.rs
@@ -10,8 +10,8 @@
 
 use ffi::OsString;
 use marker::PhantomData;
-use mem;
 use vec;
+use sys::ArgsSysCall;
 
 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
@@ -21,38 +21,10 @@ 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,
-        }
+    let v = ArgsSysCall::perform();
+    Args {
+        iter: v.into_iter(),
+        _dont_send_or_sync_me: PhantomData,
     }
 }
 
diff --git a/src/libstd/sys/wasm/mod.rs b/src/libstd/sys/wasm/mod.rs
index ba3d6a2813a..c02e5e809c8 100644
--- a/src/libstd/sys/wasm/mod.rs
+++ b/src/libstd/sys/wasm/mod.rs
@@ -26,17 +26,11 @@
 
 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;
+use ptr;
+use sys::os_str::Buf;
+use sys_common::{AsInner, FromInner};
+use ffi::{OsString, OsStr};
+use time::Duration;
 
 pub mod args;
 #[cfg(feature = "backtrace")]
@@ -92,7 +86,7 @@ pub unsafe fn strlen(mut s: *const c_char) -> usize {
 }
 
 pub unsafe fn abort_internal() -> ! {
-    ::intrinsics::abort();
+    ExitSysCall::perform(1)
 }
 
 // We don't have randomness yet, but I totally used a random number generator to
@@ -103,3 +97,218 @@ pub unsafe fn abort_internal() -> ! {
 pub fn hashmap_random_keys() -> (u64, u64) {
     (1, 2)
 }
+
+// Implement a minimal set of system calls to enable basic IO
+pub enum SysCallIndex {
+    Read = 0,
+    Write = 1,
+    Exit = 2,
+    Args = 3,
+    GetEnv = 4,
+    SetEnv = 5,
+    Time = 6,
+}
+
+#[repr(C)]
+pub struct ReadSysCall {
+    fd: usize,
+    ptr: *mut u8,
+    len: usize,
+    result: usize,
+}
+
+impl ReadSysCall {
+    pub fn perform(fd: usize, buffer: &mut [u8]) -> usize {
+        let mut call_record = ReadSysCall {
+            fd,
+            len: buffer.len(),
+            ptr: buffer.as_mut_ptr(),
+            result: 0
+        };
+        if unsafe { syscall(SysCallIndex::Read, &mut call_record) } {
+            call_record.result
+        } else {
+            0
+        }
+    }
+}
+
+#[repr(C)]
+pub struct WriteSysCall {
+    fd: usize,
+    ptr: *const u8,
+    len: usize,
+}
+
+impl WriteSysCall {
+    pub fn perform(fd: usize, buffer: &[u8]) {
+        let mut call_record = WriteSysCall {
+            fd,
+            len: buffer.len(),
+            ptr: buffer.as_ptr()
+        };
+        unsafe { syscall(SysCallIndex::Write, &mut call_record); }
+    }
+}
+
+#[repr(C)]
+pub struct ExitSysCall {
+    code: usize,
+}
+
+impl ExitSysCall {
+    pub fn perform(code: usize) -> ! {
+        let mut call_record = ExitSysCall {
+            code
+        };
+        unsafe {
+            syscall(SysCallIndex::Exit, &mut call_record);
+            ::intrinsics::abort();
+        }
+    }
+}
+
+fn receive_buffer<E, F: FnMut(&mut [u8]) -> Result<usize, E>>(estimate: usize, mut f: F)
+    -> Result<Vec<u8>, E>
+{
+    let mut buffer = vec![0; estimate];
+    loop {
+        let result = f(&mut buffer)?;
+        if result <= buffer.len() {
+            buffer.truncate(result);
+            break;
+        }
+        buffer.resize(result, 0);
+    }
+    Ok(buffer)
+}
+
+#[repr(C)]
+pub struct ArgsSysCall {
+    ptr: *mut u8,
+    len: usize,
+    result: usize
+}
+
+impl ArgsSysCall {
+    pub fn perform() -> Vec<OsString> {
+        receive_buffer(1024, |buffer| -> Result<usize, !> {
+            let mut call_record = ArgsSysCall {
+                len: buffer.len(),
+                ptr: buffer.as_mut_ptr(),
+                result: 0
+            };
+            if unsafe { syscall(SysCallIndex::Args, &mut call_record) } {
+                Ok(call_record.result)
+            } else {
+                Ok(0)
+            }
+        })
+            .unwrap()
+            .split(|b| *b == 0)
+            .map(|s| FromInner::from_inner(Buf { inner: s.to_owned() }))
+            .collect()
+    }
+}
+
+#[repr(C)]
+pub struct GetEnvSysCall {
+    key_ptr: *const u8,
+    key_len: usize,
+    value_ptr: *mut u8,
+    value_len: usize,
+    result: usize
+}
+
+impl GetEnvSysCall {
+    pub fn perform(key: &OsStr) -> Option<OsString> {
+        let key_buf = &AsInner::as_inner(key).inner;
+        receive_buffer(64, |buffer| {
+            let mut call_record = GetEnvSysCall {
+                key_len: key_buf.len(),
+                key_ptr: key_buf.as_ptr(),
+                value_len: buffer.len(),
+                value_ptr: buffer.as_mut_ptr(),
+                result: !0usize
+            };
+            if unsafe { syscall(SysCallIndex::GetEnv, &mut call_record) } {
+                if call_record.result == !0usize {
+                    Err(())
+                } else {
+                    Ok(call_record.result)
+                }
+            } else {
+                Err(())
+            }
+        }).ok().map(|s| {
+            FromInner::from_inner(Buf { inner: s })
+        })
+    }
+}
+
+#[repr(C)]
+pub struct SetEnvSysCall {
+    key_ptr: *const u8,
+    key_len: usize,
+    value_ptr: *const u8,
+    value_len: usize
+}
+
+impl SetEnvSysCall {
+    pub fn perform(key: &OsStr, value: Option<&OsStr>) {
+        let key_buf = &AsInner::as_inner(key).inner;
+        let value_buf = value.map(|v| &AsInner::as_inner(v).inner);
+        let mut call_record = SetEnvSysCall {
+            key_len: key_buf.len(),
+            key_ptr: key_buf.as_ptr(),
+            value_len: value_buf.map(|v| v.len()).unwrap_or(!0usize),
+            value_ptr: value_buf.map(|v| v.as_ptr()).unwrap_or(ptr::null())
+        };
+        unsafe { syscall(SysCallIndex::SetEnv, &mut call_record); }
+    }
+}
+
+pub enum TimeClock {
+    Monotonic = 0,
+    System = 1,
+}
+
+#[repr(C)]
+pub struct TimeSysCall {
+    clock: usize,
+    secs_hi: usize,
+    secs_lo: usize,
+    nanos: usize
+}
+
+impl TimeSysCall {
+    pub fn perform(clock: TimeClock) -> Duration {
+        let mut call_record = TimeSysCall {
+            clock: clock as usize,
+            secs_hi: 0,
+            secs_lo: 0,
+            nanos: 0
+        };
+        if unsafe { syscall(SysCallIndex::Time, &mut call_record) } {
+            Duration::new(
+                ((call_record.secs_hi as u64) << 32) | (call_record.secs_lo as u64),
+                call_record.nanos as u32
+            )
+        } else {
+            panic!("Time system call is not implemented by WebAssembly host");
+        }
+    }
+}
+
+unsafe fn syscall<T>(index: SysCallIndex, data: &mut T) -> bool {
+    #[cfg(feature = "wasm_syscall")]
+    extern {
+        #[no_mangle]
+        fn rust_wasm_syscall(index: usize, data: *mut Void) -> usize;
+    }
+
+    #[cfg(not(feature = "wasm_syscall"))]
+    unsafe fn rust_wasm_syscall(_index: usize, _data: *mut Void) -> usize { 0 }
+
+    rust_wasm_syscall(index as usize, data as *mut T as *mut Void) != 0
+}
diff --git a/src/libstd/sys/wasm/os.rs b/src/libstd/sys/wasm/os.rs
index c98030f7ebf..0cb991e19b0 100644
--- a/src/libstd/sys/wasm/os.rs
+++ b/src/libstd/sys/wasm/os.rs
@@ -8,23 +8,20 @@
 // 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};
+use sys::{unsupported, Void, ExitSysCall, GetEnvSysCall, SetEnvSysCall};
 
 pub fn errno() -> i32 {
     0
 }
 
 pub fn error_string(_errno: i32) -> String {
-    format!("operation successful")
+    "operation successful".to_string()
 }
 
 pub fn getcwd() -> io::Result<PathBuf> {
@@ -87,36 +84,15 @@ pub fn env() -> Env {
 }
 
 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)))
-    }
+    Ok(GetEnvSysCall::perform(k))
 }
 
-pub fn setenv(_k: &OsStr, _v: &OsStr) -> io::Result<()> {
-    unsupported()
+pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
+    Ok(SetEnvSysCall::perform(k, Some(v)))
 }
 
-pub fn unsetenv(_n: &OsStr) -> io::Result<()> {
-    unsupported()
+pub fn unsetenv(k: &OsStr) -> io::Result<()> {
+    Ok(SetEnvSysCall::perform(k, None))
 }
 
 pub fn temp_dir() -> PathBuf {
@@ -128,7 +104,7 @@ pub fn home_dir() -> Option<PathBuf> {
 }
 
 pub fn exit(_code: i32) -> ! {
-    unsafe { intrinsics::abort() }
+    ExitSysCall::perform(_code as isize as usize)
 }
 
 pub fn getpid() -> u32 {
diff --git a/src/libstd/sys/wasm/os_str.rs b/src/libstd/sys/wasm/os_str.rs
index 543c22ebe18..e0da5bdf36c 100644
--- a/src/libstd/sys/wasm/os_str.rs
+++ b/src/libstd/sys/wasm/os_str.rs
@@ -19,7 +19,7 @@ use rc::Rc;
 use sync::Arc;
 use sys_common::{AsInner, IntoInner};
 use sys_common::bytestring::debug_fmt_bytestring;
-use std_unicode::lossy::Utf8Lossy;
+use core::str::lossy::Utf8Lossy;
 
 #[derive(Clone, Hash)]
 pub struct Buf {
@@ -104,6 +104,11 @@ impl Buf {
         self.inner.shrink_to_fit()
     }
 
+    #[inline]
+    pub fn shrink_to(&mut self, min_capacity: usize) {
+        self.inner.shrink_to(min_capacity)
+    }
+
     pub fn as_slice(&self) -> &Slice {
         unsafe { mem::transmute(&*self.inner) }
     }
diff --git a/src/libstd/sys/wasm/process.rs b/src/libstd/sys/wasm/process.rs
index f3f5de350f1..433e9cec7c8 100644
--- a/src/libstd/sys/wasm/process.rs
+++ b/src/libstd/sys/wasm/process.rs
@@ -129,6 +129,18 @@ impl fmt::Display for ExitStatus {
     }
 }
 
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct ExitCode(bool);
+
+impl ExitCode {
+    pub const SUCCESS: ExitCode = ExitCode(false);
+    pub const FAILURE: ExitCode = ExitCode(true);
+
+    pub fn as_i32(&self) -> i32 {
+        self.0 as i32
+    }
+}
+
 pub struct Process(Void);
 
 impl Process {
diff --git a/src/libstd/sys/wasm/rwlock.rs b/src/libstd/sys/wasm/rwlock.rs
index 8b06f541674..6516010af47 100644
--- a/src/libstd/sys/wasm/rwlock.rs
+++ b/src/libstd/sys/wasm/rwlock.rs
@@ -30,7 +30,7 @@ impl RWLock {
         if *mode >= 0 {
             *mode += 1;
         } else {
-            panic!("rwlock locked for writing");
+            rtabort!("rwlock locked for writing");
         }
     }
 
@@ -51,7 +51,7 @@ impl RWLock {
         if *mode == 0 {
             *mode = -1;
         } else {
-            panic!("rwlock locked for reading")
+            rtabort!("rwlock locked for reading")
         }
     }
 
diff --git a/src/libstd/sys/wasm/stdio.rs b/src/libstd/sys/wasm/stdio.rs
index 0f75f240251..023f29576a2 100644
--- a/src/libstd/sys/wasm/stdio.rs
+++ b/src/libstd/sys/wasm/stdio.rs
@@ -9,19 +9,19 @@
 // except according to those terms.
 
 use io;
-use sys::{Void, unsupported};
+use sys::{ReadSysCall, WriteSysCall};
 
-pub struct Stdin(Void);
+pub struct Stdin;
 pub struct Stdout;
 pub struct Stderr;
 
 impl Stdin {
     pub fn new() -> io::Result<Stdin> {
-        unsupported()
+        Ok(Stdin)
     }
 
-    pub fn read(&self, _data: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
+    pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
+        Ok(ReadSysCall::perform(0, data))
     }
 }
 
@@ -31,19 +31,7 @@ impl 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())
-        }
+        WriteSysCall::perform(1, data);
         Ok(data.len())
     }
 
@@ -58,16 +46,7 @@ impl 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())
-        }
+        WriteSysCall::perform(2, data);
         Ok(data.len())
     }
 
@@ -90,3 +69,7 @@ pub const STDIN_BUF_SIZE: usize = 0;
 pub fn is_ebadf(_err: &io::Error) -> bool {
     true
 }
+
+pub fn stderr_prints_nothing() -> bool {
+    !cfg!(feature = "wasm_syscall")
+}
diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs
index 13980e0cc19..8173a624211 100644
--- a/src/libstd/sys/wasm/thread.rs
+++ b/src/libstd/sys/wasm/thread.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use alloc::boxed::FnBox;
+use boxed::FnBox;
 use ffi::CStr;
 use io;
 use sys::{unsupported, Void};
@@ -19,7 +19,7 @@ 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>)
+    pub unsafe fn new<'a>(_stack: usize, _p: Box<dyn FnBox() + 'a>)
         -> io::Result<Thread>
     {
         unsupported()
@@ -43,6 +43,8 @@ impl Thread {
 }
 
 pub mod guard {
-    pub unsafe fn current() -> Option<usize> { None }
-    pub unsafe fn init() -> Option<usize> { None }
+    pub type Guard = !;
+    pub unsafe fn current() -> Option<Guard> { None }
+    pub unsafe fn init() -> Option<Guard> { None }
+    pub unsafe fn deinit() {}
 }
diff --git a/src/libstd/sys/wasm/time.rs b/src/libstd/sys/wasm/time.rs
index c269def98f6..e52435e6339 100644
--- a/src/libstd/sys/wasm/time.rs
+++ b/src/libstd/sys/wasm/time.rs
@@ -8,56 +8,50 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use fmt;
 use time::Duration;
+use sys::{TimeSysCall, TimeClock};
 
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
-pub struct Instant;
+pub struct Instant(Duration);
 
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct SystemTime;
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+pub struct SystemTime(Duration);
 
-pub const UNIX_EPOCH: SystemTime = SystemTime;
+pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0));
 
 impl Instant {
     pub fn now() -> Instant {
-        panic!("not supported on web assembly");
+        Instant(TimeSysCall::perform(TimeClock::Monotonic))
     }
 
-    pub fn sub_instant(&self, _other: &Instant) -> Duration {
-        panic!("can't sub yet");
+    pub fn sub_instant(&self, other: &Instant) -> Duration {
+        self.0 - other.0
     }
 
-    pub fn add_duration(&self, _other: &Duration) -> Instant {
-        panic!("can't add yet");
+    pub fn add_duration(&self, other: &Duration) -> Instant {
+        Instant(self.0 + *other)
     }
 
-    pub fn sub_duration(&self, _other: &Duration) -> Instant {
-        panic!("can't sub yet");
+    pub fn sub_duration(&self, other: &Duration) -> Instant {
+        Instant(self.0 - *other)
     }
 }
 
 impl SystemTime {
     pub fn now() -> SystemTime {
-        panic!("not supported on web assembly");
+        SystemTime(TimeSysCall::perform(TimeClock::System))
     }
 
-    pub fn sub_time(&self, _other: &SystemTime)
+    pub fn sub_time(&self, other: &SystemTime)
                     -> Result<Duration, Duration> {
-        panic!()
-    }
-
-    pub fn add_duration(&self, _other: &Duration) -> SystemTime {
-        panic!()
+        self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
     }
 
-    pub fn sub_duration(&self, _other: &Duration) -> SystemTime {
-        panic!()
+    pub fn add_duration(&self, other: &Duration) -> SystemTime {
+        SystemTime(self.0 + *other)
     }
-}
 
-impl fmt::Debug for SystemTime {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
-        panic!()
+    pub fn sub_duration(&self, other: &Duration) -> SystemTime {
+        SystemTime(self.0 - *other)
     }
 }
diff --git a/src/libstd/sys/windows/backtrace/mod.rs b/src/libstd/sys/windows/backtrace/mod.rs
index 176891fff23..f64cae810b9 100644
--- a/src/libstd/sys/windows/backtrace/mod.rs
+++ b/src/libstd/sys/windows/backtrace/mod.rs
@@ -46,111 +46,281 @@ mod printing;
 #[path = "backtrace_gnu.rs"]
 pub mod gnu;
 
-pub use self::printing::{resolve_symname, foreach_symbol_fileline};
+pub use self::printing::{foreach_symbol_fileline, resolve_symname};
+use self::printing::{load_printing_fns_64, load_printing_fns_ex};
 
-pub fn unwind_backtrace(frames: &mut [Frame])
-    -> io::Result<(usize, BacktraceContext)>
-{
+pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> {
     let dbghelp = DynamicLibrary::open("dbghelp.dll")?;
 
     // Fetch the symbols necessary from dbghelp.dll
     let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn)?;
     let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn)?;
-    let StackWalk64 = sym!(dbghelp, "StackWalk64", StackWalk64Fn)?;
+
+    // StackWalkEx might not be present and we'll fall back to StackWalk64
+    let sw_var = match sym!(dbghelp, "StackWalkEx", StackWalkExFn) {
+        Ok(StackWalkEx) => {
+            StackWalkVariant::StackWalkEx(StackWalkEx, load_printing_fns_ex(&dbghelp)?)
+        }
+        Err(e) => match sym!(dbghelp, "StackWalk64", StackWalk64Fn) {
+            Ok(StackWalk64) => {
+                StackWalkVariant::StackWalk64(StackWalk64, load_printing_fns_64(&dbghelp)?)
+            }
+            Err(..) => return Err(e),
+        },
+    };
 
     // Allocate necessary structures for doing the stack walk
     let process = unsafe { c::GetCurrentProcess() };
-    let thread = unsafe { c::GetCurrentThread() };
-    let mut context: c::CONTEXT = unsafe { mem::zeroed() };
-    unsafe { c::RtlCaptureContext(&mut context) };
-    let mut frame: c::STACKFRAME64 = unsafe { mem::zeroed() };
-    let image = init_frame(&mut frame, &context);
 
     let backtrace_context = BacktraceContext {
         handle: process,
         SymCleanup,
+        StackWalkVariant: sw_var,
         dbghelp,
     };
 
     // Initialize this process's symbols
     let ret = unsafe { SymInitialize(process, ptr::null_mut(), c::TRUE) };
     if ret != c::TRUE {
-        return Ok((0, backtrace_context))
+        return Ok((0, backtrace_context));
     }
 
     // And now that we're done with all the setup, do the stack walking!
-    // Start from -1 to avoid printing this stack frame, which will
-    // always be exactly the same.
+    match backtrace_context.StackWalkVariant {
+        StackWalkVariant::StackWalkEx(StackWalkEx, _) => {
+            set_frames(StackWalkEx, frames).map(|i| (i, backtrace_context))
+        }
+
+        StackWalkVariant::StackWalk64(StackWalk64, _) => {
+            set_frames(StackWalk64, frames).map(|i| (i, backtrace_context))
+        }
+    }
+}
+
+fn set_frames<W: StackWalker>(StackWalk: W, frames: &mut [Frame]) -> io::Result<usize> {
+    let process = unsafe { c::GetCurrentProcess() };
+    let thread = unsafe { c::GetCurrentProcess() };
+    let mut context: c::CONTEXT = unsafe { mem::zeroed() };
+    unsafe { c::RtlCaptureContext(&mut context) };
+    let mut frame = W::Item::new();
+    let image = frame.init(&context);
+
     let mut i = 0;
-    unsafe {
-        while i < frames.len() &&
-              StackWalk64(image, process, thread, &mut frame, &mut context,
-                          ptr::null_mut(),
-                          ptr::null_mut(),
-                          ptr::null_mut(),
-                          ptr::null_mut()) == c::TRUE
-        {
-            let addr = frame.AddrPC.Offset;
-            if addr == frame.AddrReturn.Offset || addr == 0 ||
-               frame.AddrReturn.Offset == 0 { break }
-
-            frames[i] = Frame {
-                symbol_addr: (addr - 1) as *const u8,
-                exact_position: (addr - 1) as *const u8,
-            };
-            i += 1;
+    while i < frames.len()
+        && StackWalk.walk(image, process, thread, &mut frame, &mut context) == c::TRUE
+    {
+        let addr = frame.get_addr();
+        frames[i] = Frame {
+            symbol_addr: addr,
+            exact_position: addr,
+            inline_context: 0,
+        };
+
+        i += 1
+    }
+    Ok(i)
+}
+
+type SymInitializeFn = unsafe extern "system" fn(c::HANDLE, *mut c_void, c::BOOL) -> c::BOOL;
+type SymCleanupFn = unsafe extern "system" fn(c::HANDLE) -> c::BOOL;
+
+type StackWalkExFn = unsafe extern "system" fn(
+    c::DWORD,
+    c::HANDLE,
+    c::HANDLE,
+    *mut c::STACKFRAME_EX,
+    *mut c::CONTEXT,
+    *mut c_void,
+    *mut c_void,
+    *mut c_void,
+    *mut c_void,
+    c::DWORD,
+) -> c::BOOL;
+
+type StackWalk64Fn = unsafe extern "system" fn(
+    c::DWORD,
+    c::HANDLE,
+    c::HANDLE,
+    *mut c::STACKFRAME64,
+    *mut c::CONTEXT,
+    *mut c_void,
+    *mut c_void,
+    *mut c_void,
+    *mut c_void,
+) -> c::BOOL;
+
+trait StackWalker {
+    type Item: StackFrame;
+
+    fn walk(&self, c::DWORD, c::HANDLE, c::HANDLE, &mut Self::Item, &mut c::CONTEXT) -> c::BOOL;
+}
+
+impl StackWalker for StackWalkExFn {
+    type Item = c::STACKFRAME_EX;
+    fn walk(
+        &self,
+        image: c::DWORD,
+        process: c::HANDLE,
+        thread: c::HANDLE,
+        frame: &mut Self::Item,
+        context: &mut c::CONTEXT,
+    ) -> c::BOOL {
+        unsafe {
+            self(
+                image,
+                process,
+                thread,
+                frame,
+                context,
+                ptr::null_mut(),
+                ptr::null_mut(),
+                ptr::null_mut(),
+                ptr::null_mut(),
+                0,
+            )
+        }
+    }
+}
+
+impl StackWalker for StackWalk64Fn {
+    type Item = c::STACKFRAME64;
+    fn walk(
+        &self,
+        image: c::DWORD,
+        process: c::HANDLE,
+        thread: c::HANDLE,
+        frame: &mut Self::Item,
+        context: &mut c::CONTEXT,
+    ) -> c::BOOL {
+        unsafe {
+            self(
+                image,
+                process,
+                thread,
+                frame,
+                context,
+                ptr::null_mut(),
+                ptr::null_mut(),
+                ptr::null_mut(),
+                ptr::null_mut(),
+            )
         }
     }
+}
+
+trait StackFrame {
+    fn new() -> Self;
+    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD;
+    fn get_addr(&self) -> *const u8;
+}
+
+impl StackFrame for c::STACKFRAME_EX {
+    fn new() -> c::STACKFRAME_EX {
+        unsafe { mem::zeroed() }
+    }
+
+    #[cfg(target_arch = "x86")]
+    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
+        self.AddrPC.Offset = ctx.Eip as u64;
+        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrStack.Offset = ctx.Esp as u64;
+        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrFrame.Offset = ctx.Ebp as u64;
+        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        c::IMAGE_FILE_MACHINE_I386
+    }
+
+    #[cfg(target_arch = "x86_64")]
+    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
+        self.AddrPC.Offset = ctx.Rip as u64;
+        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrStack.Offset = ctx.Rsp as u64;
+        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrFrame.Offset = ctx.Rbp as u64;
+        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        c::IMAGE_FILE_MACHINE_AMD64
+    }
+
+    #[cfg(target_arch = "aarch64")]
+    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
+        self.AddrPC.Offset = ctx.Pc as u64;
+        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrStack.Offset = ctx.Sp as u64;
+        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrFrame.Offset = ctx.Fp as u64;
+        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        c::IMAGE_FILE_MACHINE_ARM64
+    }
 
-    Ok((i, backtrace_context))
+    fn get_addr(&self) -> *const u8 {
+        (self.AddrPC.Offset - 1) as *const u8
+    }
 }
 
-type SymInitializeFn =
-    unsafe extern "system" fn(c::HANDLE, *mut c_void,
-                              c::BOOL) -> c::BOOL;
-type SymCleanupFn =
-    unsafe extern "system" fn(c::HANDLE) -> c::BOOL;
-
-type StackWalk64Fn =
-    unsafe extern "system" fn(c::DWORD, c::HANDLE, c::HANDLE,
-                              *mut c::STACKFRAME64, *mut c::CONTEXT,
-                              *mut c_void, *mut c_void,
-                              *mut c_void, *mut c_void) -> c::BOOL;
-
-#[cfg(target_arch = "x86")]
-fn init_frame(frame: &mut c::STACKFRAME64,
-              ctx: &c::CONTEXT) -> c::DWORD {
-    frame.AddrPC.Offset = ctx.Eip as u64;
-    frame.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
-    frame.AddrStack.Offset = ctx.Esp as u64;
-    frame.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
-    frame.AddrFrame.Offset = ctx.Ebp as u64;
-    frame.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
-    c::IMAGE_FILE_MACHINE_I386
+impl StackFrame for c::STACKFRAME64 {
+    fn new() -> c::STACKFRAME64 {
+        unsafe { mem::zeroed() }
+    }
+
+    #[cfg(target_arch = "x86")]
+    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
+        self.AddrPC.Offset = ctx.Eip as u64;
+        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrStack.Offset = ctx.Esp as u64;
+        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrFrame.Offset = ctx.Ebp as u64;
+        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        c::IMAGE_FILE_MACHINE_I386
+    }
+
+    #[cfg(target_arch = "x86_64")]
+    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
+        self.AddrPC.Offset = ctx.Rip as u64;
+        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrStack.Offset = ctx.Rsp as u64;
+        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrFrame.Offset = ctx.Rbp as u64;
+        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        c::IMAGE_FILE_MACHINE_AMD64
+    }
+
+    #[cfg(target_arch = "aarch64")]
+    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
+        self.AddrPC.Offset = ctx.Pc as u64;
+        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrStack.Offset = ctx.Sp as u64;
+        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrFrame.Offset = ctx.Fp as u64;
+        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        c::IMAGE_FILE_MACHINE_ARM64
+    }
+
+    fn get_addr(&self) -> *const u8 {
+        (self.AddrPC.Offset - 1) as *const u8
+    }
 }
 
-#[cfg(target_arch = "x86_64")]
-fn init_frame(frame: &mut c::STACKFRAME64,
-              ctx: &c::CONTEXT) -> c::DWORD {
-    frame.AddrPC.Offset = ctx.Rip as u64;
-    frame.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
-    frame.AddrStack.Offset = ctx.Rsp as u64;
-    frame.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
-    frame.AddrFrame.Offset = ctx.Rbp as u64;
-    frame.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
-    c::IMAGE_FILE_MACHINE_AMD64
+enum StackWalkVariant {
+    StackWalkEx(StackWalkExFn, printing::PrintingFnsEx),
+    StackWalk64(StackWalk64Fn, printing::PrintingFns64),
 }
 
 pub struct BacktraceContext {
     handle: c::HANDLE,
     SymCleanup: SymCleanupFn,
     // Only used in printing for msvc and not gnu
+    // The gnu version is effectively a ZST dummy.
+    #[allow(dead_code)]
+    StackWalkVariant: StackWalkVariant,
+    // keeping DynamycLibrary loaded until its functions no longer needed
     #[allow(dead_code)]
     dbghelp: DynamicLibrary,
 }
 
 impl Drop for BacktraceContext {
     fn drop(&mut self) {
-        unsafe { (self.SymCleanup)(self.handle); }
+        unsafe {
+            (self.SymCleanup)(self.handle);
+        }
     }
 }
diff --git a/src/libstd/sys/windows/backtrace/printing/mod.rs b/src/libstd/sys/windows/backtrace/printing/mod.rs
index 3e566f6e2bd..251d5028aea 100644
--- a/src/libstd/sys/windows/backtrace/printing/mod.rs
+++ b/src/libstd/sys/windows/backtrace/printing/mod.rs
@@ -15,6 +15,20 @@ mod printing;
 #[cfg(target_env = "gnu")]
 mod printing {
     pub use sys_common::gnu::libbacktrace::{foreach_symbol_fileline, resolve_symname};
+
+    // dummy functions to mirror those present in msvc version.
+    use sys::dynamic_lib::DynamicLibrary;
+    use io;
+    pub struct PrintingFnsEx {}
+    pub struct PrintingFns64 {}
+    pub fn load_printing_fns_ex(_: &DynamicLibrary) -> io::Result<PrintingFnsEx> {
+        Ok(PrintingFnsEx{})
+    }
+    pub fn load_printing_fns_64(_: &DynamicLibrary) -> io::Result<PrintingFns64> {
+        Ok(PrintingFns64{})
+    }
 }
 
 pub use self::printing::{foreach_symbol_fileline, resolve_symname};
+pub use self::printing::{load_printing_fns_ex, load_printing_fns_64,
+                         PrintingFnsEx, PrintingFns64};
diff --git a/src/libstd/sys/windows/backtrace/printing/msvc.rs b/src/libstd/sys/windows/backtrace/printing/msvc.rs
index 5a49b77af8e..c8b946bf13a 100644
--- a/src/libstd/sys/windows/backtrace/printing/msvc.rs
+++ b/src/libstd/sys/windows/backtrace/printing/msvc.rs
@@ -10,27 +10,108 @@
 
 use ffi::CStr;
 use io;
-use libc::{c_ulong, c_char};
+use libc::{c_char, c_ulong};
 use mem;
-use sys::c;
 use sys::backtrace::BacktraceContext;
+use sys::backtrace::StackWalkVariant;
+use sys::c;
+use sys::dynamic_lib::DynamicLibrary;
 use sys_common::backtrace::Frame;
 
+// Structs holding printing functions and loaders for them
+// Two versions depending on whether dbghelp.dll has StackWalkEx or not
+// (the former being in newer Windows versions, the older being in Win7 and before)
+pub struct PrintingFnsEx {
+    resolve_symname: SymFromInlineContextFn,
+    sym_get_line: SymGetLineFromInlineContextFn,
+}
+pub struct PrintingFns64 {
+    resolve_symname: SymFromAddrFn,
+    sym_get_line: SymGetLineFromAddr64Fn,
+}
+
+pub fn load_printing_fns_ex(dbghelp: &DynamicLibrary) -> io::Result<PrintingFnsEx> {
+    Ok(PrintingFnsEx {
+        resolve_symname: sym!(dbghelp, "SymFromInlineContext", SymFromInlineContextFn)?,
+        sym_get_line: sym!(
+            dbghelp,
+            "SymGetLineFromInlineContext",
+            SymGetLineFromInlineContextFn
+        )?,
+    })
+}
+pub fn load_printing_fns_64(dbghelp: &DynamicLibrary) -> io::Result<PrintingFns64> {
+    Ok(PrintingFns64 {
+        resolve_symname: sym!(dbghelp, "SymFromAddr", SymFromAddrFn)?,
+        sym_get_line: sym!(dbghelp, "SymGetLineFromAddr64", SymGetLineFromAddr64Fn)?,
+    })
+}
+
 type SymFromAddrFn =
-    unsafe extern "system" fn(c::HANDLE, u64, *mut u64,
-                              *mut c::SYMBOL_INFO) -> c::BOOL;
+    unsafe extern "system" fn(c::HANDLE, u64, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL;
+type SymFromInlineContextFn =
+    unsafe extern "system" fn(c::HANDLE, u64, c::ULONG, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL;
+
 type SymGetLineFromAddr64Fn =
-    unsafe extern "system" fn(c::HANDLE, u64, *mut u32,
-                              *mut c::IMAGEHLP_LINE64) -> c::BOOL;
+    unsafe extern "system" fn(c::HANDLE, u64, *mut u32, *mut c::IMAGEHLP_LINE64) -> c::BOOL;
+type SymGetLineFromInlineContextFn = unsafe extern "system" fn(
+    c::HANDLE,
+    u64,
+    c::ULONG,
+    u64,
+    *mut c::DWORD,
+    *mut c::IMAGEHLP_LINE64,
+) -> c::BOOL;
 
 /// Converts a pointer to symbol to its string value.
-pub fn resolve_symname<F>(frame: Frame,
-                          callback: F,
-                          context: &BacktraceContext) -> io::Result<()>
-    where F: FnOnce(Option<&str>) -> io::Result<()>
+pub fn resolve_symname<F>(frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()>
+where
+    F: FnOnce(Option<&str>) -> io::Result<()>,
 {
-    let SymFromAddr = sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn)?;
+    match context.StackWalkVariant {
+        StackWalkVariant::StackWalkEx(_, ref fns) => resolve_symname_internal(
+            |process: c::HANDLE,
+             symbol_address: u64,
+             inline_context: c::ULONG,
+             info: *mut c::SYMBOL_INFO| unsafe {
+                let mut displacement = 0u64;
+                (fns.resolve_symname)(
+                    process,
+                    symbol_address,
+                    inline_context,
+                    &mut displacement,
+                    info,
+                )
+            },
+            frame,
+            callback,
+            context,
+        ),
+        StackWalkVariant::StackWalk64(_, ref fns) => resolve_symname_internal(
+            |process: c::HANDLE,
+             symbol_address: u64,
+             _inline_context: c::ULONG,
+             info: *mut c::SYMBOL_INFO| unsafe {
+                let mut displacement = 0u64;
+                (fns.resolve_symname)(process, symbol_address, &mut displacement, info)
+            },
+            frame,
+            callback,
+            context,
+        ),
+    }
+}
 
+fn resolve_symname_internal<F, R>(
+    mut symbol_resolver: R,
+    frame: Frame,
+    callback: F,
+    context: &BacktraceContext,
+) -> io::Result<()>
+where
+    F: FnOnce(Option<&str>) -> io::Result<()>,
+    R: FnMut(c::HANDLE, u64, c::ULONG, *mut c::SYMBOL_INFO) -> c::BOOL,
+{
     unsafe {
         let mut info: c::SYMBOL_INFO = mem::zeroed();
         info.MaxNameLen = c::MAX_SYM_NAME as c_ulong;
@@ -39,13 +120,22 @@ pub fn resolve_symname<F>(frame: Frame,
         // due to struct alignment.
         info.SizeOfStruct = 88;
 
-        let mut displacement = 0u64;
-        let ret = SymFromAddr(context.handle,
-                              frame.symbol_addr as u64,
-                              &mut displacement,
-                              &mut info);
-
-        let symname = if ret == c::TRUE {
+        let ret = symbol_resolver(
+            context.handle,
+            frame.symbol_addr as u64,
+            frame.inline_context,
+            &mut info,
+        );
+        let valid_range = if ret == c::TRUE && frame.symbol_addr as usize >= info.Address as usize {
+            if info.Size != 0 {
+                (frame.symbol_addr as usize) < info.Address as usize + info.Size as usize
+            } else {
+                true
+            }
+        } else {
+            false
+        };
+        let symname = if valid_range {
             let ptr = info.Name.as_ptr() as *const c_char;
             CStr::from_ptr(ptr).to_str().ok()
         } else {
@@ -55,28 +145,72 @@ pub fn resolve_symname<F>(frame: Frame,
     }
 }
 
-pub fn foreach_symbol_fileline<F>(frame: Frame,
-                                  mut f: F,
-                                  context: &BacktraceContext)
-    -> io::Result<bool>
-    where F: FnMut(&[u8], u32) -> io::Result<()>
+pub fn foreach_symbol_fileline<F>(
+    frame: Frame,
+    callback: F,
+    context: &BacktraceContext,
+) -> io::Result<bool>
+where
+    F: FnMut(&[u8], u32) -> io::Result<()>,
 {
-    let SymGetLineFromAddr64 = sym!(&context.dbghelp,
-                                    "SymGetLineFromAddr64",
-                                    SymGetLineFromAddr64Fn)?;
+    match context.StackWalkVariant {
+        StackWalkVariant::StackWalkEx(_, ref fns) => foreach_symbol_fileline_iternal(
+            |process: c::HANDLE,
+             frame_address: u64,
+             inline_context: c::ULONG,
+             line: *mut c::IMAGEHLP_LINE64| unsafe {
+                let mut displacement = 0u32;
+                (fns.sym_get_line)(
+                    process,
+                    frame_address,
+                    inline_context,
+                    0,
+                    &mut displacement,
+                    line,
+                )
+            },
+            frame,
+            callback,
+            context,
+        ),
+        StackWalkVariant::StackWalk64(_, ref fns) => foreach_symbol_fileline_iternal(
+            |process: c::HANDLE,
+             frame_address: u64,
+             _inline_context: c::ULONG,
+             line: *mut c::IMAGEHLP_LINE64| unsafe {
+                let mut displacement = 0u32;
+                (fns.sym_get_line)(process, frame_address, &mut displacement, line)
+            },
+            frame,
+            callback,
+            context,
+        ),
+    }
+}
 
+fn foreach_symbol_fileline_iternal<F, G>(
+    mut line_getter: G,
+    frame: Frame,
+    mut callback: F,
+    context: &BacktraceContext,
+) -> io::Result<bool>
+where
+    F: FnMut(&[u8], u32) -> io::Result<()>,
+    G: FnMut(c::HANDLE, u64, c::ULONG, *mut c::IMAGEHLP_LINE64) -> c::BOOL,
+{
     unsafe {
         let mut line: c::IMAGEHLP_LINE64 = mem::zeroed();
         line.SizeOfStruct = ::mem::size_of::<c::IMAGEHLP_LINE64>() as u32;
 
-        let mut displacement = 0u32;
-        let ret = SymGetLineFromAddr64(context.handle,
-                                       frame.exact_position as u64,
-                                       &mut displacement,
-                                       &mut line);
+        let ret = line_getter(
+            context.handle,
+            frame.exact_position as u64,
+            frame.inline_context,
+            &mut line,
+        );
         if ret == c::TRUE {
             let name = CStr::from_ptr(line.Filename).to_bytes();
-            f(name, line.LineNumber as u32)?;
+            callback(name, line.LineNumber as u32)?;
         }
         Ok(false)
     }
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index 66b44f1402f..e514a56dcc4 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -280,6 +280,9 @@ pub const IMAGE_FILE_MACHINE_I386: DWORD = 0x014c;
 #[cfg(target_arch = "x86_64")]
 #[cfg(feature = "backtrace")]
 pub const IMAGE_FILE_MACHINE_AMD64: DWORD = 0x8664;
+#[cfg(target_arch = "aarch64")]
+#[cfg(feature = "backtrace")]
+pub const IMAGE_FILE_MACHINE_ARM64: DWORD = 0xAA64;
 
 pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
 pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
@@ -296,6 +299,8 @@ pub const PIPE_READMODE_BYTE: DWORD = 0x00000000;
 
 pub const FD_SETSIZE: usize = 64;
 
+pub const STACK_SIZE_PARAM_IS_A_RESERVATION: DWORD = 0x00010000;
+
 #[repr(C)]
 #[cfg(not(target_pointer_width = "64"))]
 pub struct WSADATA {
@@ -619,6 +624,24 @@ pub struct ADDRESS64 {
 
 #[repr(C)]
 #[cfg(feature = "backtrace")]
+pub struct STACKFRAME_EX {
+    pub AddrPC: ADDRESS64,
+    pub AddrReturn: ADDRESS64,
+    pub AddrFrame: ADDRESS64,
+    pub AddrStack: ADDRESS64,
+    pub AddrBStore: ADDRESS64,
+    pub FuncTableEntry: *mut c_void,
+    pub Params: [u64; 4],
+    pub Far: BOOL,
+    pub Virtual: BOOL,
+    pub Reserved: [u64; 3],
+    pub KdHelp: KDHELP64,
+    pub StackFrameSize: DWORD,
+    pub InlineFrameContext: DWORD,
+}
+
+#[repr(C)]
+#[cfg(feature = "backtrace")]
 pub struct STACKFRAME64 {
     pub AddrPC: ADDRESS64,
     pub AddrReturn: ADDRESS64,
@@ -771,9 +794,68 @@ pub struct FLOATING_SAVE_AREA {
 // will not appear in the final documentation. This should be also defined for
 // other architectures supported by Windows such as ARM, and for historical
 // interest, maybe MIPS and PowerPC as well.
-#[cfg(all(dox, not(any(target_arch = "x86_64", target_arch = "x86"))))]
+#[cfg(all(dox, not(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"))))]
 pub enum CONTEXT {}
 
+#[cfg(target_arch = "aarch64")]
+pub const ARM64_MAX_BREAKPOINTS: usize = 8;
+
+#[cfg(target_arch = "aarch64")]
+pub const ARM64_MAX_WATCHPOINTS: usize = 2;
+
+#[cfg(target_arch = "aarch64")]
+#[repr(C)]
+pub struct ARM64_NT_NEON128 {
+    pub D: [f64; 2],
+}
+
+#[cfg(target_arch = "aarch64")]
+#[repr(C, align(16))]
+pub struct CONTEXT {
+    pub ContextFlags: DWORD,
+    pub Cpsr: DWORD,
+    pub X0: u64,
+    pub X1: u64,
+    pub X2: u64,
+    pub X3: u64,
+    pub X4: u64,
+    pub X5: u64,
+    pub X6: u64,
+    pub X7: u64,
+    pub X8: u64,
+    pub X9: u64,
+    pub X10: u64,
+    pub X11: u64,
+    pub X12: u64,
+    pub X13: u64,
+    pub X14: u64,
+    pub X15: u64,
+    pub X16: u64,
+    pub X17: u64,
+    pub X18: u64,
+    pub X19: u64,
+    pub X20: u64,
+    pub X21: u64,
+    pub X22: u64,
+    pub X23: u64,
+    pub X24: u64,
+    pub X25: u64,
+    pub X26: u64,
+    pub X27: u64,
+    pub X28: u64,
+    pub Fp: u64,
+    pub Lr: u64,
+    pub Sp: u64,
+    pub Pc: u64,
+    pub V: [ARM64_NT_NEON128; 32],
+    pub Fpcr: DWORD,
+    pub Fpsr: DWORD,
+    pub Bcr: [DWORD; ARM64_MAX_BREAKPOINTS],
+    pub Bvr: [DWORD; ARM64_MAX_BREAKPOINTS],
+    pub Wcr: [DWORD; ARM64_MAX_WATCHPOINTS],
+    pub Wvr: [DWORD; ARM64_MAX_WATCHPOINTS],
+}
+
 #[repr(C)]
 pub struct SOCKADDR_STORAGE_LH {
     pub ss_family: ADDRESS_FAMILY,
diff --git a/src/libstd/sys/windows/ext/ffi.rs b/src/libstd/sys/windows/ext/ffi.rs
index d6b8896ac09..bae0d02786a 100644
--- a/src/libstd/sys/windows/ext/ffi.rs
+++ b/src/libstd/sys/windows/ext/ffi.rs
@@ -31,7 +31,7 @@
 //!
 //! 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
+//! invalid sequences with [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD], as is
 //! conventionally done in other Rust APIs that deal with string
 //! encodings.
 //!
@@ -65,6 +65,7 @@
 //! [`from_wide`]: trait.OsStringExt.html#tymethod.from_wide
 //! [`encode_wide`]: trait.OsStrExt.html#tymethod.encode_wide
 //! [`collect`]: ../../../iter/trait.Iterator.html#method.collect
+//! [U+FFFD]: ../../../char/constant.REPLACEMENT_CHARACTER.html
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -76,7 +77,9 @@ use sys_common::{FromInner, AsInner};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use sys_common::wtf8::EncodeWide;
 
-/// Windows-specific extensions to `OsString`.
+/// Windows-specific extensions to [`OsString`].
+///
+/// [`OsString`]: ../../../../std/ffi/struct.OsString.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait OsStringExt {
     /// Creates an `OsString` from a potentially ill-formed UTF-16 slice of
@@ -109,7 +112,9 @@ impl OsStringExt for OsString {
     }
 }
 
-/// Windows-specific extensions to `OsStr`.
+/// Windows-specific extensions to [`OsStr`].
+///
+/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait OsStrExt {
     /// Re-encodes an `OsStr` as a wide character sequence, i.e. potentially
diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs
index 24c41046f26..78c9e95a055 100644
--- a/src/libstd/sys/windows/ext/fs.rs
+++ b/src/libstd/sys/windows/ext/fs.rs
@@ -45,15 +45,15 @@ pub trait FileExt {
     /// use std::fs::File;
     /// use std::os::windows::prelude::*;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let mut file = File::open("foo.txt")?;
-    /// let mut buffer = [0; 10];
-    ///
-    /// // Read 10 bytes, starting 72 bytes from the
-    /// // start of the file.
-    /// file.seek_read(&mut buffer[..], 72)?;
-    /// # Ok(())
-    /// # }
+    /// fn main() -> io::Result<()> {
+    ///     let mut file = File::open("foo.txt")?;
+    ///     let mut buffer = [0; 10];
+    ///
+    ///     // Read 10 bytes, starting 72 bytes from the
+    ///     // start of the file.
+    ///     file.seek_read(&mut buffer[..], 72)?;
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "file_offset", since = "1.15.0")]
     fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
@@ -79,14 +79,14 @@ pub trait FileExt {
     /// use std::fs::File;
     /// use std::os::windows::prelude::*;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let mut buffer = File::create("foo.txt")?;
+    /// fn main() -> std::io::Result<()> {
+    ///     let mut buffer = File::create("foo.txt")?;
     ///
-    /// // Write a byte string starting 72 bytes from
-    /// // the start of the file.
-    /// buffer.seek_write(b"some bytes", 72)?;
-    /// # Ok(())
-    /// # }
+    ///     // Write a byte string starting 72 bytes from
+    ///     // the start of the file.
+    ///     buffer.seek_write(b"some bytes", 72)?;
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "file_offset", since = "1.15.0")]
     fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
@@ -103,9 +103,9 @@ impl FileExt for fs::File {
     }
 }
 
-/// Windows-specific extensions to [`OpenOptions`].
+/// Windows-specific extensions to [`fs::OpenOptions`].
 ///
-/// [`OpenOptions`]: ../../../fs/struct.OpenOptions.html
+/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html
 #[stable(feature = "open_options_ext", since = "1.10.0")]
 pub trait OpenOptionsExt {
     /// Overrides the `dwDesiredAccess` argument to the call to [`CreateFile`]
@@ -281,13 +281,12 @@ impl OpenOptionsExt for OpenOptions {
     }
 }
 
-/// Extension methods for [`fs::Metadata`] to access the raw fields contained
-/// within.
+/// Windows-specific extensions to [`fs::Metadata`].
 ///
 /// The data members that this trait exposes correspond to the members
 /// of the [`BY_HANDLE_FILE_INFORMATION`] structure.
 ///
-/// [`fs::Metadata`]: ../../../fs/struct.Metadata.html
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 /// [`BY_HANDLE_FILE_INFORMATION`]:
 ///     https://msdn.microsoft.com/en-us/library/windows/desktop/aa363788.aspx
 #[stable(feature = "metadata_ext", since = "1.1.0")]
@@ -305,11 +304,11 @@ pub trait MetadataExt {
     /// use std::fs;
     /// use std::os::windows::prelude::*;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let metadata = fs::metadata("foo.txt")?;
-    /// let attributes = metadata.file_attributes();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> io::Result<()> {
+    ///     let metadata = fs::metadata("foo.txt")?;
+    ///     let attributes = metadata.file_attributes();
+    ///     Ok(())
+    /// }
     /// ```
     ///
     /// [File Attribute Constants]:
@@ -335,11 +334,11 @@ pub trait MetadataExt {
     /// use std::fs;
     /// use std::os::windows::prelude::*;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let metadata = fs::metadata("foo.txt")?;
-    /// let creation_time = metadata.creation_time();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> io::Result<()> {
+    ///     let metadata = fs::metadata("foo.txt")?;
+    ///     let creation_time = metadata.creation_time();
+    ///     Ok(())
+    /// }
     /// ```
     ///
     /// [`FILETIME`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx
@@ -370,11 +369,11 @@ pub trait MetadataExt {
     /// use std::fs;
     /// use std::os::windows::prelude::*;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let metadata = fs::metadata("foo.txt")?;
-    /// let last_access_time = metadata.last_access_time();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> io::Result<()> {
+    ///     let metadata = fs::metadata("foo.txt")?;
+    ///     let last_access_time = metadata.last_access_time();
+    ///     Ok(())
+    /// }
     /// ```
     ///
     /// [`FILETIME`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx
@@ -403,11 +402,11 @@ pub trait MetadataExt {
     /// use std::fs;
     /// use std::os::windows::prelude::*;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let metadata = fs::metadata("foo.txt")?;
-    /// let last_write_time = metadata.last_write_time();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> io::Result<()> {
+    ///     let metadata = fs::metadata("foo.txt")?;
+    ///     let last_write_time = metadata.last_write_time();
+    ///     Ok(())
+    /// }
     /// ```
     ///
     /// [`FILETIME`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx
@@ -426,11 +425,11 @@ pub trait MetadataExt {
     /// use std::fs;
     /// use std::os::windows::prelude::*;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let metadata = fs::metadata("foo.txt")?;
-    /// let file_size = metadata.file_size();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> io::Result<()> {
+    ///     let metadata = fs::metadata("foo.txt")?;
+    ///     let file_size = metadata.file_size();
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn file_size(&self) -> u64;
@@ -445,6 +444,27 @@ impl MetadataExt for Metadata {
     fn file_size(&self) -> u64 { self.as_inner().size() }
 }
 
+/// Windows-specific extensions to [`FileType`].
+///
+/// On Windows, a symbolic link knows whether it is a file or directory.
+///
+/// [`FileType`]: ../../../../std/fs/struct.FileType.html
+#[unstable(feature = "windows_file_type_ext", issue = "0")]
+pub trait FileTypeExt {
+    /// Returns whether this file type is a symbolic link that is also a directory.
+    #[unstable(feature = "windows_file_type_ext", issue = "0")]
+    fn is_symlink_dir(&self) -> bool;
+    /// Returns whether this file type is a symbolic link that is also a file.
+    #[unstable(feature = "windows_file_type_ext", issue = "0")]
+    fn is_symlink_file(&self) -> bool;
+}
+
+#[unstable(feature = "windows_file_type_ext", issue = "0")]
+impl FileTypeExt for fs::FileType {
+    fn is_symlink_dir(&self) -> bool { self.as_inner().is_symlink_dir() }
+    fn is_symlink_file(&self) -> bool { self.as_inner().is_symlink_file() }
+}
+
 /// Creates a new file symbolic link on the filesystem.
 ///
 /// The `dst` path will be a file symbolic link pointing to the `src`
@@ -455,10 +475,10 @@ impl MetadataExt for Metadata {
 /// ```no_run
 /// use std::os::windows::fs;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::symlink_file("a.txt", "b.txt")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     fs::symlink_file("a.txt", "b.txt")?;
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "symlink", since = "1.1.0")]
 pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
@@ -476,10 +496,10 @@ pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
 /// ```no_run
 /// use std::os::windows::fs;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::symlink_dir("a", "b")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     fs::symlink_dir("a", "b")?;
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "symlink", since = "1.1.0")]
 pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
diff --git a/src/libstd/sys/windows/ext/mod.rs b/src/libstd/sys/windows/ext/mod.rs
index 4b458d293bc..1f10609f32c 100644
--- a/src/libstd/sys/windows/ext/mod.rs
+++ b/src/libstd/sys/windows/ext/mod.rs
@@ -18,6 +18,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(cfg(windows))]
+#![allow(missing_docs)]
 
 pub mod ffi;
 pub mod fs;
diff --git a/src/libstd/sys/windows/ext/process.rs b/src/libstd/sys/windows/ext/process.rs
index 759f055c4b1..a02bcbe0c87 100644
--- a/src/libstd/sys/windows/ext/process.rs
+++ b/src/libstd/sys/windows/ext/process.rs
@@ -82,7 +82,9 @@ impl IntoRawHandle for process::ChildStderr {
     }
 }
 
-/// Windows-specific extensions to `std::process::ExitStatus`
+/// Windows-specific extensions to [`process::ExitStatus`].
+///
+/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html
 #[stable(feature = "exit_status_from", since = "1.12.0")]
 pub trait ExitStatusExt {
     /// Creates a new `ExitStatus` from the raw underlying `u32` return value of
@@ -98,7 +100,9 @@ impl ExitStatusExt for process::ExitStatus {
     }
 }
 
-/// Windows-specific extensions to the `std::process::Command` builder
+/// Windows-specific extensions to the [`process::Command`] builder.
+///
+/// [`process::Command`]: ../../../../std/process/struct.Command.html
 #[stable(feature = "windows_process_extensions", since = "1.16.0")]
 pub trait CommandExt {
     /// Sets the [process creation flags][1] to be passed to `CreateProcess`.
diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs
index 165e1b0609b..082d4689c7b 100644
--- a/src/libstd/sys/windows/fs.rs
+++ b/src/libstd/sys/windows/fs.rs
@@ -38,8 +38,9 @@ pub struct FileAttr {
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-pub enum FileType {
-    Dir, File, SymlinkFile, SymlinkDir, ReparsePoint, MountPoint,
+pub struct FileType {
+    attributes: c::DWORD,
+    reparse_tag: c::DWORD,
 }
 
 pub struct ReadDir {
@@ -516,30 +517,34 @@ impl FilePermissions {
 
 impl FileType {
     fn new(attrs: c::DWORD, reparse_tag: c::DWORD) -> FileType {
-        match (attrs & c::FILE_ATTRIBUTE_DIRECTORY != 0,
-               attrs & c::FILE_ATTRIBUTE_REPARSE_POINT != 0,
-               reparse_tag) {
-            (false, false, _) => FileType::File,
-            (true, false, _) => FileType::Dir,
-            (false, true, c::IO_REPARSE_TAG_SYMLINK) => FileType::SymlinkFile,
-            (true, true, c::IO_REPARSE_TAG_SYMLINK) => FileType::SymlinkDir,
-            (true, true, c::IO_REPARSE_TAG_MOUNT_POINT) => FileType::MountPoint,
-            (_, true, _) => FileType::ReparsePoint,
-            // Note: if a _file_ has a reparse tag of the type IO_REPARSE_TAG_MOUNT_POINT it is
-            // invalid, as junctions always have to be dirs. We set the filetype to ReparsePoint
-            // to indicate it is something symlink-like, but not something you can follow.
+        FileType {
+            attributes: attrs,
+            reparse_tag: reparse_tag,
         }
     }
-
-    pub fn is_dir(&self) -> bool { *self == FileType::Dir }
-    pub fn is_file(&self) -> bool { *self == FileType::File }
+    pub fn is_dir(&self) -> bool {
+        !self.is_symlink() && self.is_directory()
+    }
+    pub fn is_file(&self) -> bool {
+        !self.is_symlink() && !self.is_directory()
+    }
     pub fn is_symlink(&self) -> bool {
-        *self == FileType::SymlinkFile ||
-        *self == FileType::SymlinkDir ||
-        *self == FileType::MountPoint
+        self.is_reparse_point() && self.is_reparse_tag_name_surrogate()
     }
     pub fn is_symlink_dir(&self) -> bool {
-        *self == FileType::SymlinkDir || *self == FileType::MountPoint
+        self.is_symlink() && self.is_directory()
+    }
+    pub fn is_symlink_file(&self) -> bool {
+        self.is_symlink() && !self.is_directory()
+    }
+    fn is_directory(&self) -> bool {
+        self.attributes & c::FILE_ATTRIBUTE_DIRECTORY != 0
+    }
+    fn is_reparse_point(&self) -> bool {
+        self.attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0
+    }
+    fn is_reparse_tag_name_surrogate(&self) -> bool {
+        self.reparse_tag & 0x20000000 != 0
     }
 }
 
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs
index 0d12ecf8fe3..ccf79de909f 100644
--- a/src/libstd/sys/windows/mod.rs
+++ b/src/libstd/sys/windows/mod.rs
@@ -266,8 +266,12 @@ pub fn dur2timeout(dur: Duration) -> c::DWORD {
 // handlers.
 //
 // https://msdn.microsoft.com/en-us/library/dn774154.aspx
-#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+#[allow(unreachable_code)]
 pub unsafe fn abort_internal() -> ! {
-    asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
-    ::intrinsics::unreachable();
+    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+    {
+        asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
+        ::intrinsics::unreachable();
+    }
+    ::intrinsics::abort();
 }
diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs
index 85560368590..9bf9f749d4d 100644
--- a/src/libstd/sys/windows/mutex.rs
+++ b/src/libstd/sys/windows/mutex.rs
@@ -117,7 +117,7 @@ impl Mutex {
             0 => {}
             n => return n as *mut _,
         }
-        let mut re = Box::new(ReentrantMutex::uninitialized());
+        let mut re = box ReentrantMutex::uninitialized();
         re.init();
         let re = Box::into_raw(re);
         match self.lock.compare_and_swap(0, re as usize, Ordering::SeqCst) {
diff --git a/src/libstd/sys/windows/os_str.rs b/src/libstd/sys/windows/os_str.rs
index 414c9c5418e..bcc66b9954b 100644
--- a/src/libstd/sys/windows/os_str.rs
+++ b/src/libstd/sys/windows/os_str.rs
@@ -114,6 +114,11 @@ impl Buf {
     }
 
     #[inline]
+    pub fn shrink_to(&mut self, min_capacity: usize) {
+        self.inner.shrink_to(min_capacity)
+    }
+
+    #[inline]
     pub fn into_box(self) -> Box<Slice> {
         unsafe { mem::transmute(self.inner.into_box()) }
     }
diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs
index f3b1185c6ea..df1dd7401af 100644
--- a/src/libstd/sys/windows/pipe.rs
+++ b/src/libstd/sys/windows/pipe.rs
@@ -236,7 +236,7 @@ enum State {
 impl<'a> AsyncPipe<'a> {
     fn new(pipe: Handle, dst: &'a mut Vec<u8>) -> io::Result<AsyncPipe<'a>> {
         // Create an event which we'll use to coordinate our overlapped
-        // opreations, this event will be used in WaitForMultipleObjects
+        // operations, this event will be used in WaitForMultipleObjects
         // and passed as part of the OVERLAPPED handle.
         //
         // Note that we do a somewhat clever thing here by flagging the
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index c93179869a6..4974a8de89c 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -10,7 +10,6 @@
 
 #![unstable(feature = "process_internals", issue = "0")]
 
-use ascii::AsciiExt;
 use collections::BTreeMap;
 use env::split_paths;
 use env;
@@ -18,7 +17,7 @@ use ffi::{OsString, OsStr};
 use fmt;
 use fs;
 use io::{self, Error, ErrorKind};
-use libc::c_void;
+use libc::{c_void, EXIT_SUCCESS, EXIT_FAILURE};
 use mem;
 use os::windows::ffi::OsStrExt;
 use path::Path;
@@ -32,7 +31,7 @@ use sys::stdio;
 use sys::cvt;
 use sys_common::{AsInner, FromInner, IntoInner};
 use sys_common::process::{CommandEnv, EnvKey};
-use alloc::borrow::Borrow;
+use borrow::Borrow;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Command
@@ -408,6 +407,19 @@ impl fmt::Display for ExitStatus {
     }
 }
 
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct ExitCode(c::DWORD);
+
+impl ExitCode {
+    pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _);
+    pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _);
+
+    #[inline]
+    pub fn as_i32(&self) -> i32 {
+        self.0 as i32
+    }
+}
+
 fn zeroed_startupinfo() -> c::STARTUPINFO {
     c::STARTUPINFO {
         cb: 0,
@@ -475,9 +487,7 @@ fn make_command_line(prog: &OsStr, args: &[OsString]) -> io::Result<Vec<u16>> {
             } else {
                 if x == '"' as u16 {
                     // Add n+1 backslashes to total 2n+1 before internal '"'.
-                    for _ in 0..(backslashes+1) {
-                        cmd.push('\\' as u16);
-                    }
+                    cmd.extend((0..(backslashes + 1)).map(|_| '\\' as u16));
                 }
                 backslashes = 0;
             }
@@ -486,9 +496,7 @@ fn make_command_line(prog: &OsStr, args: &[OsString]) -> io::Result<Vec<u16>> {
 
         if quote {
             // Add n backslashes to total 2n before ending '"'.
-            for _ in 0..backslashes {
-                cmd.push('\\' as u16);
-            }
+            cmd.extend((0..backslashes).map(|_| '\\' as u16));
             cmd.push('"' as u16);
         }
         Ok(())
diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs
index b43df20bddd..81b89da21d3 100644
--- a/src/libstd/sys/windows/stdio.rs
+++ b/src/libstd/sys/windows/stdio.rs
@@ -227,3 +227,7 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 // idea is that on windows we use a slightly smaller buffer that's
 // been seen to be acceptable.
 pub const STDIN_BUF_SIZE: usize = 8 * 1024;
+
+pub fn stderr_prints_nothing() -> bool {
+    false
+}
diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs
index 74786d09285..85588cc6c8e 100644
--- a/src/libstd/sys/windows/thread.rs
+++ b/src/libstd/sys/windows/thread.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use alloc::boxed::FnBox;
+use boxed::FnBox;
 use io;
 use ffi::CStr;
 use mem;
@@ -28,7 +28,7 @@ pub struct Thread {
 }
 
 impl Thread {
-    pub unsafe fn new<'a>(stack: usize, p: Box<FnBox() + 'a>)
+    pub unsafe fn new<'a>(stack: usize, p: Box<dyn FnBox() + 'a>)
                           -> io::Result<Thread> {
         let p = box p;
 
@@ -42,7 +42,8 @@ impl Thread {
         let stack_size = (stack + 0xfffe) & (!0xfffe);
         let ret = c::CreateThread(ptr::null_mut(), stack_size,
                                   thread_start, &*p as *const _ as *mut _,
-                                  0, ptr::null_mut());
+                                  c::STACK_SIZE_PARAM_IS_A_RESERVATION,
+                                  ptr::null_mut());
 
         return if ret as usize == 0 {
             Err(io::Error::last_os_error())
@@ -93,6 +94,8 @@ impl Thread {
 
 #[cfg_attr(test, allow(dead_code))]
 pub mod guard {
-    pub unsafe fn current() -> Option<usize> { None }
-    pub unsafe fn init() -> Option<usize> { None }
+    pub type Guard = !;
+    pub unsafe fn current() -> Option<Guard> { None }
+    pub unsafe fn init() -> Option<Guard> { None }
+    pub unsafe fn deinit() {}
 }
diff --git a/src/libstd/sys_common/at_exit_imp.rs b/src/libstd/sys_common/at_exit_imp.rs
index ce6fd4cb075..76e5df2c865 100644
--- a/src/libstd/sys_common/at_exit_imp.rs
+++ b/src/libstd/sys_common/at_exit_imp.rs
@@ -12,19 +12,24 @@
 //!
 //! Documentation can be found on the `rt::at_exit` function.
 
-use alloc::boxed::FnBox;
+use boxed::FnBox;
 use ptr;
+use mem;
 use sys_common::mutex::Mutex;
 
-type Queue = Vec<Box<FnBox()>>;
+type Queue = Vec<Box<dyn FnBox()>>;
 
 // NB these are specifically not types from `std::sync` as they currently rely
 // on poisoning and this module needs to operate at a lower level than requiring
 // the thread infrastructure to be in place (useful on the borders of
 // initialization/destruction).
+// We never call `LOCK.init()`, so it is UB to attempt to
+// acquire this mutex reentrantly!
 static LOCK: Mutex = Mutex::new();
 static mut QUEUE: *mut Queue = ptr::null_mut();
 
+const DONE: *mut Queue = 1_usize as *mut _;
+
 // The maximum number of times the cleanup routines will be run. While running
 // the at_exit closures new ones may be registered, and this count is the number
 // of times the new closures will be allowed to register successfully. After
@@ -35,7 +40,7 @@ unsafe fn init() -> bool {
     if QUEUE.is_null() {
         let state: Box<Queue> = box Vec::new();
         QUEUE = Box::into_raw(state);
-    } else if QUEUE as usize == 1 {
+    } else if QUEUE == DONE {
         // can't re-init after a cleanup
         return false
     }
@@ -44,20 +49,21 @@ unsafe fn init() -> bool {
 }
 
 pub fn cleanup() {
-    for i in 0..ITERS {
+    for i in 1..=ITERS {
         unsafe {
-            LOCK.lock();
-            let queue = QUEUE;
-            QUEUE = if i == ITERS - 1 {1} else {0} as *mut _;
-            LOCK.unlock();
+            let queue = {
+                let _guard = LOCK.lock();
+                mem::replace(&mut QUEUE, if i == ITERS { DONE } else { ptr::null_mut() })
+            };
 
             // make sure we're not recursively cleaning up
-            assert!(queue as usize != 1);
+            assert!(queue != DONE);
 
             // If we never called init, not need to cleanup!
-            if queue as usize != 0 {
+            if !queue.is_null() {
                 let queue: Box<Queue> = Box::from_raw(queue);
                 for to_run in *queue {
+                    // We are not holding any lock, so reentrancy is fine.
                     to_run();
                 }
             }
@@ -65,16 +71,16 @@ pub fn cleanup() {
     }
 }
 
-pub fn push(f: Box<FnBox()>) -> bool {
-    let mut ret = true;
+pub fn push(f: Box<dyn FnBox()>) -> bool {
     unsafe {
-        LOCK.lock();
+        let _guard = LOCK.lock();
         if init() {
+            // We are just moving `f` around, not calling it.
+            // There is no possibility of reentrancy here.
             (*QUEUE).push(f);
+            true
         } else {
-            ret = false;
+            false
         }
-        LOCK.unlock();
     }
-    ret
 }
diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs
index 36cbce2df75..77371782977 100644
--- a/src/libstd/sys_common/backtrace.rs
+++ b/src/libstd/sys_common/backtrace.rs
@@ -41,13 +41,15 @@ pub struct Frame {
     pub exact_position: *const u8,
     /// Address of the enclosing function.
     pub symbol_addr: *const u8,
+    /// Which inlined function is this frame referring to
+    pub inline_context: u32,
 }
 
 /// Max number of frames to print.
 const MAX_NB_FRAMES: usize = 100;
 
 /// Prints the current backtrace.
-pub fn print(w: &mut Write, format: PrintFormat) -> io::Result<()> {
+pub fn print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> {
     static LOCK: Mutex = Mutex::new();
 
     // Use a lock to prevent mixed output in multithreading context.
@@ -60,10 +62,11 @@ pub fn print(w: &mut Write, format: PrintFormat) -> io::Result<()> {
     }
 }
 
-fn _print(w: &mut Write, format: PrintFormat) -> io::Result<()> {
+fn _print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> {
     let mut frames = [Frame {
         exact_position: ptr::null(),
         symbol_addr: ptr::null(),
+        inline_context: 0,
     }; MAX_NB_FRAMES];
     let (nb_frames, context) = unwind_backtrace(&mut frames)?;
     let (skipped_before, skipped_after) =
@@ -133,13 +136,13 @@ pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
     f()
 }
 
-/// Controls how the backtrace should be formated.
+/// Controls how the backtrace should be formatted.
 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
 pub enum PrintFormat {
-    /// Show all the frames with absolute path for files.
-    Full = 2,
     /// Show only relevant data from the backtrace.
-    Short = 3,
+    Short = 2,
+    /// Show all the frames with absolute path for files.
+    Full = 3,
 }
 
 // For now logging is turned off by default, and this function checks to see
@@ -147,23 +150,21 @@ pub enum PrintFormat {
 pub fn log_enabled() -> Option<PrintFormat> {
     static ENABLED: atomic::AtomicIsize = atomic::AtomicIsize::new(0);
     match ENABLED.load(Ordering::SeqCst) {
-        0 => {},
+        0 => {}
         1 => return None,
-        2 => return Some(PrintFormat::Full),
-        3 => return Some(PrintFormat::Short),
-        _ => unreachable!(),
+        2 => return Some(PrintFormat::Short),
+        _ => return Some(PrintFormat::Full),
     }
 
-    let val = match env::var_os("RUST_BACKTRACE") {
-        Some(x) => if &x == "0" {
+    let val = env::var_os("RUST_BACKTRACE").and_then(|x|
+        if &x == "0" {
             None
         } else if &x == "full" {
             Some(PrintFormat::Full)
         } else {
             Some(PrintFormat::Short)
-        },
-        None => None,
-    };
+        }
+    );
     ENABLED.store(match val {
         Some(v) => v as isize,
         None => 1,
@@ -175,7 +176,7 @@ pub fn log_enabled() -> Option<PrintFormat> {
 ///
 /// These output functions should now be used everywhere to ensure consistency.
 /// You may want to also use `output_fileline`.
-fn output(w: &mut Write, idx: usize, frame: Frame,
+fn output(w: &mut dyn Write, idx: usize, frame: Frame,
               s: Option<&str>, format: PrintFormat) -> io::Result<()> {
     // Remove the `17: 0x0 - <unknown>` line.
     if format == PrintFormat::Short && frame.exact_position == ptr::null() {
@@ -200,7 +201,7 @@ fn output(w: &mut Write, idx: usize, frame: Frame,
 ///
 /// See also `output`.
 #[allow(dead_code)]
-fn output_fileline(w: &mut Write,
+fn output_fileline(w: &mut dyn Write,
                    file: &[u8],
                    line: u32,
                    format: PrintFormat) -> io::Result<()> {
@@ -252,7 +253,7 @@ fn output_fileline(w: &mut Write,
 // 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, mut s: &str, format: PrintFormat) -> io::Result<()> {
+pub fn demangle(writer: &mut dyn 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.
@@ -261,7 +262,7 @@ pub fn demangle(writer: &mut Write, mut s: &str, format: PrintFormat) -> io::Res
         let candidate = &s[i + llvm.len()..];
         let all_hex = candidate.chars().all(|c| {
             match c {
-                'A' ... 'F' | '0' ... '9' => true,
+                'A' ..= 'F' | '0' ..= '9' => true,
                 _ => false,
             }
         });
diff --git a/src/libstd/sys_common/bytestring.rs b/src/libstd/sys_common/bytestring.rs
index eb9cad09915..971b83938c1 100644
--- a/src/libstd/sys_common/bytestring.rs
+++ b/src/libstd/sys_common/bytestring.rs
@@ -11,7 +11,7 @@
 #![allow(dead_code)]
 
 use fmt::{Formatter, Result, Write};
-use std_unicode::lossy::{Utf8Lossy, Utf8LossyChunk};
+use core::str::lossy::{Utf8Lossy, Utf8LossyChunk};
 
 pub fn debug_fmt_bytestring(slice: &[u8], f: &mut Formatter) -> Result {
     // Writes out a valid unicode string with the correct escape sequences
diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs
index 27504d374dd..d0c4d6a7737 100644
--- a/src/libstd/sys_common/mod.rs
+++ b/src/libstd/sys_common/mod.rs
@@ -28,6 +28,16 @@
 use sync::Once;
 use sys;
 
+macro_rules! rtabort {
+    ($($t:tt)*) => (::sys_common::util::abort(format_args!($($t)*)))
+}
+
+macro_rules! rtassert {
+    ($e:expr) => (if !$e {
+        rtabort!(concat!("assertion failed: ", stringify!($e)));
+    })
+}
+
 pub mod at_exit_imp;
 #[cfg(feature = "backtrace")]
 pub mod backtrace;
@@ -101,10 +111,6 @@ pub fn at_exit<F: FnOnce() + Send + 'static>(f: F) -> Result<(), ()> {
     if at_exit_imp::push(Box::new(f)) {Ok(())} else {Err(())}
 }
 
-macro_rules! rtabort {
-    ($($t:tt)*) => (::sys_common::util::abort(format_args!($($t)*)))
-}
-
 /// One-time runtime cleanup.
 pub fn cleanup() {
     static CLEANUP: Once = Once::new();
diff --git a/src/libstd/sys_common/mutex.rs b/src/libstd/sys_common/mutex.rs
index d1a738770d3..c6d531c7a1a 100644
--- a/src/libstd/sys_common/mutex.rs
+++ b/src/libstd/sys_common/mutex.rs
@@ -24,11 +24,17 @@ impl Mutex {
     ///
     /// Behavior is undefined if the mutex is moved after it is
     /// first used with any of the functions below.
+    /// Also, until `init` is called, behavior is undefined if this
+    /// mutex is ever used reentrantly, i.e., `raw_lock` or `try_lock`
+    /// are called by the thread currently holding the lock.
     pub const fn new() -> Mutex { Mutex(imp::Mutex::new()) }
 
     /// Prepare the mutex for use.
     ///
     /// This should be called once the mutex is at a stable memory address.
+    /// If called, this must be the very first thing that happens to the mutex.
+    /// Calling it in parallel with or after any operation (including another
+    /// `init()`) is undefined behavior.
     #[inline]
     pub unsafe fn init(&mut self) { self.0.init() }
 
@@ -37,7 +43,15 @@ impl Mutex {
     /// Behavior is undefined if the mutex has been moved between this and any
     /// previous function call.
     #[inline]
-    pub unsafe fn lock(&self) { self.0.lock() }
+    pub unsafe fn raw_lock(&self) { self.0.lock() }
+
+    /// Calls raw_lock() and then returns an RAII guard to guarantee the mutex
+    /// will be unlocked.
+    #[inline]
+    pub unsafe fn lock(&self) -> MutexGuard {
+        self.raw_lock();
+        MutexGuard(&self.0)
+    }
 
     /// Attempts to lock the mutex without blocking, returning whether it was
     /// successfully acquired or not.
@@ -51,8 +65,11 @@ impl Mutex {
     ///
     /// Behavior is undefined if the current thread does not actually hold the
     /// mutex.
+    ///
+    /// Consider switching from the pair of raw_lock() and raw_unlock() to
+    /// lock() whenever possible.
     #[inline]
-    pub unsafe fn unlock(&self) { self.0.unlock() }
+    pub unsafe fn raw_unlock(&self) { self.0.unlock() }
 
     /// Deallocates all resources associated with this mutex.
     ///
@@ -64,3 +81,14 @@ impl Mutex {
 
 // not meant to be exported to the outside world, just the containing module
 pub fn raw(mutex: &Mutex) -> &imp::Mutex { &mutex.0 }
+
+#[must_use]
+/// A simple RAII utility for the above Mutex without the poisoning semantics.
+pub struct MutexGuard<'a>(&'a imp::Mutex);
+
+impl<'a> Drop for MutexGuard<'a> {
+    #[inline]
+    fn drop(&mut self) {
+        unsafe { self.0.unlock(); }
+    }
+}
diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs
index c70b39995eb..b841afe1a51 100644
--- a/src/libstd/sys_common/net.rs
+++ b/src/libstd/sys_common/net.rs
@@ -166,27 +166,9 @@ pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
     hints.ai_socktype = c::SOCK_STREAM;
     let mut res = ptr::null_mut();
     unsafe {
-        match cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res)) {
-            Ok(_) => {
-                Ok(LookupHost { original: res, cur: res })
-            },
-            #[cfg(unix)]
-            Err(e) => {
-                // 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
-            #[cfg(not(unix))]
-            Err(e) => Err(e),
-        }
+        cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res)).map(|_| {
+            LookupHost { original: res, cur: res }
+        })
     }
 }
 
diff --git a/src/libstd/sys_common/poison.rs b/src/libstd/sys_common/poison.rs
index 934ac3edbf1..1625efe4a2a 100644
--- a/src/libstd/sys_common/poison.rs
+++ b/src/libstd/sys_common/poison.rs
@@ -98,7 +98,7 @@ pub struct PoisonError<T> {
 }
 
 /// 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
+/// can occur while trying to acquire 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
@@ -251,7 +251,7 @@ impl<T> Error for TryLockError<T> {
         }
     }
 
-    fn cause(&self) -> Option<&Error> {
+    fn cause(&self) -> Option<&dyn Error> {
         match *self {
             TryLockError::Poisoned(ref p) => Some(p),
             _ => None
diff --git a/src/libstd/sys_common/process.rs b/src/libstd/sys_common/process.rs
index fd1a5fdb410..ddf0ebe603e 100644
--- a/src/libstd/sys_common/process.rs
+++ b/src/libstd/sys_common/process.rs
@@ -14,7 +14,7 @@
 use ffi::{OsStr, OsString};
 use env;
 use collections::BTreeMap;
-use alloc::borrow::Borrow;
+use borrow::Borrow;
 
 pub trait EnvKey:
     From<OsString> + Into<OsString> +
@@ -47,6 +47,7 @@ impl EnvKey for DefaultEnvKey {}
 #[derive(Clone, Debug)]
 pub struct CommandEnv<K> {
     clear: bool,
+    saw_path: bool,
     vars: BTreeMap<K, Option<OsString>>
 }
 
@@ -54,6 +55,7 @@ impl<K: EnvKey> Default for CommandEnv<K> {
     fn default() -> Self {
         CommandEnv {
             clear: false,
+            saw_path: false,
             vars: Default::default()
         }
     }
@@ -108,9 +110,11 @@ impl<K: EnvKey> CommandEnv<K> {
 
     // The following functions build up changes
     pub fn set(&mut self, key: &OsStr, value: &OsStr) {
+        self.maybe_saw_path(&key);
         self.vars.insert(key.to_owned().into(), Some(value.to_owned()));
     }
     pub fn remove(&mut self, key: &OsStr) {
+        self.maybe_saw_path(&key);
         if self.clear {
             self.vars.remove(key);
         } else {
@@ -121,4 +125,12 @@ impl<K: EnvKey> CommandEnv<K> {
         self.clear = true;
         self.vars.clear();
     }
+    pub fn have_changed_path(&self) -> bool {
+        self.saw_path || self.clear
+    }
+    fn maybe_saw_path(&mut self, key: &OsStr) {
+        if !self.saw_path && key == "PATH" {
+            self.saw_path = true;
+        }
+    }
 }
diff --git a/src/libstd/sys_common/remutex.rs b/src/libstd/sys_common/remutex.rs
index ce43ec6d9ab..071a3a25c7a 100644
--- a/src/libstd/sys_common/remutex.rs
+++ b/src/libstd/sys_common/remutex.rs
@@ -13,6 +13,7 @@ use marker;
 use ops::Deref;
 use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
 use sys::mutex as sys;
+use panic::{UnwindSafe, RefUnwindSafe};
 
 /// A re-entrant mutual exclusion
 ///
@@ -28,6 +29,9 @@ pub struct ReentrantMutex<T> {
 unsafe impl<T: Send> Send for ReentrantMutex<T> {}
 unsafe impl<T: Send> Sync for ReentrantMutex<T> {}
 
+impl<T> UnwindSafe for ReentrantMutex<T> {}
+impl<T> RefUnwindSafe for ReentrantMutex<T> {}
+
 
 /// An RAII implementation of a "scoped lock" of a mutex. When this structure is
 /// dropped (falls out of scope), the lock will be unlocked.
@@ -41,7 +45,7 @@ unsafe impl<T: Send> Sync for ReentrantMutex<T> {}
 /// because implementation of the trait would violate Rust’s reference aliasing
 /// rules. Use interior mutability (usually `RefCell`) in order to mutate the
 /// guarded data.
-#[must_use]
+#[must_use = "if unused the ReentrantMutex will immediately unlock"]
 pub struct ReentrantMutexGuard<'a, T: 'a> {
     // funny underscores due to how Deref currently works (it disregards field
     // privacy).
diff --git a/src/libstd/sys_common/thread.rs b/src/libstd/sys_common/thread.rs
index f1379b6ec63..86a5e2b8694 100644
--- a/src/libstd/sys_common/thread.rs
+++ b/src/libstd/sys_common/thread.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use alloc::boxed::FnBox;
+use boxed::FnBox;
 use env;
 use sync::atomic::{self, Ordering};
 use sys::stack_overflow;
@@ -21,7 +21,7 @@ pub unsafe fn start_thread(main: *mut u8) {
     let _handler = stack_overflow::Handler::new();
 
     // Finally, let's run some code.
-    Box::from_raw(main as *mut Box<FnBox()>)()
+    Box::from_raw(main as *mut Box<dyn FnBox()>)()
 }
 
 pub fn min_stack() -> usize {
diff --git a/src/libstd/sys_common/thread_info.rs b/src/libstd/sys_common/thread_info.rs
index 7970042b1d6..d75cbded734 100644
--- a/src/libstd/sys_common/thread_info.rs
+++ b/src/libstd/sys_common/thread_info.rs
@@ -11,10 +11,11 @@
 #![allow(dead_code)] // stack_guard isn't used right now on all platforms
 
 use cell::RefCell;
+use sys::thread::guard::Guard;
 use thread::Thread;
 
 struct ThreadInfo {
-    stack_guard: Option<usize>,
+    stack_guard: Option<Guard>,
     thread: Thread,
 }
 
@@ -38,14 +39,18 @@ pub fn current_thread() -> Option<Thread> {
     ThreadInfo::with(|info| info.thread.clone())
 }
 
-pub fn stack_guard() -> Option<usize> {
-    ThreadInfo::with(|info| info.stack_guard).and_then(|o| o)
+pub fn stack_guard() -> Option<Guard> {
+    ThreadInfo::with(|info| info.stack_guard.clone()).and_then(|o| o)
 }
 
-pub fn set(stack_guard: Option<usize>, thread: Thread) {
+pub fn set(stack_guard: Option<Guard>, thread: Thread) {
     THREAD_INFO.with(|c| assert!(c.borrow().is_none()));
     THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{
         stack_guard,
         thread,
     }));
 }
+
+pub fn reset_guard(stack_guard: Option<Guard>) {
+    THREAD_INFO.with(move |c| c.borrow_mut().as_mut().unwrap().stack_guard = stack_guard);
+}
diff --git a/src/libstd/sys_common/thread_local.rs b/src/libstd/sys_common/thread_local.rs
index a4aa3d96d25..bb72cb0930a 100644
--- a/src/libstd/sys_common/thread_local.rs
+++ b/src/libstd/sys_common/thread_local.rs
@@ -161,15 +161,16 @@ impl StaticKey {
         // Additionally a 0-index of a tls key hasn't been seen on windows, so
         // we just simplify the whole branch.
         if imp::requires_synchronized_create() {
+            // We never call `INIT_LOCK.init()`, so it is UB to attempt to
+            // acquire this mutex reentrantly!
             static INIT_LOCK: Mutex = Mutex::new();
-            INIT_LOCK.lock();
+            let _guard = INIT_LOCK.lock();
             let mut key = self.key.load(Ordering::SeqCst);
             if key == 0 {
                 key = imp::create(self.dtor) as usize;
                 self.key.store(key, Ordering::SeqCst);
             }
-            INIT_LOCK.unlock();
-            assert!(key != 0);
+            rtassert!(key != 0);
             return key
         }
 
@@ -190,7 +191,7 @@ impl StaticKey {
             imp::destroy(key1);
             key2
         };
-        assert!(key != 0);
+        rtassert!(key != 0);
         match self.key.compare_and_swap(0, key as usize, Ordering::SeqCst) {
             // The CAS succeeded, so we've created the actual key
             0 => key as usize,
diff --git a/src/libstd/sys_common/util.rs b/src/libstd/sys_common/util.rs
index a391c7cc6ef..a373e980b97 100644
--- a/src/libstd/sys_common/util.rs
+++ b/src/libstd/sys_common/util.rs
@@ -10,10 +10,13 @@
 
 use fmt;
 use io::prelude::*;
-use sys::stdio::Stderr;
+use sys::stdio::{Stderr, stderr_prints_nothing};
 use thread;
 
 pub fn dumb_print(args: fmt::Arguments) {
+    if stderr_prints_nothing() {
+        return
+    }
     let _ = Stderr::new().map(|mut stderr| stderr.write_fmt(args));
 }
 
diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs
index 46d554d6411..45204b56ead 100644
--- a/src/libstd/sys_common/wtf8.rs
+++ b/src/libstd/sys_common/wtf8.rs
@@ -27,7 +27,6 @@
 
 use core::str::next_code_point;
 
-use ascii::*;
 use borrow::Cow;
 use char;
 use fmt;
@@ -57,7 +56,7 @@ pub struct CodePoint {
 /// Example: `U+1F4A9`
 impl fmt::Debug for CodePoint {
     #[inline]
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         write!(formatter, "U+{:04X}", self.value)
     }
 }
@@ -77,7 +76,7 @@ impl CodePoint {
     #[inline]
     pub fn from_u32(value: u32) -> Option<CodePoint> {
         match value {
-            0 ... 0x10FFFF => Some(CodePoint { value: value }),
+            0 ..= 0x10FFFF => Some(CodePoint { value: value }),
             _ => None
         }
     }
@@ -102,7 +101,7 @@ impl CodePoint {
     #[inline]
     pub fn to_char(&self) -> Option<char> {
         match self.value {
-            0xD800 ... 0xDFFF => None,
+            0xD800 ..= 0xDFFF => None,
             _ => Some(unsafe { char::from_u32_unchecked(self.value) })
         }
     }
@@ -145,7 +144,7 @@ impl ops::DerefMut for Wtf8Buf {
 /// Example: `"a\u{D800}"` for a string with code points [U+0061, U+D800]
 impl fmt::Debug for Wtf8Buf {
     #[inline]
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         fmt::Debug::fmt(&**self, formatter)
     }
 }
@@ -254,6 +253,11 @@ impl Wtf8Buf {
         self.bytes.shrink_to_fit()
     }
 
+    #[inline]
+    pub fn shrink_to(&mut self, min_capacity: usize) {
+        self.bytes.shrink_to(min_capacity)
+    }
+
     /// Returns the number of bytes that this string buffer can hold without reallocating.
     #[inline]
     pub fn capacity(&self) -> usize {
@@ -301,7 +305,7 @@ impl Wtf8Buf {
     /// like concatenating ill-formed UTF-16 strings effectively would.
     #[inline]
     pub fn push(&mut self, code_point: CodePoint) {
-        if let trail @ 0xDC00...0xDFFF = code_point.to_u32() {
+        if let trail @ 0xDC00..=0xDFFF = code_point.to_u32() {
             if let Some(lead) = (&*self).final_lead_surrogate() {
                 let len_without_lead_surrogate = self.len() - 3;
                 self.bytes.truncate(len_without_lead_surrogate);
@@ -428,20 +432,15 @@ impl fmt::Debug for Wtf8 {
 
         formatter.write_str("\"")?;
         let mut pos = 0;
-        loop {
-            match self.next_surrogate(pos) {
-                None => break,
-                Some((surrogate_pos, surrogate)) => {
-                    write_str_escaped(
-                        formatter,
-                        unsafe { str::from_utf8_unchecked(
-                            &self.bytes[pos .. surrogate_pos]
-                        )},
-                    )?;
-                    write!(formatter, "\\u{{{:x}}}", surrogate)?;
-                    pos = surrogate_pos + 3;
-                }
-            }
+        while let Some((surrogate_pos, surrogate)) = self.next_surrogate(pos) {
+            write_str_escaped(
+                formatter,
+                unsafe { str::from_utf8_unchecked(
+                    &self.bytes[pos .. surrogate_pos]
+                )},
+            )?;
+            write!(formatter, "\\u{{{:x}}}", surrogate)?;
+            pos = surrogate_pos + 3;
         }
         write_str_escaped(
             formatter,
@@ -526,7 +525,7 @@ impl Wtf8 {
     #[inline]
     pub fn ascii_byte_at(&self, position: usize) -> u8 {
         match self.bytes[position] {
-            ascii_byte @ 0x00 ... 0x7F => ascii_byte,
+            ascii_byte @ 0x00 ..= 0x7F => ascii_byte,
             _ => 0xFF
         }
     }
@@ -631,7 +630,7 @@ impl Wtf8 {
             return None
         }
         match &self.bytes[(len - 3)..] {
-            &[0xED, b2 @ 0xA0...0xAF, b3] => Some(decode_surrogate(b2, b3)),
+            &[0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)),
             _ => None
         }
     }
@@ -643,7 +642,7 @@ impl Wtf8 {
             return None
         }
         match &self.bytes[..3] {
-            &[0xED, b2 @ 0xB0...0xBF, b3] => Some(decode_surrogate(b2, b3)),
+            &[0xED, b2 @ 0xB0..=0xBF, b3] => Some(decode_surrogate(b2, b3)),
             _ => None
         }
     }
@@ -876,24 +875,8 @@ impl Hash for Wtf8 {
     }
 }
 
-impl AsciiExt for Wtf8 {
-    type Owned = Wtf8Buf;
-
-    fn is_ascii(&self) -> bool {
-        self.bytes.is_ascii()
-    }
-    fn to_ascii_uppercase(&self) -> Wtf8Buf {
-        Wtf8Buf { bytes: self.bytes.to_ascii_uppercase() }
-    }
-    fn to_ascii_lowercase(&self) -> Wtf8Buf {
-        Wtf8Buf { bytes: self.bytes.to_ascii_lowercase() }
-    }
-    fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool {
-        self.bytes.eq_ignore_ascii_case(&other.bytes)
-    }
-
-    fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() }
-    fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() }
+impl Wtf8 {
+    pub fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() }
 }
 
 #[cfg(test)]
@@ -1262,7 +1245,7 @@ mod tests {
     #[test]
     fn wtf8_display() {
         fn d(b: &[u8]) -> String {
-            format!("{}", &unsafe { Wtf8::from_bytes_unchecked(b) })
+            (&unsafe { Wtf8::from_bytes_unchecked(b) }).to_string()
         }
 
         assert_eq!("", d("".as_bytes()));
diff --git a/src/libstd/termination.rs b/src/libstd/termination.rs
deleted file mode 100644
index 93a913bb540..00000000000
--- a/src/libstd/termination.rs
+++ /dev/null
@@ -1,86 +0,0 @@
-// 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 error::Error;
-#[cfg(target_arch = "wasm32")]
-mod exit {
-    pub const SUCCESS: i32 = 0;
-    pub const FAILURE: i32 = 1;
-}
-#[cfg(not(target_arch = "wasm32"))]
-mod exit {
-    use libc;
-    pub const SUCCESS: i32 = libc::EXIT_SUCCESS;
-    pub const FAILURE: i32 = libc::EXIT_FAILURE;
-}
-
-/// A trait for implementing arbitrary return types in the `main` function.
-///
-/// The c-main function only supports to return integers as return type.
-/// So, every type implementing the `Termination` trait has to be converted
-/// to an integer.
-///
-/// The default implementations are returning `libc::EXIT_SUCCESS` to indicate
-/// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned.
-#[cfg_attr(not(test), lang = "termination")]
-#[unstable(feature = "termination_trait", issue = "43301")]
-#[rustc_on_unimplemented =
-  "`main` can only return types that implement {Termination}, not `{Self}`"]
-pub trait Termination {
-    /// Is called to get the representation of the value as status code.
-    /// This status code is returned to the operating system.
-    fn report(self) -> i32;
-}
-
-#[unstable(feature = "termination_trait", issue = "43301")]
-impl Termination for () {
-    fn report(self) -> i32 { exit::SUCCESS }
-}
-
-#[unstable(feature = "termination_trait", issue = "43301")]
-impl<T: Termination, E: Error> Termination for Result<T, E> {
-    fn report(self) -> i32 {
-        match self {
-            Ok(val) => val.report(),
-            Err(err) => {
-                print_error(err);
-                exit::FAILURE
-            }
-        }
-    }
-}
-
-#[unstable(feature = "termination_trait", issue = "43301")]
-fn print_error<E: Error>(err: E) {
-    eprintln!("Error: {}", err.description());
-
-    if let Some(ref err) = err.cause() {
-        eprintln!("Caused by: {}", err.description());
-    }
-}
-
-#[unstable(feature = "termination_trait", issue = "43301")]
-impl Termination for ! {
-    fn report(self) -> i32 { unreachable!(); }
-}
-
-#[unstable(feature = "termination_trait", issue = "43301")]
-impl Termination for bool {
-    fn report(self) -> i32 {
-        if self { exit::SUCCESS } else { exit::FAILURE }
-    }
-}
-
-#[unstable(feature = "termination_trait", issue = "43301")]
-impl Termination for i32 {
-    fn report(self) -> i32 {
-        self
-    }
-}
diff --git a/src/libstd/tests/env.rs b/src/libstd/tests/env.rs
new file mode 100644
index 00000000000..8acb8a46d7b
--- /dev/null
+++ b/src/libstd/tests/env.rs
@@ -0,0 +1,94 @@
+// 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.
+
+extern crate rand;
+
+use std::env::*;
+use std::ffi::{OsString, OsStr};
+
+use rand::Rng;
+
+fn make_rand_name() -> OsString {
+    let mut rng = rand::thread_rng();
+    let n = format!("TEST{}", rng.gen_ascii_chars().take(10)
+                                 .collect::<String>());
+    let n = OsString::from(n);
+    assert!(var_os(&n).is_none());
+    n
+}
+
+fn eq(a: Option<OsString>, b: Option<&str>) {
+    assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s));
+}
+
+#[test]
+fn test_set_var() {
+    let n = make_rand_name();
+    set_var(&n, "VALUE");
+    eq(var_os(&n), Some("VALUE"));
+}
+
+#[test]
+fn test_remove_var() {
+    let n = make_rand_name();
+    set_var(&n, "VALUE");
+    remove_var(&n);
+    eq(var_os(&n), None);
+}
+
+#[test]
+fn test_set_var_overwrite() {
+    let n = make_rand_name();
+    set_var(&n, "1");
+    set_var(&n, "2");
+    eq(var_os(&n), Some("2"));
+    set_var(&n, "");
+    eq(var_os(&n), Some(""));
+}
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn test_var_big() {
+    let mut s = "".to_string();
+    let mut i = 0;
+    while i < 100 {
+        s.push_str("aaaaaaaaaa");
+        i += 1;
+    }
+    let n = make_rand_name();
+    set_var(&n, &s);
+    eq(var_os(&n), Some(&s));
+}
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn test_env_set_get_huge() {
+    let n = make_rand_name();
+    let s = "x".repeat(10000);
+    set_var(&n, &s);
+    eq(var_os(&n), Some(&s));
+    remove_var(&n);
+    eq(var_os(&n), None);
+}
+
+#[test]
+fn test_env_set_var() {
+    let n = make_rand_name();
+
+    let mut e = vars_os();
+    set_var(&n, "VALUE");
+    assert!(!e.any(|(k, v)| {
+        &*k == &*n && &*v == "VALUE"
+    }));
+
+    assert!(vars_os().any(|(k, v)| {
+        &*k == &*n && &*v == "VALUE"
+    }));
+}
diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs
index fcbca38a98f..a170abb2628 100644
--- a/src/libstd/thread/local.rs
+++ b/src/libstd/thread/local.rs
@@ -172,12 +172,16 @@ macro_rules! __thread_local_inner {
                 &'static $crate::cell::UnsafeCell<
                     $crate::option::Option<$t>>>
             {
+                #[cfg(target_arch = "wasm32")]
+                static __KEY: $crate::thread::__StaticLocalKeyInner<$t> =
+                    $crate::thread::__StaticLocalKeyInner::new();
+
                 #[thread_local]
-                #[cfg(target_thread_local)]
+                #[cfg(all(target_thread_local, not(target_arch = "wasm32")))]
                 static __KEY: $crate::thread::__FastLocalKeyInner<$t> =
                     $crate::thread::__FastLocalKeyInner::new();
 
-                #[cfg(not(target_thread_local))]
+                #[cfg(all(not(target_thread_local), not(target_arch = "wasm32")))]
                 static __KEY: $crate::thread::__OsLocalKeyInner<$t> =
                     $crate::thread::__OsLocalKeyInner::new();
 
@@ -195,64 +199,20 @@ macro_rules! __thread_local_inner {
     }
 }
 
-/// Indicator of the state of a thread local storage key.
-#[unstable(feature = "thread_local_state",
-           reason = "state querying was recently added",
-           issue = "27716")]
-#[derive(Debug, Eq, PartialEq, Copy, Clone)]
-pub enum LocalKeyState {
-    /// All keys are in this state whenever a thread starts. Keys will
-    /// transition to the `Valid` state once the first call to [`with`] happens
-    /// and the initialization expression succeeds.
-    ///
-    /// Keys in the `Uninitialized` state will yield a reference to the closure
-    /// passed to [`with`] so long as the initialization routine does not panic.
-    ///
-    /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
-    Uninitialized,
-
-    /// Once a key has been accessed successfully, it will enter the `Valid`
-    /// state. Keys in the `Valid` state will remain so until the thread exits,
-    /// at which point the destructor will be run and the key will enter the
-    /// `Destroyed` state.
-    ///
-    /// Keys in the `Valid` state will be guaranteed to yield a reference to the
-    /// closure passed to [`with`].
-    ///
-    /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
-    Valid,
-
-    /// When a thread exits, the destructors for keys will be run (if
-    /// necessary). While a destructor is running, and possibly after a
-    /// destructor has run, a key is in the `Destroyed` state.
-    ///
-    /// Keys in the `Destroyed` states will trigger a panic when accessed via
-    /// [`with`].
-    ///
-    /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
-    Destroyed,
-}
-
 /// An error returned by [`LocalKey::try_with`](struct.LocalKey.html#method.try_with).
-#[unstable(feature = "thread_local_state",
-           reason = "state querying was recently added",
-           issue = "27716")]
+#[stable(feature = "thread_local_try_with", since = "1.26.0")]
 pub struct AccessError {
     _private: (),
 }
 
-#[unstable(feature = "thread_local_state",
-           reason = "state querying was recently added",
-           issue = "27716")]
+#[stable(feature = "thread_local_try_with", since = "1.26.0")]
 impl fmt::Debug for AccessError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_struct("AccessError").finish()
     }
 }
 
-#[unstable(feature = "thread_local_state",
-           reason = "state querying was recently added",
-           issue = "27716")]
+#[stable(feature = "thread_local_try_with", since = "1.26.0")]
 impl fmt::Display for AccessError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Display::fmt("already destroyed", f)
@@ -312,64 +272,21 @@ impl<T: 'static> LocalKey<T> {
         (*ptr).as_ref().unwrap()
     }
 
-    /// Query the current state of this key.
-    ///
-    /// A key is initially in the `Uninitialized` state whenever a thread
-    /// starts. It will remain in this state up until the first call to [`with`]
-    /// within a thread has run the initialization expression successfully.
-    ///
-    /// 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. 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
-    /// destructor starts to run. Keys may remain in the `Destroyed` state after
-    /// destruction has completed. Keys without destructors (e.g. with types
-    /// that are [`Copy`]), may never enter the `Destroyed` state.
-    ///
-    /// Keys in the `Uninitialized` state can be accessed so long as the
-    /// initialization does not panic. Keys in the `Valid` state are guaranteed
-    /// to be able to be accessed. Keys in the `Destroyed` state will panic on
-    /// any call to [`with`].
-    ///
-    /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
-    /// [`Copy`]: ../../std/marker/trait.Copy.html
-    #[unstable(feature = "thread_local_state",
-               reason = "state querying was recently added",
-               issue = "27716")]
-    pub fn state(&'static self) -> LocalKeyState {
-        unsafe {
-            match (self.inner)() {
-                Some(cell) => {
-                    match *cell.get() {
-                        Some(..) => LocalKeyState::Valid,
-                        None => LocalKeyState::Uninitialized,
-                    }
-                }
-                None => LocalKeyState::Destroyed,
-            }
-        }
-    }
-
     /// Acquires a reference to the value in this TLS key.
     ///
     /// This will lazily initialize the value if this thread has not referenced
     /// this key yet. If the key has been destroyed (which may happen if this is called
-    /// in a destructor), this function will return a ThreadLocalError.
+    /// in a destructor), this function will return an [`AccessError`](struct.AccessError.html).
     ///
     /// # Panics
     ///
     /// This function will still `panic!()` if the key is uninitialized and the
     /// key's initializer panics.
-    #[unstable(feature = "thread_local_state",
-               reason = "state querying was recently added",
-               issue = "27716")]
+    #[stable(feature = "thread_local_try_with", since = "1.26.0")]
     pub fn try_with<F, R>(&'static self, f: F) -> Result<R, AccessError>
-                      where F: FnOnce(&T) -> R {
+    where
+        F: FnOnce(&T) -> R,
+    {
         unsafe {
             let slot = (self.inner)().ok_or(AccessError {
                 _private: (),
@@ -382,6 +299,39 @@ impl<T: 'static> LocalKey<T> {
     }
 }
 
+/// On some platforms like wasm32 there's no threads, so no need to generate
+/// thread locals and we can instead just use plain statics!
+#[doc(hidden)]
+#[cfg(target_arch = "wasm32")]
+pub mod statik {
+    use cell::UnsafeCell;
+    use fmt;
+
+    pub struct Key<T> {
+        inner: UnsafeCell<Option<T>>,
+    }
+
+    unsafe impl<T> ::marker::Sync for Key<T> { }
+
+    impl<T> fmt::Debug for Key<T> {
+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            f.pad("Key { .. }")
+        }
+    }
+
+    impl<T> Key<T> {
+        pub const fn new() -> Key<T> {
+            Key {
+                inner: UnsafeCell::new(None),
+            }
+        }
+
+        pub unsafe fn get(&self) -> Option<&'static UnsafeCell<Option<T>>> {
+            Some(&*(&self.inner as *const _))
+        }
+    }
+}
+
 #[doc(hidden)]
 #[cfg(target_thread_local)]
 pub mod fast {
@@ -530,7 +480,6 @@ pub mod os {
 mod tests {
     use sync::mpsc::{channel, Sender};
     use cell::{Cell, UnsafeCell};
-    use super::LocalKeyState;
     use thread;
 
     struct Foo(Sender<()>);
@@ -569,21 +518,13 @@ mod tests {
         struct Foo;
         impl Drop for Foo {
             fn drop(&mut self) {
-                assert!(FOO.state() == LocalKeyState::Destroyed);
+                assert!(FOO.try_with(|_| ()).is_err());
             }
         }
-        fn foo() -> Foo {
-            assert!(FOO.state() == LocalKeyState::Uninitialized);
-            Foo
-        }
-        thread_local!(static FOO: Foo = foo());
+        thread_local!(static FOO: Foo = Foo);
 
         thread::spawn(|| {
-            assert!(FOO.state() == LocalKeyState::Uninitialized);
-            FOO.with(|_| {
-                assert!(FOO.state() == LocalKeyState::Valid);
-            });
-            assert!(FOO.state() == LocalKeyState::Valid);
+            assert!(FOO.try_with(|_| ()).is_ok());
         }).join().ok().unwrap();
     }
 
@@ -613,7 +554,7 @@ mod tests {
             fn drop(&mut self) {
                 unsafe {
                     HITS += 1;
-                    if K2.state() == LocalKeyState::Destroyed {
+                    if K2.try_with(|_| ()).is_err() {
                         assert_eq!(HITS, 3);
                     } else {
                         if HITS == 1 {
@@ -629,7 +570,7 @@ mod tests {
             fn drop(&mut self) {
                 unsafe {
                     HITS += 1;
-                    assert!(K1.state() != LocalKeyState::Destroyed);
+                    assert!(K1.try_with(|_| ()).is_ok());
                     assert_eq!(HITS, 2);
                     K1.with(|s| *s.get() = Some(S1));
                 }
@@ -648,7 +589,7 @@ mod tests {
 
         impl Drop for S1 {
             fn drop(&mut self) {
-                assert!(K1.state() == LocalKeyState::Destroyed);
+                assert!(K1.try_with(|_| ()).is_err());
             }
         }
 
@@ -672,9 +613,7 @@ mod tests {
             fn drop(&mut self) {
                 let S1(ref tx) = *self;
                 unsafe {
-                    if K2.state() != LocalKeyState::Destroyed {
-                        K2.with(|s| *s.get() = Some(Foo(tx.clone())));
-                    }
+                    let _ = K2.try_with(|s| *s.get() = Some(Foo(tx.clone())));
                 }
             }
         }
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index ee49bf796b8..61c6084a250 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -191,7 +191,7 @@ use time::Duration;
 #[macro_use] mod local;
 
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use self::local::{LocalKey, LocalKeyState, AccessError};
+pub use self::local::{LocalKey, AccessError};
 
 // The types used by the thread_local! macro to access TLS keys. Note that there
 // are two types, the "OS" type and the "fast" type. The OS thread local key
@@ -203,6 +203,9 @@ pub use self::local::{LocalKey, LocalKeyState, AccessError};
 // where available, but both are needed.
 
 #[unstable(feature = "libstd_thread_internals", issue = "0")]
+#[cfg(target_arch = "wasm32")]
+#[doc(hidden)] pub use self::local::statik::Key as __StaticLocalKeyInner;
+#[unstable(feature = "libstd_thread_internals", issue = "0")]
 #[cfg(target_thread_local)]
 #[doc(hidden)] pub use self::local::fast::Key as __FastLocalKeyInner;
 #[unstable(feature = "libstd_thread_internals", issue = "0")]
@@ -652,7 +655,7 @@ pub fn panicking() -> bool {
 /// The thread may sleep longer than the duration specified due to scheduling
 /// specifics or platform-dependent functionality.
 ///
-/// # Platform behavior
+/// # Platform-specific behavior
 ///
 /// On Unix platforms this function will not return early due to a
 /// signal being received or a spurious wakeup.
@@ -676,7 +679,7 @@ pub fn sleep_ms(ms: u32) {
 /// The thread may sleep longer than the duration specified due to scheduling
 /// specifics or platform-dependent functionality.
 ///
-/// # Platform behavior
+/// # Platform-specific behavior
 ///
 /// On Unix platforms this function will not return early due to a
 /// signal being received or a spurious wakeup. Platforms which do not support
@@ -728,7 +731,8 @@ const NOTIFIED: usize = 2;
 ///   specifying a maximum time to block the thread for.
 ///
 /// * The [`unpark`] method on a [`Thread`] atomically makes the token available
-///   if it wasn't already.
+///   if it wasn't already. Because the token is initially absent, [`unpark`]
+///   followed by [`park`] will result in the second call returning immediately.
 ///
 /// In other words, each [`Thread`] acts a bit like a spinlock that can be
 /// locked and unlocked using `park` and `unpark`.
@@ -763,6 +767,8 @@ const NOTIFIED: usize = 2;
 /// // Let some time pass for the thread to be spawned.
 /// thread::sleep(Duration::from_millis(10));
 ///
+/// // There is no race condition here, if `unpark`
+/// // happens first, `park` will return immediately.
 /// println!("Unpark the thread");
 /// parked_thread.thread().unpark();
 ///
@@ -793,7 +799,10 @@ pub fn park() {
     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(NOTIFIED) => {
+            thread.inner.state.store(EMPTY, SeqCst);
+            return;
+        } // should consume this notification, so prohibit spurious wakeups in next park.
         Err(_) => panic!("inconsistent park state"),
     }
     loop {
@@ -837,7 +846,7 @@ pub fn park_timeout_ms(ms: u32) {
 ///
 /// See the [park documentation][park] for more details.
 ///
-/// # Platform behavior
+/// # Platform-specific behavior
 ///
 /// Platforms which do not support nanosecond precision for sleeping will have
 /// `dur` rounded up to the nearest granularity of time they can sleep for.
@@ -879,7 +888,10 @@ pub fn park_timeout(dur: Duration) {
     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(NOTIFIED) => {
+            thread.inner.state.store(EMPTY, SeqCst);
+            return;
+        } // should consume this notification, so prohibit spurious wakeups in next park.
         Err(_) => panic!("inconsistent park_timeout state"),
     }
 
@@ -928,24 +940,23 @@ pub struct ThreadId(u64);
 impl ThreadId {
     // Generate a new unique thread ID.
     fn new() -> ThreadId {
+        // We never call `GUARD.init()`, so it is UB to attempt to
+        // acquire this mutex reentrantly!
         static GUARD: mutex::Mutex = mutex::Mutex::new();
         static mut COUNTER: u64 = 0;
 
         unsafe {
-            GUARD.lock();
+            let _guard = GUARD.lock();
 
             // If we somehow use up all our bits, panic so that we're not
             // covering up subtle bugs of IDs being reused.
             if COUNTER == ::u64::MAX {
-                GUARD.unlock();
                 panic!("failed to generate unique thread ID: bitspace exhausted");
             }
 
             let id = COUNTER;
             COUNTER += 1;
 
-            GUARD.unlock();
-
             ThreadId(id)
         }
     }
@@ -1169,7 +1180,7 @@ impl fmt::Debug for Thread {
 ///
 /// [`Result`]: ../../std/result/enum.Result.html
 #[stable(feature = "rust1", since = "1.0.0")]
-pub type Result<T> = ::result::Result<T, Box<Any + Send + 'static>>;
+pub type Result<T> = ::result::Result<T, Box<dyn Any + Send + 'static>>;
 
 // This packet is used to communicate the return value between the child thread
 // and the parent thread. Memory is shared through the `Arc` within and there's
@@ -1270,6 +1281,11 @@ impl<T> JoinInner<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct JoinHandle<T>(JoinInner<T>);
 
+#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")]
+unsafe impl<T> Send for JoinHandle<T> {}
+#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")]
+unsafe impl<T> Sync for JoinHandle<T> {}
+
 impl<T> JoinHandle<T> {
     /// Extracts a handle to the underlying thread.
     ///
@@ -1432,7 +1448,7 @@ mod tests {
         rx.recv().unwrap();
     }
 
-    fn avoid_copying_the_body<F>(spawnfn: F) where F: FnOnce(Box<Fn() + Send>) {
+    fn avoid_copying_the_body<F>(spawnfn: F) where F: FnOnce(Box<dyn Fn() + Send>) {
         let (tx, rx) = channel();
 
         let x: Box<_> = box 1;
@@ -1479,7 +1495,7 @@ mod tests {
         // (well, it would if the constant were 8000+ - I lowered it to be more
         // valgrind-friendly. try this at home, instead..!)
         const GENERATIONS: u32 = 16;
-        fn child_no(x: u32) -> Box<Fn() + Send> {
+        fn child_no(x: u32) -> Box<dyn Fn() + Send> {
             return Box::new(move|| {
                 if x < GENERATIONS {
                     thread::spawn(move|| child_no(x+1)());
@@ -1525,10 +1541,10 @@ mod tests {
     #[test]
     fn test_try_panic_message_any() {
         match thread::spawn(move|| {
-            panic!(box 413u16 as Box<Any + Send>);
+            panic!(box 413u16 as Box<dyn Any + Send>);
         }).join() {
             Err(e) => {
-                type T = Box<Any + Send>;
+                type T = Box<dyn Any + Send>;
                 assert!(e.is::<T>());
                 let any = e.downcast::<T>().unwrap();
                 assert!(any.is::<u16>());
diff --git a/src/libstd/time/mod.rs b/src/libstd/time.rs
index 6ce3b3e8a00..90ab3491599 100644
--- a/src/libstd/time/mod.rs
+++ b/src/libstd/time.rs
@@ -29,9 +29,7 @@ use sys::time;
 use sys_common::FromInner;
 
 #[stable(feature = "time", since = "1.3.0")]
-pub use self::duration::Duration;
-
-mod duration;
+pub use core::time::Duration;
 
 /// A measurement of a monotonically nondecreasing clock.
 /// Opaque and useful only with `Duration`.
@@ -51,6 +49,9 @@ mod duration;
 /// allows measuring the duration between two instants (or comparing two
 /// instants).
 ///
+/// The size of an `Instant` struct may vary depending on the target operating
+/// system.
+///
 /// Example:
 ///
 /// ```no_run
@@ -90,6 +91,9 @@ pub struct Instant(time::Instant);
 /// fixed point in time, a `SystemTime` can be converted to a human-readable time,
 /// or perhaps some other string representation.
 ///
+/// The size of a `SystemTime` struct may vary depending on the target operating
+/// system.
+///
 /// [`Instant`]: ../../std/time/struct.Instant.html
 /// [`Result`]: ../../std/result/enum.Result.html
 /// [`Duration`]: ../../std/time/struct.Duration.html
@@ -255,6 +259,28 @@ impl fmt::Debug for Instant {
 }
 
 impl SystemTime {
+    /// An anchor in time which can be used to create new `SystemTime` instances or
+    /// learn about where in time a `SystemTime` lies.
+    ///
+    /// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with
+    /// respect to the system clock. Using `duration_since` on an existing
+    /// `SystemTime` instance can tell how far away from this point in time a
+    /// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a
+    /// `SystemTime` instance to represent another fixed point in time.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::time::SystemTime;
+    ///
+    /// match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
+    ///     Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()),
+    ///     Err(_) => panic!("SystemTime before UNIX EPOCH!"),
+    /// }
+    /// ```
+    #[stable(feature = "assoc_unix_epoch", since = "1.28.0")]
+    pub const UNIX_EPOCH: SystemTime = UNIX_EPOCH;
+
     /// Returns the system time corresponding to "now".
     ///
     /// # Examples
diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs
deleted file mode 100644
index cb5bfb9176e..00000000000
--- a/src/libstd/time/duration.rs
+++ /dev/null
@@ -1,587 +0,0 @@
-// Copyright 2012-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 iter::Sum;
-use ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign};
-
-const NANOS_PER_SEC: u32 = 1_000_000_000;
-const NANOS_PER_MILLI: u32 = 1_000_000;
-const NANOS_PER_MICRO: u32 = 1_000;
-const MILLIS_PER_SEC: u64 = 1_000;
-const MICROS_PER_SEC: u64 = 1_000_000;
-
-/// A `Duration` type to represent a span of time, typically used for system
-/// timeouts.
-///
-/// Each `Duration` is composed of a whole number of seconds and a fractional part
-/// represented in nanoseconds.  If the underlying system does not support
-/// nanosecond-level precision, APIs binding a system timeout will typically round up
-/// the number of nanoseconds.
-///
-/// `Duration`s implement many common traits, including [`Add`], [`Sub`], and other
-/// [`ops`] traits.
-///
-/// [`Add`]: ../../std/ops/trait.Add.html
-/// [`Sub`]: ../../std/ops/trait.Sub.html
-/// [`ops`]: ../../std/ops/index.html
-///
-/// # Examples
-///
-/// ```
-/// use std::time::Duration;
-///
-/// let five_seconds = Duration::new(5, 0);
-/// let five_seconds_and_five_nanos = five_seconds + Duration::new(0, 5);
-///
-/// assert_eq!(five_seconds_and_five_nanos.as_secs(), 5);
-/// assert_eq!(five_seconds_and_five_nanos.subsec_nanos(), 5);
-///
-/// let ten_millis = Duration::from_millis(10);
-/// ```
-#[stable(feature = "duration", since = "1.3.0")]
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Default)]
-pub struct Duration {
-    secs: u64,
-    nanos: u32, // Always 0 <= nanos < NANOS_PER_SEC
-}
-
-impl Duration {
-    /// Creates a new `Duration` from the specified number of whole seconds and
-    /// additional nanoseconds.
-    ///
-    /// If the number of nanoseconds is greater than 1 billion (the number of
-    /// nanoseconds in a second), then it will carry over into the seconds provided.
-    ///
-    /// # Panics
-    ///
-    /// This constructor will panic if the carry from the nanoseconds overflows
-    /// the seconds counter.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::time::Duration;
-    ///
-    /// let five_seconds = Duration::new(5, 0);
-    /// ```
-    #[stable(feature = "duration", since = "1.3.0")]
-    #[inline]
-    pub fn new(secs: u64, nanos: u32) -> Duration {
-        let secs = secs.checked_add((nanos / NANOS_PER_SEC) as u64)
-            .expect("overflow in Duration::new");
-        let nanos = nanos % NANOS_PER_SEC;
-        Duration { secs: secs, nanos: nanos }
-    }
-
-    /// Creates a new `Duration` from the specified number of whole seconds.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::time::Duration;
-    ///
-    /// let duration = Duration::from_secs(5);
-    ///
-    /// assert_eq!(5, duration.as_secs());
-    /// assert_eq!(0, duration.subsec_nanos());
-    /// ```
-    #[stable(feature = "duration", since = "1.3.0")]
-    #[inline]
-    pub fn from_secs(secs: u64) -> Duration {
-        Duration { secs: secs, nanos: 0 }
-    }
-
-    /// Creates a new `Duration` from the specified number of milliseconds.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::time::Duration;
-    ///
-    /// let duration = Duration::from_millis(2569);
-    ///
-    /// assert_eq!(2, duration.as_secs());
-    /// assert_eq!(569_000_000, duration.subsec_nanos());
-    /// ```
-    #[stable(feature = "duration", since = "1.3.0")]
-    #[inline]
-    pub fn from_millis(millis: u64) -> Duration {
-        let secs = millis / MILLIS_PER_SEC;
-        let nanos = ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI;
-        Duration { secs: secs, nanos: nanos }
-    }
-
-    /// Creates a new `Duration` from the specified number of microseconds.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(duration_from_micros)]
-    /// use std::time::Duration;
-    ///
-    /// let duration = Duration::from_micros(1_000_002);
-    ///
-    /// assert_eq!(1, duration.as_secs());
-    /// assert_eq!(2000, duration.subsec_nanos());
-    /// ```
-    #[unstable(feature = "duration_from_micros", issue = "44400")]
-    #[inline]
-    pub fn from_micros(micros: u64) -> Duration {
-        let secs = micros / MICROS_PER_SEC;
-        let nanos = ((micros % MICROS_PER_SEC) as u32) * NANOS_PER_MICRO;
-        Duration { secs: secs, nanos: nanos }
-    }
-
-    /// Creates a new `Duration` from the specified number of nanoseconds.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(duration_extras)]
-    /// use std::time::Duration;
-    ///
-    /// let duration = Duration::from_nanos(1_000_000_123);
-    ///
-    /// assert_eq!(1, duration.as_secs());
-    /// assert_eq!(123, duration.subsec_nanos());
-    /// ```
-    #[unstable(feature = "duration_extras", issue = "46507")]
-    #[inline]
-    pub fn from_nanos(nanos: u64) -> Duration {
-        let secs = nanos / (NANOS_PER_SEC as u64);
-        let nanos = (nanos % (NANOS_PER_SEC as u64)) as u32;
-        Duration { secs: secs, nanos: nanos }
-    }
-
-    /// Returns the number of _whole_ seconds contained by this `Duration`.
-    ///
-    /// The returned value does not include the fractional (nanosecond) part of the
-    /// duration, which can be obtained using [`subsec_nanos`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::time::Duration;
-    ///
-    /// let duration = Duration::new(5, 730023852);
-    /// assert_eq!(duration.as_secs(), 5);
-    /// ```
-    ///
-    /// To determine the total number of seconds represented by the `Duration`,
-    /// use `as_secs` in combination with [`subsec_nanos`]:
-    ///
-    /// ```
-    /// use std::time::Duration;
-    ///
-    /// let duration = Duration::new(5, 730023852);
-    ///
-    /// assert_eq!(5.730023852,
-    ///            duration.as_secs() as f64
-    ///            + duration.subsec_nanos() as f64 * 1e-9);
-    /// ```
-    ///
-    /// [`subsec_nanos`]: #method.subsec_nanos
-    #[stable(feature = "duration", since = "1.3.0")]
-    #[inline]
-    pub fn as_secs(&self) -> u64 { self.secs }
-
-    /// Returns the fractional part of this `Duration`, in milliseconds.
-    ///
-    /// This method does **not** return the length of the duration when
-    /// represented by milliseconds. The returned number always represents a
-    /// fractional portion of a second (i.e. it is less than one thousand).
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(duration_extras)]
-    /// use std::time::Duration;
-    ///
-    /// let duration = Duration::from_millis(5432);
-    /// assert_eq!(duration.as_secs(), 5);
-    /// assert_eq!(duration.subsec_millis(), 432);
-    /// ```
-    #[unstable(feature = "duration_extras", issue = "46507")]
-    #[inline]
-    pub fn subsec_millis(&self) -> u32 { self.nanos / NANOS_PER_MILLI }
-
-    /// Returns the fractional part of this `Duration`, in microseconds.
-    ///
-    /// This method does **not** return the length of the duration when
-    /// represented by microseconds. The returned number always represents a
-    /// fractional portion of a second (i.e. it is less than one million).
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(duration_extras, duration_from_micros)]
-    /// use std::time::Duration;
-    ///
-    /// let duration = Duration::from_micros(1_234_567);
-    /// assert_eq!(duration.as_secs(), 1);
-    /// assert_eq!(duration.subsec_micros(), 234_567);
-    /// ```
-    #[unstable(feature = "duration_extras", issue = "46507")]
-    #[inline]
-    pub fn subsec_micros(&self) -> u32 { self.nanos / NANOS_PER_MICRO }
-
-    /// Returns the fractional part of this `Duration`, in nanoseconds.
-    ///
-    /// This method does **not** return the length of the duration when
-    /// represented by nanoseconds. The returned number always represents a
-    /// fractional portion of a second (i.e. it is less than one billion).
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::time::Duration;
-    ///
-    /// let duration = Duration::from_millis(5010);
-    /// assert_eq!(duration.as_secs(), 5);
-    /// assert_eq!(duration.subsec_nanos(), 10_000_000);
-    /// ```
-    #[stable(feature = "duration", since = "1.3.0")]
-    #[inline]
-    pub fn subsec_nanos(&self) -> u32 { self.nanos }
-
-    /// Checked `Duration` addition. Computes `self + other`, returning [`None`]
-    /// if overflow occurred.
-    ///
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// use std::time::Duration;
-    ///
-    /// assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), Some(Duration::new(0, 1)));
-    /// assert_eq!(Duration::new(1, 0).checked_add(Duration::new(std::u64::MAX, 0)), None);
-    /// ```
-    #[stable(feature = "duration_checked_ops", since = "1.16.0")]
-    #[inline]
-    pub fn checked_add(self, rhs: Duration) -> Option<Duration> {
-        if let Some(mut secs) = self.secs.checked_add(rhs.secs) {
-            let mut nanos = self.nanos + rhs.nanos;
-            if nanos >= NANOS_PER_SEC {
-                nanos -= NANOS_PER_SEC;
-                if let Some(new_secs) = secs.checked_add(1) {
-                    secs = new_secs;
-                } else {
-                    return None;
-                }
-            }
-            debug_assert!(nanos < NANOS_PER_SEC);
-            Some(Duration {
-                secs,
-                nanos,
-            })
-        } else {
-            None
-        }
-    }
-
-    /// Checked `Duration` subtraction. Computes `self - other`, returning [`None`]
-    /// if the result would be negative or if overflow occurred.
-    ///
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// use std::time::Duration;
-    ///
-    /// assert_eq!(Duration::new(0, 1).checked_sub(Duration::new(0, 0)), Some(Duration::new(0, 1)));
-    /// assert_eq!(Duration::new(0, 0).checked_sub(Duration::new(0, 1)), None);
-    /// ```
-    #[stable(feature = "duration_checked_ops", since = "1.16.0")]
-    #[inline]
-    pub fn checked_sub(self, rhs: Duration) -> Option<Duration> {
-        if let Some(mut secs) = self.secs.checked_sub(rhs.secs) {
-            let nanos = if self.nanos >= rhs.nanos {
-                self.nanos - rhs.nanos
-            } else {
-                if let Some(sub_secs) = secs.checked_sub(1) {
-                    secs = sub_secs;
-                    self.nanos + NANOS_PER_SEC - rhs.nanos
-                } else {
-                    return None;
-                }
-            };
-            debug_assert!(nanos < NANOS_PER_SEC);
-            Some(Duration { secs: secs, nanos: nanos })
-        } else {
-            None
-        }
-    }
-
-    /// Checked `Duration` multiplication. Computes `self * other`, returning
-    /// [`None`] if overflow occurred.
-    ///
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// use std::time::Duration;
-    ///
-    /// assert_eq!(Duration::new(0, 500_000_001).checked_mul(2), Some(Duration::new(1, 2)));
-    /// assert_eq!(Duration::new(std::u64::MAX - 1, 0).checked_mul(2), None);
-    /// ```
-    #[stable(feature = "duration_checked_ops", since = "1.16.0")]
-    #[inline]
-    pub fn checked_mul(self, rhs: u32) -> Option<Duration> {
-        // Multiply nanoseconds as u64, because it cannot overflow that way.
-        let total_nanos = self.nanos as u64 * rhs as u64;
-        let extra_secs = total_nanos / (NANOS_PER_SEC as u64);
-        let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32;
-        if let Some(secs) = self.secs
-            .checked_mul(rhs as u64)
-            .and_then(|s| s.checked_add(extra_secs)) {
-            debug_assert!(nanos < NANOS_PER_SEC);
-            Some(Duration {
-                secs,
-                nanos,
-            })
-        } else {
-            None
-        }
-    }
-
-    /// Checked `Duration` division. Computes `self / other`, returning [`None`]
-    /// if `other == 0`.
-    ///
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// use std::time::Duration;
-    ///
-    /// assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0)));
-    /// assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000)));
-    /// assert_eq!(Duration::new(2, 0).checked_div(0), None);
-    /// ```
-    #[stable(feature = "duration_checked_ops", since = "1.16.0")]
-    #[inline]
-    pub fn checked_div(self, rhs: u32) -> Option<Duration> {
-        if rhs != 0 {
-            let secs = self.secs / (rhs as u64);
-            let carry = self.secs - secs * (rhs as u64);
-            let extra_nanos = carry * (NANOS_PER_SEC as u64) / (rhs as u64);
-            let nanos = self.nanos / rhs + (extra_nanos as u32);
-            debug_assert!(nanos < NANOS_PER_SEC);
-            Some(Duration { secs: secs, nanos: nanos })
-        } else {
-            None
-        }
-    }
-}
-
-#[stable(feature = "duration", since = "1.3.0")]
-impl Add for Duration {
-    type Output = Duration;
-
-    fn add(self, rhs: Duration) -> Duration {
-        self.checked_add(rhs).expect("overflow when adding durations")
-    }
-}
-
-#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
-impl AddAssign for Duration {
-    fn add_assign(&mut self, rhs: Duration) {
-        *self = *self + rhs;
-    }
-}
-
-#[stable(feature = "duration", since = "1.3.0")]
-impl Sub for Duration {
-    type Output = Duration;
-
-    fn sub(self, rhs: Duration) -> Duration {
-        self.checked_sub(rhs).expect("overflow when subtracting durations")
-    }
-}
-
-#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
-impl SubAssign for Duration {
-    fn sub_assign(&mut self, rhs: Duration) {
-        *self = *self - rhs;
-    }
-}
-
-#[stable(feature = "duration", since = "1.3.0")]
-impl Mul<u32> for Duration {
-    type Output = Duration;
-
-    fn mul(self, rhs: u32) -> Duration {
-        self.checked_mul(rhs).expect("overflow when multiplying duration by scalar")
-    }
-}
-
-#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
-impl MulAssign<u32> for Duration {
-    fn mul_assign(&mut self, rhs: u32) {
-        *self = *self * rhs;
-    }
-}
-
-#[stable(feature = "duration", since = "1.3.0")]
-impl Div<u32> for Duration {
-    type Output = Duration;
-
-    fn div(self, rhs: u32) -> Duration {
-        self.checked_div(rhs).expect("divide by zero error when dividing duration by scalar")
-    }
-}
-
-#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
-impl DivAssign<u32> for Duration {
-    fn div_assign(&mut self, rhs: u32) {
-        *self = *self / rhs;
-    }
-}
-
-#[stable(feature = "duration_sum", since = "1.16.0")]
-impl Sum for Duration {
-    fn sum<I: Iterator<Item=Duration>>(iter: I) -> Duration {
-        iter.fold(Duration::new(0, 0), |a, b| a + b)
-    }
-}
-
-#[stable(feature = "duration_sum", since = "1.16.0")]
-impl<'a> Sum<&'a Duration> for Duration {
-    fn sum<I: Iterator<Item=&'a Duration>>(iter: I) -> Duration {
-        iter.fold(Duration::new(0, 0), |a, b| a + *b)
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::Duration;
-
-    #[test]
-    fn creation() {
-        assert!(Duration::from_secs(1) != Duration::from_secs(0));
-        assert_eq!(Duration::from_secs(1) + Duration::from_secs(2),
-                   Duration::from_secs(3));
-        assert_eq!(Duration::from_millis(10) + Duration::from_secs(4),
-                   Duration::new(4, 10 * 1_000_000));
-        assert_eq!(Duration::from_millis(4000), Duration::new(4, 0));
-    }
-
-    #[test]
-    fn secs() {
-        assert_eq!(Duration::new(0, 0).as_secs(), 0);
-        assert_eq!(Duration::from_secs(1).as_secs(), 1);
-        assert_eq!(Duration::from_millis(999).as_secs(), 0);
-        assert_eq!(Duration::from_millis(1001).as_secs(), 1);
-    }
-
-    #[test]
-    fn nanos() {
-        assert_eq!(Duration::new(0, 0).subsec_nanos(), 0);
-        assert_eq!(Duration::new(0, 5).subsec_nanos(), 5);
-        assert_eq!(Duration::new(0, 1_000_000_001).subsec_nanos(), 1);
-        assert_eq!(Duration::from_secs(1).subsec_nanos(), 0);
-        assert_eq!(Duration::from_millis(999).subsec_nanos(), 999 * 1_000_000);
-        assert_eq!(Duration::from_millis(1001).subsec_nanos(), 1 * 1_000_000);
-    }
-
-    #[test]
-    fn add() {
-        assert_eq!(Duration::new(0, 0) + Duration::new(0, 1),
-                   Duration::new(0, 1));
-        assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001),
-                   Duration::new(1, 1));
-    }
-
-    #[test]
-    fn checked_add() {
-        assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)),
-                   Some(Duration::new(0, 1)));
-        assert_eq!(Duration::new(0, 500_000_000).checked_add(Duration::new(0, 500_000_001)),
-                   Some(Duration::new(1, 1)));
-        assert_eq!(Duration::new(1, 0).checked_add(Duration::new(::u64::MAX, 0)), None);
-    }
-
-    #[test]
-    fn sub() {
-        assert_eq!(Duration::new(0, 1) - Duration::new(0, 0),
-                   Duration::new(0, 1));
-        assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000),
-                   Duration::new(0, 1));
-        assert_eq!(Duration::new(1, 0) - Duration::new(0, 1),
-                   Duration::new(0, 999_999_999));
-    }
-
-    #[test]
-    fn checked_sub() {
-        let zero = Duration::new(0, 0);
-        let one_nano = Duration::new(0, 1);
-        let one_sec = Duration::new(1, 0);
-        assert_eq!(one_nano.checked_sub(zero), Some(Duration::new(0, 1)));
-        assert_eq!(one_sec.checked_sub(one_nano),
-                   Some(Duration::new(0, 999_999_999)));
-        assert_eq!(zero.checked_sub(one_nano), None);
-        assert_eq!(zero.checked_sub(one_sec), None);
-    }
-
-    #[test] #[should_panic]
-    fn sub_bad1() {
-        Duration::new(0, 0) - Duration::new(0, 1);
-    }
-
-    #[test] #[should_panic]
-    fn sub_bad2() {
-        Duration::new(0, 0) - Duration::new(1, 0);
-    }
-
-    #[test]
-    fn mul() {
-        assert_eq!(Duration::new(0, 1) * 2, Duration::new(0, 2));
-        assert_eq!(Duration::new(1, 1) * 3, Duration::new(3, 3));
-        assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4));
-        assert_eq!(Duration::new(0, 500_000_001) * 4000,
-                   Duration::new(2000, 4000));
-    }
-
-    #[test]
-    fn checked_mul() {
-        assert_eq!(Duration::new(0, 1).checked_mul(2), Some(Duration::new(0, 2)));
-        assert_eq!(Duration::new(1, 1).checked_mul(3), Some(Duration::new(3, 3)));
-        assert_eq!(Duration::new(0, 500_000_001).checked_mul(4), Some(Duration::new(2, 4)));
-        assert_eq!(Duration::new(0, 500_000_001).checked_mul(4000),
-                   Some(Duration::new(2000, 4000)));
-        assert_eq!(Duration::new(::u64::MAX - 1, 0).checked_mul(2), None);
-    }
-
-    #[test]
-    fn div() {
-        assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0));
-        assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333));
-        assert_eq!(Duration::new(99, 999_999_000) / 100,
-                   Duration::new(0, 999_999_990));
-    }
-
-    #[test]
-    fn checked_div() {
-        assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0)));
-        assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000)));
-        assert_eq!(Duration::new(2, 0).checked_div(0), None);
-    }
-}