about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorBryan Drewery <bryan@shatow.net>2018-03-19 13:11:55 -0700
committerBryan Drewery <bryan@shatow.net>2018-03-19 13:11:55 -0700
commit00dac20e017d321b9999b04fd6d3132c4a21a388 (patch)
tree4a3b8da2afb957823317ffc83a8b0532934e46d0 /src/libstd
parentd740083fc8981ee933dc48a6b3dcee21b82c993e (diff)
parent57c74c39813c4668d3be5a0c244758f59ab32d9a (diff)
downloadrust-00dac20e017d321b9999b04fd6d3132c4a21a388.tar.gz
rust-00dac20e017d321b9999b04fd6d3132c4a21a388.zip
Merge branch 'update-beta-freebsd' into freebsd-posix-spawn
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/Cargo.toml2
-rw-r--r--src/libstd/ascii.rs481
-rw-r--r--src/libstd/build.rs3
-rw-r--r--src/libstd/collections/hash/map.rs167
-rw-r--r--src/libstd/collections/hash/set.rs18
-rw-r--r--src/libstd/collections/hash/table.rs57
-rw-r--r--src/libstd/collections/mod.rs3
-rw-r--r--src/libstd/error.rs2
-rw-r--r--src/libstd/ffi/c_str.rs16
-rw-r--r--src/libstd/fs.rs4
-rw-r--r--src/libstd/io/mod.rs2
-rw-r--r--src/libstd/io/stdio.rs42
-rw-r--r--src/libstd/lib.rs46
-rw-r--r--src/libstd/macros.rs86
-rw-r--r--src/libstd/net/parser.rs19
-rw-r--r--src/libstd/net/tcp.rs59
-rw-r--r--src/libstd/net/udp.rs55
-rw-r--r--src/libstd/panicking.rs6
-rw-r--r--src/libstd/path.rs108
-rw-r--r--src/libstd/primitive_docs.rs11
-rw-r--r--src/libstd/process.rs94
-rw-r--r--src/libstd/rt.rs2
-rw-r--r--src/libstd/sync/condvar.rs216
-rw-r--r--src/libstd/sys/cloudabi/shims/process.rs12
-rw-r--r--src/libstd/sys/redox/net/tcp.rs10
-rw-r--r--src/libstd/sys/redox/net/udp.rs10
-rw-r--r--src/libstd/sys/redox/process.rs13
-rw-r--r--src/libstd/sys/unix/ext/net.rs114
-rw-r--r--src/libstd/sys/unix/process/mod.rs2
-rw-r--r--src/libstd/sys/unix/process/process_common.rs14
-rw-r--r--src/libstd/sys/wasm/process.rs12
-rw-r--r--src/libstd/sys/windows/process.rs14
-rw-r--r--src/libstd/sys_common/wtf8.rs23
-rw-r--r--src/libstd/termination.rs77
-rw-r--r--src/libstd/tests/env.rs95
-rw-r--r--src/libstd/thread/local.rs128
-rw-r--r--src/libstd/thread/mod.rs2
37 files changed, 1185 insertions, 840 deletions
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index c1fe4a89d6a..12017598853 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -26,7 +26,7 @@ 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" }
diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs
index 82e1a3447dc..0837ff91c14 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.
 ///
@@ -245,7 +244,7 @@ pub trait AsciiExt {
     fn is_ascii_punctuation(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII graphic character:
-    /// U+0021 '@' ... U+007E '~'.
+    /// U+0021 '!' ... U+007E '~'.
     /// For strings, true if all characters in the string are
     /// ASCII graphic characters.
     ///
@@ -483,477 +482,3 @@ impl AsciiExt for str {
         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..6652ff98201 100644
--- a/src/libstd/build.rs
+++ b/src/libstd/build.rs
@@ -86,6 +86,7 @@ fn main() {
 
 fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> {
     let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", ".libs")?;
+    let cflags = env::var("CFLAGS").unwrap_or_default() + " -fvisibility=hidden -O2";
 
     run(Command::new("sh")
                 .current_dir(&native.out_dir)
@@ -98,7 +99,7 @@ fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> {
                 .arg("--disable-host-shared")
                 .arg(format!("--host={}", build_helper::gnu_target(target)))
                 .arg(format!("--build={}", build_helper::gnu_target(host)))
-                .env("CFLAGS", env::var("CFLAGS").unwrap_or_default() + " -fvisibility=hidden"));
+                .env("CFLAGS", cflags));
 
     run(Command::new(build_helper::make(host))
                 .current_dir(&native.out_dir)
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index a82ff915093..b18b38ec302 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -11,6 +11,8 @@
 use self::Entry::*;
 use self::VacantEntryState::*;
 
+use alloc::heap::{Heap, Alloc};
+use alloc::allocator::CollectionAllocErr;
 use cell::Cell;
 use borrow::Borrow;
 use cmp::max;
@@ -42,21 +44,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 {
@@ -620,7 +629,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")]
@@ -637,7 +646,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")]
@@ -724,7 +733,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")]
@@ -741,7 +750,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]
@@ -770,22 +779,50 @@ 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.try_reserve(additional) {
+            Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
+            Err(CollectionAllocErr::AllocErr(e)) => Heap.oom(e),
+            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> {
         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)?;
         } 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)?;
         }
+        Ok(())
     }
 
     /// Resizes the internal vectors to a new capacity. It's your
@@ -795,15 +832,15 @@ 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) -> 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, 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);
@@ -838,6 +875,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
@@ -849,7 +887,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);
@@ -1306,7 +1344,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);
     /// ```
@@ -1722,7 +1760,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() }
@@ -1750,7 +1788,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")]
@@ -1773,7 +1811,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")]
@@ -1808,7 +1846,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")]
@@ -1840,7 +1878,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")]
@@ -1863,7 +1901,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")]
@@ -1886,7 +1924,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")]
@@ -1921,7 +1959,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")]
@@ -2082,7 +2120,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();
@@ -2097,7 +2134,7 @@ impl<'a, K, V> Entry<'a, K, V> {
     ///    .or_insert(42);
     /// assert_eq!(map["poneyland"], 43);
     /// ```
-    #[unstable(feature = "entry_and_modify", issue = "44733")]
+    #[stable(feature = "entry_and_modify", since = "1.26.0")]
     pub fn and_modify<F>(self, mut f: F) -> Self
         where F: FnMut(&mut V)
     {
@@ -2718,6 +2755,9 @@ mod test_map {
     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() {
@@ -2787,24 +2827,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;
@@ -2812,9 +2852,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)
         }
     }
 
@@ -2834,8 +2874,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);
             }
 
@@ -2846,7 +2886,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());
@@ -2893,8 +2933,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);
             }
 
@@ -2944,13 +2984,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(_) => {}
@@ -2961,7 +3001,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);
@@ -3462,7 +3502,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);
@@ -3571,7 +3611,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);
@@ -3652,4 +3692,33 @@ mod test_map {
         let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { hm.entry(0) <- makepanic(); }));
         assert_eq!(hm.len(), 0);
     }
+
+    #[test]
+    fn test_try_reserve() {
+
+        let mut empty_bytes: HashMap<u8,u8> = HashMap::new();
+
+        const MAX_USIZE: usize = usize::MAX;
+
+        // 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;
+
+        if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) {
+        } else { panic!("usize::MAX should trigger an overflow!"); }
+
+        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!") }
+        }
+    }
+
 }
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index e9427fb40a0..9e63ba2717a 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -724,7 +724,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 +1097,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 +1124,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 +1155,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 +1208,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 +1244,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 +1283,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 +1307,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 +1745,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 73bd5747c10..8e78dc546c6 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -17,6 +17,7 @@ use mem::{align_of, size_of, needs_drop};
 use mem;
 use ops::{Deref, DerefMut};
 use ptr::{self, Unique, NonNull};
+use alloc::allocator::CollectionAllocErr;
 
 use self::BucketState::*;
 
@@ -741,14 +742,15 @@ fn test_offset_calculation() {
 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 try_new_uninitialized(capacity: usize) -> 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
@@ -768,25 +770,38 @@ impl<K, V> RawTable<K, V> {
                                                            align_of::<HashUint>(),
                                                            pairs_size,
                                                            align_of::<(K, V)>());
-        assert!(!oflo, "capacity overflow");
+        if oflo {
+            return Err(CollectionAllocErr::CapacityOverflow);
+        }
 
         // 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 size_of_bucket = size_of::<HashUint>().checked_add(size_of::<(K, V)>())
+            .ok_or(CollectionAllocErr::CapacityOverflow)?;
+        let capacity_mul_size_of_bucket = capacity.checked_mul(size_of_bucket);
+        if capacity_mul_size_of_bucket.is_none() || size < capacity_mul_size_of_bucket.unwrap() {
+            return Err(CollectionAllocErr::CapacityOverflow);
+        }
 
-        let buffer = Heap.alloc(Layout::from_size_align(size, alignment).unwrap())
-            .unwrap_or_else(|e| Heap.oom(e));
+        let buffer = Heap.alloc(Layout::from_size_align(size, alignment)
+            .ok_or(CollectionAllocErr::CapacityOverflow)?)?;
 
         let hashes = buffer as *mut HashUint;
 
-        RawTable {
+        Ok(RawTable {
             capacity_mask: capacity.wrapping_sub(1),
             size: 0,
             hashes: TaggedHashUintPtr::new(hashes),
             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::try_new_uninitialized(capacity) {
+            Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
+            Err(CollectionAllocErr::AllocErr(e)) => Heap.oom(e),
+            Ok(table) => { table }
         }
     }
 
@@ -809,13 +824,23 @@ impl<K, V> RawTable<K, V> {
         }
     }
 
+    /// 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> {
+        unsafe {
+            let ret = RawTable::try_new_uninitialized(capacity)?;
+            ptr::write_bytes(ret.hashes.ptr(), 0, capacity);
+            Ok(ret)
+        }
+    }
+
     /// 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::try_new(capacity) {
+            Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
+            Err(CollectionAllocErr::AllocErr(e)) => Heap.oom(e),
+            Ok(table) => { table }
         }
     }
 
diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs
index e9a150f34a5..be88f4e268a 100644
--- a/src/libstd/collections/mod.rs
+++ b/src/libstd/collections/mod.rs
@@ -438,6 +438,9 @@ 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::allocator::CollectionAllocErr;
+
 mod hash;
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index eb5022ad577..f8dbe193fed 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -234,7 +234,7 @@ impl<'a> From<Cow<'a, str>> for Box<Error> {
     }
 }
 
-#[unstable(feature = "never_type", issue = "35121")]
+#[stable(feature = "never_type", since = "1.26.0")]
 impl Error for ! {
     fn description(&self) -> &str { *self }
 }
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index e91d3a32a50..c88c2bc9137 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;
     ///
@@ -875,6 +875,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 +884,7 @@ impl CStr {
     ///
     /// # Examples
     ///
-    /// ```no_run
+    /// ```ignore (extern-declaration)
     /// # fn main() {
     /// use std::ffi::CStr;
     /// use std::os::raw::c_char;
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index 292a78278ab..db52ed67d3a 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -453,6 +453,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.
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index aa07f64b678..d403bf6bfe5 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -1506,6 +1506,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
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index 831688bb73d..1f73054e3be 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -17,7 +17,7 @@ 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! {
@@ -663,29 +663,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<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);
     }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 3c9004cdd19..62bef4bc499 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -266,13 +266,11 @@
 #![feature(float_from_str_radix)]
 #![feature(fn_traits)]
 #![feature(fnbox)]
-#![feature(fused)]
 #![feature(generic_param_attrs)]
-#![feature(hashmap_hasher)]
+#![feature(hashmap_internals)]
 #![feature(heap_api)]
 #![feature(i128)]
 #![feature(i128_type)]
-#![feature(inclusive_range)]
 #![feature(int_error_internals)]
 #![feature(integer_atomics)]
 #![feature(into_cow)]
@@ -283,7 +281,7 @@
 #![feature(macro_reexport)]
 #![feature(macro_vis_matcher)]
 #![feature(needs_panic_runtime)]
-#![feature(never_type)]
+#![feature(exhaustive_patterns)]
 #![feature(num_bits_bytes)]
 #![feature(old_wrapping)]
 #![feature(on_unimplemented)]
@@ -299,7 +297,7 @@
 #![feature(rand)]
 #![feature(raw)]
 #![feature(rustc_attrs)]
-#![feature(sip_hash_13)]
+#![feature(stdsimd)]
 #![feature(slice_bytes)]
 #![feature(slice_concat_ext)]
 #![feature(slice_internals)]
@@ -314,6 +312,7 @@
 #![feature(thread_local)]
 #![feature(toowned_clone_into)]
 #![feature(try_from)]
+#![feature(try_reserve)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
 #![feature(untagged_unions)]
@@ -324,7 +323,7 @@
 #![feature(doc_spotlight)]
 #![cfg_attr(test, feature(update_panic_count))]
 #![cfg_attr(windows, feature(used))]
-#![cfg_attr(stage0, feature(repr_align))]
+#![cfg_attr(stage0, feature(never_type))]
 
 #![default_lib_allocator]
 
@@ -355,8 +354,9 @@ use prelude::v1::*;
 // 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,
+#[macro_reexport(assert_eq, assert_ne, debug_assert, debug_assert_eq,
                  debug_assert_ne, unreachable, unimplemented, write, writeln, try)]
+#[cfg_attr(stage0, macro_reexport(assert))]
 extern crate core as __core;
 
 #[macro_use]
@@ -501,11 +501,35 @@ 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;
+    pub use core::simd;
+}
+
+#[unstable(feature = "stdsimd", issue = "48556")]
+#[cfg(all(not(stage0), not(test)))]
+pub use stdsimd::simd;
+#[unstable(feature = "stdsimd", issue = "48556")]
+#[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!`
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index f058b1caef5..000f9713615 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -68,6 +68,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!()))
@@ -312,7 +315,10 @@ pub mod builtin {
     /// ```
     #[stable(feature = "compile_error_macro", since = "1.20.0")]
     #[macro_export]
-    macro_rules! compile_error { ($msg:expr) => ({ /* compiler built-in */ }) }
+    macro_rules! compile_error {
+        ($msg:expr) => ({ /* compiler built-in */ });
+        ($msg:expr,) => ({ /* compiler built-in */ });
+    }
 
     /// The core macro for formatted string creation & output.
     ///
@@ -400,7 +406,10 @@ pub mod builtin {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[macro_export]
-    macro_rules! option_env { ($name:expr) => ({ /* compiler built-in */ }) }
+    macro_rules! option_env {
+        ($name:expr) => ({ /* compiler built-in */ });
+        ($name:expr,) => ({ /* compiler built-in */ });
+    }
 
     /// Concatenate identifiers into one identifier.
     ///
@@ -463,7 +472,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.
     ///
@@ -488,7 +497,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.
     ///
@@ -580,7 +589,10 @@ 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 */ }) }
+    macro_rules! include_str {
+        ($file:expr) => ({ /* compiler built-in */ });
+        ($file:expr,) => ({ /* compiler built-in */ });
+    }
 
     /// Includes a file as a reference to a byte array.
     ///
@@ -614,7 +626,10 @@ 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 */ }) }
+    macro_rules! include_bytes {
+        ($file:expr) => ({ /* compiler built-in */ });
+        ($file:expr,) => ({ /* compiler built-in */ });
+    }
 
     /// Expands to a string that represents the current module path.
     ///
@@ -700,7 +715,64 @@ pub mod builtin {
     /// "🙈🙊🙉🙈🙊🙉".
     #[stable(feature = "rust1", since = "1.0.0")]
     #[macro_export]
-    macro_rules! include { ($file:expr) => ({ /* compiler built-in */ }) }
+    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")]
+    #[macro_export]
+    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.
diff --git a/src/libstd/net/parser.rs b/src/libstd/net/parser.rs
index 261d44eebaa..ae5037cc44e 100644
--- a/src/libstd/net/parser.rs
+++ b/src/libstd/net/parser.rs
@@ -372,6 +372,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 263a2c13249..e28ccdb766a 100644
--- a/src/libstd/net/tcp.rs
+++ b/src/libstd/net/tcp.rs
@@ -259,8 +259,8 @@ 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.
     ///
     /// # Platform-specific behavior
     ///
@@ -269,9 +269,11 @@ impl TcpStream {
     /// 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,8 +306,8 @@ 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.
     ///
     /// # Platform-specific behavior
     ///
@@ -300,6 +316,7 @@ impl TcpStream {
     /// 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)
@@ -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 5e19519b88f..8e56954bea4 100644
--- a/src/libstd/net/udp.rs
+++ b/src/libstd/net/udp.rs
@@ -228,8 +228,8 @@ 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.
     ///
     /// # Platform-specific behavior
     ///
@@ -238,6 +238,7 @@ impl UdpSocket {
     /// 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,8 +274,8 @@ 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.
     ///
     /// # Platform-specific behavior
     ///
@@ -269,6 +284,7 @@ impl UdpSocket {
     /// 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)
@@ -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/panicking.rs b/src/libstd/panicking.rs
index 161c3fc7113..454ac64735c 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -55,7 +55,8 @@ extern {
                                 data: *mut u8,
                                 data_ptr: *mut usize,
                                 vtable_ptr: *mut usize) -> u32;
-    #[unwind]
+    #[cfg_attr(stage0, unwind)]
+    #[cfg_attr(not(stage0), unwind(allowed))]
     fn __rust_start_panic(data: usize, vtable: usize) -> u32;
 }
 
@@ -315,7 +316,8 @@ pub fn panicking() -> bool {
 /// Entry point of panic from the libcore crate.
 #[cfg(not(test))]
 #[lang = "panic_fmt"]
-#[unwind]
+#[cfg_attr(stage0, unwind)]
+#[cfg_attr(not(stage0), unwind(allowed))]
 pub extern fn rust_begin_panic(msg: fmt::Arguments,
                                file: &'static str,
                                line: u32,
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index e03a182653e..ec961575473 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -87,6 +87,7 @@ use io;
 use iter::{self, FusedIterator};
 use ops::{self, Deref};
 use rc::Rc;
+use str::FromStr;
 use sync::Arc;
 
 use ffi::{OsStr, OsString};
@@ -905,7 +906,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 +1009,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 +1036,50 @@ 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
+///
+/// ```
+/// #![feature(path_ancestors)]
+///
+/// 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)]
+#[unstable(feature = "path_ancestors", issue = "48581")]
+pub struct Ancestors<'a> {
+    next: Option<&'a Path>,
+}
+
+#[unstable(feature = "path_ancestors", issue = "48581")]
+impl<'a> Iterator for Ancestors<'a> {
+    type Item = &'a Path;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let next = self.next;
+        self.next = match next {
+            Some(path) => path.parent(),
+            None => None,
+        };
+        next
+    }
+}
+
+#[unstable(feature = "path_ancestors", issue = "48581")]
+impl<'a> FusedIterator for Ancestors<'a> {}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Basic types and traits
 ////////////////////////////////////////////////////////////////////////////////
@@ -1397,6 +1442,32 @@ impl From<String> for PathBuf {
     }
 }
 
+/// Error returned from [`PathBuf::from_str`][`from_str`].
+///
+/// Note that parsing a path will never fail. This error is just a placeholder
+/// for implementing `FromStr` for `PathBuf`.
+///
+/// [`from_str`]: struct.PathBuf.html#method.from_str
+#[derive(Debug, Clone, PartialEq, Eq)]
+#[stable(feature = "path_from_str", since = "1.26.0")]
+pub enum ParsePathError {}
+
+#[stable(feature = "path_from_str", since = "1.26.0")]
+impl fmt::Display for ParsePathError {
+    fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
+        match *self {}
+    }
+}
+
+#[stable(feature = "path_from_str", since = "1.26.0")]
+impl FromStr for PathBuf {
+    type Err = ParsePathError;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        Ok(PathBuf::from(s))
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<P: AsRef<Path>> iter::FromIterator<P> for PathBuf {
     fn from_iter<I: IntoIterator<Item = P>>(iter: I) -> PathBuf {
@@ -1820,12 +1891,43 @@ 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
+    ///
+    /// ```
+    /// #![feature(path_ancestors)]
+    ///
+    /// 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
+    #[unstable(feature = "path_ancestors", issue = "48581")]
+    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
     ///
diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs
index 358aa2c37df..e6e6be2e453 100644
--- a/src/libstd/primitive_docs.rs
+++ b/src/libstd/primitive_docs.rs
@@ -79,7 +79,6 @@ mod prim_bool { }
 /// write:
 ///
 /// ```
-/// #![feature(never_type)]
 /// # fn foo() -> u32 {
 /// let x: ! = {
 ///     return 123
@@ -131,13 +130,15 @@ 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`.
 ///
 /// [`String::from_str`]: str/trait.FromStr.html#tymethod.from_str
 /// [`Result<String, !>`]: result/enum.Result.html
@@ -154,7 +155,6 @@ mod prim_bool { }
 /// for example:
 ///
 /// ```
-/// # #![feature(never_type)]
 /// # use std::fmt;
 /// # trait Debug {
 /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result;
@@ -192,7 +192,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")]
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index 9b2f815b713..d5ac2d19e83 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -1080,6 +1080,46 @@ 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.
@@ -1392,6 +1432,60 @@ 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 =
+  "`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_lib", issue = "43301")]
+impl Termination for () {
+    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 {
+    fn report(self) -> i32 {
+        self.0.as_i32()
+    }
+}
+
 #[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
 mod tests {
     use io::prelude::*;
diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs
index 9dbaf784f89..e1392762a59 100644
--- a/src/libstd/rt.rs
+++ b/src/libstd/rt.rs
@@ -68,7 +68,7 @@ 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)
diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs
index 54bb6513650..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.
@@ -221,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.
     ///
@@ -295,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.
@@ -304,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
@@ -355,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
@@ -480,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};
@@ -550,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());
@@ -569,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/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/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..2ed67bd2836 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;
@@ -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/process.rs b/src/libstd/sys/redox/process.rs
index 3fd54973896..d0b94e14f54 100644
--- a/src/libstd/sys/redox/process.rs
+++ b/src/libstd/sys/redox/process.rs
@@ -13,6 +13,7 @@ use ffi::OsStr;
 use os::unix::ffi::OsStrExt;
 use fmt;
 use io::{self, Error, ErrorKind};
+use libc::{EXIT_SUCCESS, EXIT_FAILURE};
 use path::{Path, PathBuf};
 use sys::fd::FileDesc;
 use sys::fs::{File, OpenOptions};
@@ -480,6 +481,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/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs
index 86b0f35be92..ad437658d14 100644
--- a/src/libstd/sys/unix/ext/net.rs
+++ b/src/libstd/sys/unix/ext/net.rs
@@ -387,10 +387,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 +404,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 +426,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 +443,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)
@@ -1250,10 +1280,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 +1298,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 +1320,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 +1338,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 +1469,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 +1672,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 +1792,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/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 7e057401fab..d0486f06a14 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};
@@ -393,6 +393,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
+    }
+}
+
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use super::*;
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/windows/process.rs b/src/libstd/sys/windows/process.rs
index c93179869a6..f1ab9c47609 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -18,7 +18,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;
@@ -408,6 +408,18 @@ 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 _);
+
+    pub fn as_i32(&self) -> i32 {
+        self.0 as i32
+    }
+}
+
 fn zeroed_startupinfo() -> c::STARTUPINFO {
     c::STARTUPINFO {
         cb: 0,
diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs
index 46d554d6411..9fff8b91f96 100644
--- a/src/libstd/sys_common/wtf8.rs
+++ b/src/libstd/sys_common/wtf8.rs
@@ -428,20 +428,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,
diff --git a/src/libstd/termination.rs b/src/libstd/termination.rs
deleted file mode 100644
index dc7fa53aab6..00000000000
--- a/src/libstd/termination.rs
+++ /dev/null
@@ -1,77 +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 fmt::Debug;
-#[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: Debug> Termination for Result<T, E> {
-    fn report(self) -> i32 {
-        match self {
-            Ok(val) => val.report(),
-            Err(err) => {
-                eprintln!("Error: {:?}", err);
-                exit::FAILURE
-            }
-        }
-    }
-}
-
-#[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..d4376523691
--- /dev/null
+++ b/src/libstd/tests/env.rs
@@ -0,0 +1,95 @@
+// 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::iter::repeat;
+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 = repeat("x").take(10000).collect::<String>();
+    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..99479bc56ef 100644
--- a/src/libstd/thread/local.rs
+++ b/src/libstd/thread/local.rs
@@ -195,64 +195,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 +268,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 a `ThreadLocalError`.
     ///
     /// # 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: (),
@@ -530,7 +443,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 +481,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 +517,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 +533,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 +552,7 @@ mod tests {
 
         impl Drop for S1 {
             fn drop(&mut self) {
-                assert!(K1.state() == LocalKeyState::Destroyed);
+                assert!(K1.try_with(|_| ()).is_err());
             }
         }
 
@@ -672,9 +576,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 ff121e2d7ee..71aee673cfe 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