about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorQuietMisdreavus <grey@quietmisdreavus.net>2017-04-09 10:38:38 -0500
committerQuietMisdreavus <grey@quietmisdreavus.net>2017-04-09 10:38:38 -0500
commit8dd4c44ef6c851afcc9651c9b32df005e35d0d1d (patch)
tree5dc8ec96361b673f8d4162821a97f8f021d83436 /src/libcore
parentbfd01b7f40ae2cbfe9acbc1d10e79ffe16870df8 (diff)
parent2c48ae6f7ffae392d85c86240c67f49df01f44fd (diff)
downloadrust-8dd4c44ef6c851afcc9651c9b32df005e35d0d1d.tar.gz
rust-8dd4c44ef6c851afcc9651c9b32df005e35d0d1d.zip
merge with master to pick up pulldown switch
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/Cargo.toml4
-rw-r--r--src/libcore/any.rs2
-rw-r--r--src/libcore/cell.rs12
-rw-r--r--src/libcore/char.rs30
-rw-r--r--src/libcore/char_private.rs1238
-rw-r--r--src/libcore/clone.rs4
-rw-r--r--src/libcore/cmp.rs60
-rw-r--r--src/libcore/convert.rs32
-rw-r--r--src/libcore/fmt/mod.rs6
-rw-r--r--src/libcore/hash/mod.rs48
-rw-r--r--src/libcore/intrinsics.rs113
-rw-r--r--src/libcore/iter/iterator.rs72
-rw-r--r--src/libcore/iter/mod.rs132
-rw-r--r--src/libcore/iter/sources.rs22
-rw-r--r--src/libcore/iter/traits.rs58
-rw-r--r--src/libcore/iter_private.rs2
-rw-r--r--src/libcore/lib.rs11
-rw-r--r--src/libcore/macros.rs58
-rw-r--r--src/libcore/marker.rs4
-rw-r--r--src/libcore/mem.rs12
-rw-r--r--src/libcore/num/bignum.rs8
-rw-r--r--src/libcore/num/dec2flt/algorithm.rs4
-rw-r--r--src/libcore/num/dec2flt/rawfp.rs13
-rw-r--r--src/libcore/num/diy_float.rs2
-rw-r--r--src/libcore/num/flt2dec/mod.rs2
-rw-r--r--src/libcore/num/mod.rs143
-rw-r--r--src/libcore/ops.rs58
-rw-r--r--src/libcore/option.rs41
-rw-r--r--src/libcore/ptr.rs150
-rw-r--r--src/libcore/raw.rs2
-rw-r--r--src/libcore/result.rs9
-rw-r--r--src/libcore/slice/mod.rs (renamed from src/libcore/slice.rs)364
-rw-r--r--src/libcore/slice/sort.rs709
-rw-r--r--src/libcore/str/mod.rs517
-rw-r--r--src/libcore/sync/atomic.rs170
-rw-r--r--src/libcore/tests/any.rs125
-rw-r--r--src/libcore/tests/array.rs28
-rw-r--r--src/libcore/tests/atomic.rs97
-rw-r--r--src/libcore/tests/cell.rs289
-rw-r--r--src/libcore/tests/char.rs404
-rw-r--r--src/libcore/tests/clone.rs25
-rw-r--r--src/libcore/tests/cmp.rs88
-rw-r--r--src/libcore/tests/fmt/builders.rs498
-rw-r--r--src/libcore/tests/fmt/float.rs37
-rw-r--r--src/libcore/tests/fmt/mod.rs40
-rw-r--r--src/libcore/tests/fmt/num.rs152
-rw-r--r--src/libcore/tests/hash/mod.rs111
-rw-r--r--src/libcore/tests/hash/sip.rs342
-rw-r--r--src/libcore/tests/intrinsics.rs30
-rw-r--r--src/libcore/tests/iter.rs1084
-rw-r--r--src/libcore/tests/lib.rs64
-rw-r--r--src/libcore/tests/mem.rs123
-rw-r--r--src/libcore/tests/nonzero.rs100
-rw-r--r--src/libcore/tests/num/bignum.rs249
-rw-r--r--src/libcore/tests/num/dec2flt/mod.rs145
-rw-r--r--src/libcore/tests/num/dec2flt/parse.rs52
-rw-r--r--src/libcore/tests/num/dec2flt/rawfp.rs154
-rw-r--r--src/libcore/tests/num/flt2dec/estimator.rs65
-rw-r--r--src/libcore/tests/num/flt2dec/mod.rs1201
-rw-r--r--src/libcore/tests/num/flt2dec/strategy/dragon.rs74
-rw-r--r--src/libcore/tests/num/flt2dec/strategy/grisu.rs124
-rw-r--r--src/libcore/tests/num/i16.rs11
-rw-r--r--src/libcore/tests/num/i32.rs11
-rw-r--r--src/libcore/tests/num/i64.rs11
-rw-r--r--src/libcore/tests/num/i8.rs11
-rw-r--r--src/libcore/tests/num/int_macros.rs219
-rw-r--r--src/libcore/tests/num/mod.rs400
-rw-r--r--src/libcore/tests/num/u16.rs11
-rw-r--r--src/libcore/tests/num/u32.rs11
-rw-r--r--src/libcore/tests/num/u64.rs11
-rw-r--r--src/libcore/tests/num/u8.rs11
-rw-r--r--src/libcore/tests/num/uint_macros.rs158
-rw-r--r--src/libcore/tests/ops.rs49
-rw-r--r--src/libcore/tests/option.rs272
-rw-r--r--src/libcore/tests/ptr.rs214
-rw-r--r--src/libcore/tests/result.rs204
-rw-r--r--src/libcore/tests/slice.rs304
-rw-r--r--src/libcore/tests/str.rs11
-rw-r--r--src/libcore/tests/tuple.rs68
79 files changed, 10439 insertions, 1361 deletions
diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml
index e847c7fa3a0..5af63aa970f 100644
--- a/src/libcore/Cargo.toml
+++ b/src/libcore/Cargo.toml
@@ -10,8 +10,8 @@ test = false
 bench = false
 
 [[test]]
-name = "coretest"
-path = "../libcoretest/lib.rs"
+name = "coretests"
+path = "../libcore/tests/lib.rs"
 
 [[bench]]
 name = "corebenches"
diff --git a/src/libcore/any.rs b/src/libcore/any.rs
index b8a4174766a..338e5c7fd95 100644
--- a/src/libcore/any.rs
+++ b/src/libcore/any.rs
@@ -137,7 +137,7 @@ impl fmt::Debug for Any + Send {
 }
 
 impl Any {
-    /// Returns true if the boxed type is the same as `T`.
+    /// Returns `true` if the boxed type is the same as `T`.
     ///
     /// # Examples
     ///
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 736797d162b..0186d972782 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -394,7 +394,6 @@ impl<T> Cell<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(move_cell)]
     /// use std::cell::Cell;
     ///
     /// let c1 = Cell::new(5i32);
@@ -404,7 +403,7 @@ impl<T> Cell<T> {
     /// assert_eq!(5, c2.get());
     /// ```
     #[inline]
-    #[unstable(feature = "move_cell", issue = "39264")]
+    #[stable(feature = "move_cell", since = "1.17.0")]
     pub fn swap(&self, other: &Self) {
         if ptr::eq(self, other) {
             return;
@@ -419,7 +418,6 @@ impl<T> Cell<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(move_cell)]
     /// use std::cell::Cell;
     ///
     /// let c = Cell::new(5);
@@ -427,7 +425,7 @@ impl<T> Cell<T> {
     ///
     /// assert_eq!(5, old);
     /// ```
-    #[unstable(feature = "move_cell", issue = "39264")]
+    #[stable(feature = "move_cell", since = "1.17.0")]
     pub fn replace(&self, val: T) -> T {
         mem::replace(unsafe { &mut *self.value.get() }, val)
     }
@@ -437,7 +435,6 @@ impl<T> Cell<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(move_cell)]
     /// use std::cell::Cell;
     ///
     /// let c = Cell::new(5);
@@ -445,7 +442,7 @@ impl<T> Cell<T> {
     ///
     /// assert_eq!(five, 5);
     /// ```
-    #[unstable(feature = "move_cell", issue = "39264")]
+    #[stable(feature = "move_cell", since = "1.17.0")]
     pub fn into_inner(self) -> T {
         unsafe { self.value.into_inner() }
     }
@@ -457,7 +454,6 @@ impl<T: Default> Cell<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(move_cell)]
     /// use std::cell::Cell;
     ///
     /// let c = Cell::new(5);
@@ -466,7 +462,7 @@ impl<T: Default> Cell<T> {
     /// assert_eq!(five, 5);
     /// assert_eq!(c.into_inner(), 0);
     /// ```
-    #[unstable(feature = "move_cell", issue = "39264")]
+    #[stable(feature = "move_cell", since = "1.17.0")]
     pub fn take(&self) -> T {
         self.replace(Default::default())
     }
diff --git a/src/libcore/char.rs b/src/libcore/char.rs
index 78764091cf0..b27c801cf89 100644
--- a/src/libcore/char.rs
+++ b/src/libcore/char.rs
@@ -94,12 +94,12 @@ pub const MAX: char = '\u{10ffff}';
 ///
 /// [`char`]: ../../std/primitive.char.html
 /// [`u32`]: ../../std/primitive.u32.html
-/// [`as`]: ../../book/casting-between-types.html#as
+/// [`as`]: ../../book/first-edition/casting-between-types.html#as
 ///
 /// For an unsafe version of this function which ignores these checks, see
-/// [`from_u32_unchecked()`].
+/// [`from_u32_unchecked`].
 ///
-/// [`from_u32_unchecked()`]: fn.from_u32_unchecked.html
+/// [`from_u32_unchecked`]: fn.from_u32_unchecked.html
 ///
 /// # Examples
 ///
@@ -146,15 +146,15 @@ pub fn from_u32(i: u32) -> Option<char> {
 ///
 /// [`char`]: ../../std/primitive.char.html
 /// [`u32`]: ../../std/primitive.u32.html
-/// [`as`]: ../../book/casting-between-types.html#as
+/// [`as`]: ../../book/first-edition/casting-between-types.html#as
 ///
 /// # Safety
 ///
 /// This function is unsafe, as it may construct invalid `char` values.
 ///
-/// For a safe version of this function, see the [`from_u32()`] function.
+/// For a safe version of this function, see the [`from_u32`] function.
 ///
-/// [`from_u32()`]: fn.from_u32.html
+/// [`from_u32`]: fn.from_u32.html
 ///
 /// # Examples
 ///
@@ -187,7 +187,7 @@ impl From<char> for u32 {
 /// with the character encoding that IANA calls ISO-8859-1.
 /// This encoding is compatible with ASCII.
 ///
-/// Note that this is different from ISO/IEC 8859-1 a.k.a. ISO 8859-1 (with one less hypen),
+/// Note that this is different from ISO/IEC 8859-1 a.k.a. ISO 8859-1 (with one less hyphen),
 /// which leaves some "blanks", byte values that are not assigned to any character.
 /// ISO-8859-1 (the IANA one) assigns them to the C0 and C1 control codes.
 ///
@@ -209,10 +209,10 @@ impl From<u8> for char {
 
 #[unstable(feature = "try_from", issue = "33417")]
 impl TryFrom<u32> for char {
-    type Err = CharTryFromError;
+    type Error = CharTryFromError;
 
     #[inline]
-    fn try_from(i: u32) -> Result<Self, Self::Err> {
+    fn try_from(i: u32) -> Result<Self, Self::Error> {
         if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
             Err(CharTryFromError(()))
         } else {
@@ -479,10 +479,10 @@ impl CharExt for char {
 /// Returns an iterator that yields the hexadecimal Unicode escape of a
 /// character, as `char`s.
 ///
-/// This `struct` is created by the [`escape_unicode()`] method on [`char`]. See
+/// This `struct` is created by the [`escape_unicode`] method on [`char`]. See
 /// its documentation for more.
 ///
-/// [`escape_unicode()`]: ../../std/primitive.char.html#method.escape_unicode
+/// [`escape_unicode`]: ../../std/primitive.char.html#method.escape_unicode
 /// [`char`]: ../../std/primitive.char.html
 #[derive(Clone, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -600,10 +600,10 @@ impl fmt::Display for EscapeUnicode {
 
 /// An iterator that yields the literal escape code of a `char`.
 ///
-/// This `struct` is created by the [`escape_default()`] method on [`char`]. See
+/// This `struct` is created by the [`escape_default`] method on [`char`]. See
 /// its documentation for more.
 ///
-/// [`escape_default()`]: ../../std/primitive.char.html#method.escape_default
+/// [`escape_default`]: ../../std/primitive.char.html#method.escape_default
 /// [`char`]: ../../std/primitive.char.html
 #[derive(Clone, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -713,10 +713,10 @@ impl fmt::Display for EscapeDefault {
 
 /// An iterator that yields the literal escape code of a `char`.
 ///
-/// This `struct` is created by the [`escape_debug()`] method on [`char`]. See its
+/// This `struct` is created by the [`escape_debug`] method on [`char`]. See its
 /// documentation for more.
 ///
-/// [`escape_debug()`]: ../../std/primitive.char.html#method.escape_debug
+/// [`escape_debug`]: ../../std/primitive.char.html#method.escape_debug
 /// [`char`]: ../../std/primitive.char.html
 #[unstable(feature = "char_escape_debug", issue = "35068")]
 #[derive(Clone, Debug)]
diff --git a/src/libcore/char_private.rs b/src/libcore/char_private.rs
index ddc473592a2..2c0f449b276 100644
--- a/src/libcore/char_private.rs
+++ b/src/libcore/char_private.rs
@@ -11,38 +11,49 @@
 // NOTE: The following code was generated by "src/etc/char_private.py",
 //       do not edit directly!
 
-use slice::SliceExt;
-
-fn check(x: u16, singletons: &[u16], normal: &[u16]) -> bool {
-    for &s in singletons {
-        if x == s {
-            return false;
-        } else if x < s {
+fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8],
+         normal: &[u8]) -> bool {
+    let xupper = (x >> 8) as u8;
+    let mut lowerstart = 0;
+    for &(upper, lowercount) in singletonuppers {
+        let lowerend = lowerstart + lowercount as usize;
+        if xupper == upper {
+            for &lower in &singletonlowers[lowerstart..lowerend] {
+                if lower == x as u8 {
+                    return false;
+                }
+            }
+        } else if xupper < upper {
             break;
         }
+        lowerstart = lowerend;
     }
-    for w in normal.chunks(2) {
-        let start = w[0];
-        let len = w[1];
-        let difference = (x as i32) - (start as i32);
-        if 0 <= difference {
-            if difference < len as i32 {
-                return false;
-            }
+
+    let mut x = x as i32;
+    let mut normal = normal.iter().cloned();
+    let mut current = true;
+    while let Some(v) = normal.next() {
+        let len = if v & 0x80 != 0 {
+            ((v & 0x7f) as i32) << 8 | normal.next().unwrap() as i32
         } else {
+            v as i32
+        };
+        x -= len;
+        if x < 0 {
             break;
         }
+        current = !current;
     }
-    true
+    current
 }
 
 pub fn is_printable(x: char) -> bool {
     let x = x as u32;
     let lower = x as u16;
     if x < 0x10000 {
-        check(lower, SINGLETONS0, NORMAL0)
+        check(lower, SINGLETONS0U, SINGLETONS0L, NORMAL0)
     } else if x < 0x20000 {
-        check(lower, SINGLETONS1, NORMAL1)
+        check(lower, SINGLETONS1U, SINGLETONS1L, NORMAL1)
     } else {
         if 0x2a6d7 <= x && x < 0x2a700 {
             return false;
@@ -66,761 +77,446 @@ pub fn is_printable(x: char) -> bool {
     }
 }
 
-const SINGLETONS0: &'static [u16] = &[
-    0xad,
-    0x378,
-    0x379,
-    0x38b,
-    0x38d,
-    0x3a2,
-    0x530,
-    0x557,
-    0x558,
-    0x560,
-    0x588,
-    0x58b,
-    0x58c,
-    0x590,
-    0x61c,
-    0x61d,
-    0x6dd,
-    0x70e,
-    0x70f,
-    0x74b,
-    0x74c,
-    0x82e,
-    0x82f,
-    0x83f,
-    0x85c,
-    0x85d,
-    0x8b5,
-    0x8e2,
-    0x984,
-    0x98d,
-    0x98e,
-    0x991,
-    0x992,
-    0x9a9,
-    0x9b1,
-    0x9ba,
-    0x9bb,
-    0x9c5,
-    0x9c6,
-    0x9c9,
-    0x9ca,
-    0x9de,
-    0x9e4,
-    0x9e5,
-    0xa04,
-    0xa11,
-    0xa12,
-    0xa29,
-    0xa31,
-    0xa34,
-    0xa37,
-    0xa3a,
-    0xa3b,
-    0xa3d,
-    0xa49,
-    0xa4a,
-    0xa5d,
-    0xa84,
-    0xa8e,
-    0xa92,
-    0xaa9,
-    0xab1,
-    0xab4,
-    0xaba,
-    0xabb,
-    0xac6,
-    0xaca,
-    0xace,
-    0xacf,
-    0xae4,
-    0xae5,
-    0xb04,
-    0xb0d,
-    0xb0e,
-    0xb11,
-    0xb12,
-    0xb29,
-    0xb31,
-    0xb34,
-    0xb3a,
-    0xb3b,
-    0xb45,
-    0xb46,
-    0xb49,
-    0xb4a,
-    0xb5e,
-    0xb64,
-    0xb65,
-    0xb84,
-    0xb91,
-    0xb9b,
-    0xb9d,
-    0xbc9,
-    0xbce,
-    0xbcf,
-    0xc04,
-    0xc0d,
-    0xc11,
-    0xc29,
-    0xc45,
-    0xc49,
-    0xc57,
-    0xc64,
-    0xc65,
-    0xc84,
-    0xc8d,
-    0xc91,
-    0xca9,
-    0xcb4,
-    0xcba,
-    0xcbb,
-    0xcc5,
-    0xcc9,
-    0xcdf,
-    0xce4,
-    0xce5,
-    0xcf0,
-    0xd04,
-    0xd0d,
-    0xd11,
-    0xd3b,
-    0xd3c,
-    0xd45,
-    0xd49,
-    0xd64,
-    0xd65,
-    0xd80,
-    0xd81,
-    0xd84,
-    0xdb2,
-    0xdbc,
-    0xdbe,
-    0xdbf,
-    0xdd5,
-    0xdd7,
-    0xdf0,
-    0xdf1,
-    0xe83,
-    0xe85,
-    0xe86,
-    0xe89,
-    0xe8b,
-    0xe8c,
-    0xe98,
-    0xea0,
-    0xea4,
-    0xea6,
-    0xea8,
-    0xea9,
-    0xeac,
-    0xeba,
-    0xebe,
-    0xebf,
-    0xec5,
-    0xec7,
-    0xece,
-    0xecf,
-    0xeda,
-    0xedb,
-    0xf48,
-    0xf98,
-    0xfbd,
-    0xfcd,
-    0x10c6,
-    0x10ce,
-    0x10cf,
-    0x1249,
-    0x124e,
-    0x124f,
-    0x1257,
-    0x1259,
-    0x125e,
-    0x125f,
-    0x1289,
-    0x128e,
-    0x128f,
-    0x12b1,
-    0x12b6,
-    0x12b7,
-    0x12bf,
-    0x12c1,
-    0x12c6,
-    0x12c7,
-    0x12d7,
-    0x1311,
-    0x1316,
-    0x1317,
-    0x135b,
-    0x135c,
-    0x13f6,
-    0x13f7,
-    0x13fe,
-    0x13ff,
-    0x1680,
-    0x170d,
-    0x176d,
-    0x1771,
-    0x17de,
-    0x17df,
-    0x180e,
-    0x180f,
-    0x191f,
-    0x196e,
-    0x196f,
-    0x1a1c,
-    0x1a1d,
-    0x1a5f,
-    0x1a7d,
-    0x1a7e,
-    0x1aae,
-    0x1aaf,
-    0x1cf7,
-    0x1f16,
-    0x1f17,
-    0x1f1e,
-    0x1f1f,
-    0x1f46,
-    0x1f47,
-    0x1f4e,
-    0x1f4f,
-    0x1f58,
-    0x1f5a,
-    0x1f5c,
-    0x1f5e,
-    0x1f7e,
-    0x1f7f,
-    0x1fb5,
-    0x1fc5,
-    0x1fd4,
-    0x1fd5,
-    0x1fdc,
-    0x1ff0,
-    0x1ff1,
-    0x1ff5,
-    0x2072,
-    0x2073,
-    0x208f,
-    0x23ff,
-    0x2b74,
-    0x2b75,
-    0x2b96,
-    0x2b97,
-    0x2bc9,
-    0x2c2f,
-    0x2c5f,
-    0x2d26,
-    0x2d2e,
-    0x2d2f,
-    0x2da7,
-    0x2daf,
-    0x2db7,
-    0x2dbf,
-    0x2dc7,
-    0x2dcf,
-    0x2dd7,
-    0x2ddf,
-    0x2e9a,
-    0x3040,
-    0x3097,
-    0x3098,
-    0x318f,
-    0x321f,
-    0x32ff,
-    0xa7af,
-    0xa8fe,
-    0xa8ff,
-    0xa9ce,
-    0xa9ff,
-    0xaa4e,
-    0xaa4f,
-    0xaa5a,
-    0xaa5b,
-    0xab07,
-    0xab08,
-    0xab0f,
-    0xab10,
-    0xab27,
-    0xab2f,
-    0xabee,
-    0xabef,
-    0xfa6e,
-    0xfa6f,
-    0xfb37,
-    0xfb3d,
-    0xfb3f,
-    0xfb42,
-    0xfb45,
-    0xfd90,
-    0xfd91,
-    0xfdfe,
-    0xfdff,
-    0xfe53,
-    0xfe67,
-    0xfe75,
-    0xffc8,
-    0xffc9,
-    0xffd0,
-    0xffd1,
-    0xffd8,
-    0xffd9,
-    0xffe7,
-    0xfffe,
-    0xffff,
+const SINGLETONS0U: &'static [(u8, u8)] = &[
+    (0x00, 1),
+    (0x03, 5),
+    (0x05, 8),
+    (0x06, 3),
+    (0x07, 4),
+    (0x08, 7),
+    (0x09, 16),
+    (0x0a, 27),
+    (0x0b, 24),
+    (0x0c, 22),
+    (0x0d, 20),
+    (0x0e, 22),
+    (0x0f, 4),
+    (0x10, 3),
+    (0x12, 18),
+    (0x13, 9),
+    (0x16, 1),
+    (0x17, 5),
+    (0x18, 2),
+    (0x19, 3),
+    (0x1a, 7),
+    (0x1c, 1),
+    (0x1f, 22),
+    (0x20, 3),
+    (0x23, 1),
+    (0x2b, 5),
+    (0x2c, 2),
+    (0x2d, 11),
+    (0x2e, 1),
+    (0x30, 3),
+    (0x31, 1),
+    (0x32, 2),
+    (0xa7, 1),
+    (0xa8, 2),
+    (0xa9, 2),
+    (0xaa, 4),
+    (0xab, 8),
+    (0xfa, 2),
+    (0xfb, 5),
+    (0xfd, 4),
+    (0xfe, 3),
+    (0xff, 9),
 ];
-const SINGLETONS1: &'static [u16] = &[
-    0xc,
-    0x27,
-    0x3b,
-    0x3e,
-    0x4e,
-    0x4f,
-    0x18f,
-    0x39e,
-    0x49e,
-    0x49f,
-    0x806,
-    0x807,
-    0x809,
-    0x836,
-    0x83d,
-    0x83e,
-    0x856,
-    0x8f3,
-    0x9d0,
-    0x9d1,
-    0xa04,
-    0xa14,
-    0xa18,
-    0xb56,
-    0xb57,
-    0x10bd,
-    0x1135,
-    0x11ce,
-    0x11cf,
-    0x11e0,
-    0x1212,
-    0x1287,
-    0x1289,
-    0x128e,
-    0x129e,
-    0x1304,
-    0x130d,
-    0x130e,
-    0x1311,
-    0x1312,
-    0x1329,
-    0x1331,
-    0x1334,
-    0x133a,
-    0x133b,
-    0x1345,
-    0x1346,
-    0x1349,
-    0x134a,
-    0x134e,
-    0x134f,
-    0x1364,
-    0x1365,
-    0x145a,
-    0x145c,
-    0x15b6,
-    0x15b7,
-    0x1c09,
-    0x1c37,
-    0x1c90,
-    0x1c91,
-    0x1ca8,
-    0x246f,
-    0x6a5f,
-    0x6aee,
-    0x6aef,
-    0x6b5a,
-    0x6b62,
-    0xbc9a,
-    0xbc9b,
-    0xd127,
-    0xd128,
-    0xd455,
-    0xd49d,
-    0xd4a0,
-    0xd4a1,
-    0xd4a3,
-    0xd4a4,
-    0xd4a7,
-    0xd4a8,
-    0xd4ad,
-    0xd4ba,
-    0xd4bc,
-    0xd4c4,
-    0xd506,
-    0xd50b,
-    0xd50c,
-    0xd515,
-    0xd51d,
-    0xd53a,
-    0xd53f,
-    0xd545,
-    0xd551,
-    0xd6a6,
-    0xd6a7,
-    0xd7cc,
-    0xd7cd,
-    0xdaa0,
-    0xe007,
-    0xe019,
-    0xe01a,
-    0xe022,
-    0xe025,
-    0xe8c5,
-    0xe8c6,
-    0xee04,
-    0xee20,
-    0xee23,
-    0xee25,
-    0xee26,
-    0xee28,
-    0xee33,
-    0xee38,
-    0xee3a,
-    0xee48,
-    0xee4a,
-    0xee4c,
-    0xee50,
-    0xee53,
-    0xee55,
-    0xee56,
-    0xee58,
-    0xee5a,
-    0xee5c,
-    0xee5e,
-    0xee60,
-    0xee63,
-    0xee65,
-    0xee66,
-    0xee6b,
-    0xee73,
-    0xee78,
-    0xee7d,
-    0xee7f,
-    0xee8a,
-    0xeea4,
-    0xeeaa,
-    0xf0af,
-    0xf0b0,
-    0xf0c0,
-    0xf0d0,
-    0xf12f,
-    0xf91f,
-    0xf931,
-    0xf932,
-    0xf93f,
+const SINGLETONS0L: &'static [u8] = &[
+    0xad, 0x78, 0x79, 0x8b, 0x8d, 0xa2, 0x30, 0x57,
+    0x58, 0x60, 0x88, 0x8b, 0x8c, 0x90, 0x1c, 0x1d,
+    0xdd, 0x0e, 0x0f, 0x4b, 0x4c, 0x2e, 0x2f, 0x3f,
+    0x5c, 0x5d, 0xb5, 0xe2, 0x84, 0x8d, 0x8e, 0x91,
+    0x92, 0xa9, 0xb1, 0xba, 0xbb, 0xc5, 0xc6, 0xc9,
+    0xca, 0xde, 0xe4, 0xe5, 0x04, 0x11, 0x12, 0x29,
+    0x31, 0x34, 0x37, 0x3a, 0x3b, 0x3d, 0x49, 0x4a,
+    0x5d, 0x84, 0x8e, 0x92, 0xa9, 0xb1, 0xb4, 0xba,
+    0xbb, 0xc6, 0xca, 0xce, 0xcf, 0xe4, 0xe5, 0x04,
+    0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a,
+    0x3b, 0x45, 0x46, 0x49, 0x4a, 0x5e, 0x64, 0x65,
+    0x84, 0x91, 0x9b, 0x9d, 0xc9, 0xce, 0xcf, 0x04,
+    0x0d, 0x11, 0x29, 0x45, 0x49, 0x57, 0x64, 0x65,
+    0x84, 0x8d, 0x91, 0xa9, 0xb4, 0xba, 0xbb, 0xc5,
+    0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x04, 0x0d, 0x11,
+    0x3b, 0x3c, 0x45, 0x49, 0x64, 0x65, 0x80, 0x81,
+    0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5, 0xd7, 0xf0,
+    0xf1, 0x83, 0x85, 0x86, 0x89, 0x8b, 0x8c, 0x98,
+    0xa0, 0xa4, 0xa6, 0xa8, 0xa9, 0xac, 0xba, 0xbe,
+    0xbf, 0xc5, 0xc7, 0xce, 0xcf, 0xda, 0xdb, 0x48,
+    0x98, 0xbd, 0xcd, 0xc6, 0xce, 0xcf, 0x49, 0x4e,
+    0x4f, 0x57, 0x59, 0x5e, 0x5f, 0x89, 0x8e, 0x8f,
+    0xb1, 0xb6, 0xb7, 0xbf, 0xc1, 0xc6, 0xc7, 0xd7,
+    0x11, 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7, 0xfe,
+    0xff, 0x80, 0x0d, 0x6d, 0x71, 0xde, 0xdf, 0x0e,
+    0x0f, 0x1f, 0x6e, 0x6f, 0x1c, 0x1d, 0x5f, 0x7d,
+    0x7e, 0xae, 0xaf, 0xf7, 0x16, 0x17, 0x1e, 0x1f,
+    0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e,
+    0x7e, 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0,
+    0xf1, 0xf5, 0x72, 0x73, 0x8f, 0xff, 0x74, 0x75,
+    0x96, 0x97, 0xc9, 0x2f, 0x5f, 0x26, 0x2e, 0x2f,
+    0xa7, 0xaf, 0xb7, 0xbf, 0xc7, 0xcf, 0xd7, 0xdf,
+    0x9a, 0x40, 0x97, 0x98, 0x8f, 0x1f, 0xff, 0xaf,
+    0xfe, 0xff, 0xce, 0xff, 0x4e, 0x4f, 0x5a, 0x5b,
+    0x07, 0x08, 0x0f, 0x10, 0x27, 0x2f, 0xee, 0xef,
+    0x6e, 0x6f, 0x37, 0x3d, 0x3f, 0x42, 0x45, 0x90,
+    0x91, 0xfe, 0xff, 0x53, 0x67, 0x75, 0xc8, 0xc9,
+    0xd0, 0xd1, 0xd8, 0xd9, 0xe7, 0xfe, 0xff,
 ];
-const NORMAL0: &'static [u16] = &[
-    0x0, 0x20,
-    0x7f, 0x22,
-    0x380, 0x4,
-    0x5c8, 0x8,
-    0x5eb, 0x5,
-    0x5f5, 0x11,
-    0x7b2, 0xe,
-    0x7fb, 0x5,
-    0x85f, 0x41,
-    0x8be, 0x16,
-    0x9b3, 0x3,
-    0x9cf, 0x8,
-    0x9d8, 0x4,
-    0x9fc, 0x5,
-    0xa0b, 0x4,
-    0xa43, 0x4,
-    0xa4e, 0x3,
-    0xa52, 0x7,
-    0xa5f, 0x7,
-    0xa76, 0xb,
-    0xad1, 0xf,
-    0xaf2, 0x7,
-    0xafa, 0x7,
-    0xb4e, 0x8,
-    0xb58, 0x4,
-    0xb78, 0xa,
-    0xb8b, 0x3,
-    0xb96, 0x3,
-    0xba0, 0x3,
-    0xba5, 0x3,
-    0xbab, 0x3,
-    0xbba, 0x4,
-    0xbc3, 0x3,
-    0xbd1, 0x6,
-    0xbd8, 0xe,
-    0xbfb, 0x5,
-    0xc3a, 0x3,
-    0xc4e, 0x7,
-    0xc5b, 0x5,
-    0xc70, 0x8,
-    0xcce, 0x7,
-    0xcd7, 0x7,
-    0xcf3, 0xe,
-    0xd50, 0x4,
-    0xd97, 0x3,
-    0xdc7, 0x3,
-    0xdcb, 0x4,
-    0xde0, 0x6,
-    0xdf5, 0xc,
-    0xe3b, 0x4,
-    0xe5c, 0x25,
-    0xe8e, 0x6,
-    0xee0, 0x20,
-    0xf6d, 0x4,
-    0xfdb, 0x25,
-    0x10c8, 0x5,
-    0x137d, 0x3,
-    0x139a, 0x6,
-    0x169d, 0x3,
-    0x16f9, 0x7,
-    0x1715, 0xb,
-    0x1737, 0x9,
-    0x1754, 0xc,
-    0x1774, 0xc,
-    0x17ea, 0x6,
-    0x17fa, 0x6,
-    0x181a, 0x6,
-    0x1878, 0x8,
-    0x18ab, 0x5,
-    0x18f6, 0xa,
-    0x192c, 0x4,
-    0x193c, 0x4,
-    0x1941, 0x3,
-    0x1975, 0xb,
-    0x19ac, 0x4,
-    0x19ca, 0x6,
-    0x19db, 0x3,
-    0x1a8a, 0x6,
-    0x1a9a, 0x6,
-    0x1abf, 0x41,
-    0x1b4c, 0x4,
-    0x1b7d, 0x3,
-    0x1bf4, 0x8,
-    0x1c38, 0x3,
-    0x1c4a, 0x3,
-    0x1c89, 0x37,
-    0x1cc8, 0x8,
-    0x1cfa, 0x6,
-    0x1df6, 0x5,
-    0x1fff, 0x11,
-    0x2028, 0x8,
-    0x205f, 0x11,
-    0x209d, 0x3,
-    0x20bf, 0x11,
-    0x20f1, 0xf,
-    0x218c, 0x4,
-    0x2427, 0x19,
-    0x244b, 0x15,
-    0x2bba, 0x3,
-    0x2bd2, 0x1a,
-    0x2bf0, 0x10,
-    0x2cf4, 0x5,
-    0x2d28, 0x5,
-    0x2d68, 0x7,
-    0x2d71, 0xe,
-    0x2d97, 0x9,
-    0x2e45, 0x3b,
-    0x2ef4, 0xc,
-    0x2fd6, 0x1a,
-    0x2ffc, 0x5,
-    0x3100, 0x5,
-    0x312e, 0x3,
-    0x31bb, 0x5,
-    0x31e4, 0xc,
-    0x4db6, 0xa,
-    0x9fd6, 0x2a,
-    0xa48d, 0x3,
-    0xa4c7, 0x9,
-    0xa62c, 0x14,
-    0xa6f8, 0x8,
-    0xa7b8, 0x3f,
-    0xa82c, 0x4,
-    0xa83a, 0x6,
-    0xa878, 0x8,
-    0xa8c6, 0x8,
-    0xa8da, 0x6,
-    0xa954, 0xb,
-    0xa97d, 0x3,
-    0xa9da, 0x4,
-    0xaa37, 0x9,
-    0xaac3, 0x18,
-    0xaaf7, 0xa,
-    0xab17, 0x9,
-    0xab66, 0xa,
-    0xabfa, 0x6,
-    0xd7a4, 0xc,
-    0xd7c7, 0x4,
-    0xd7fc, 0x2104,
-    0xfada, 0x26,
-    0xfb07, 0xc,
-    0xfb18, 0x5,
-    0xfbc2, 0x11,
-    0xfd40, 0x10,
-    0xfdc8, 0x28,
-    0xfe1a, 0x6,
-    0xfe6c, 0x4,
-    0xfefd, 0x4,
-    0xffbf, 0x3,
-    0xffdd, 0x3,
-    0xffef, 0xd,
+const SINGLETONS1U: &'static [(u8, u8)] = &[
+    (0x00, 6),
+    (0x01, 1),
+    (0x03, 1),
+    (0x04, 2),
+    (0x08, 8),
+    (0x09, 2),
+    (0x0a, 3),
+    (0x0b, 2),
+    (0x10, 1),
+    (0x11, 4),
+    (0x12, 5),
+    (0x13, 18),
+    (0x14, 2),
+    (0x15, 2),
+    (0x1c, 5),
+    (0x24, 1),
+    (0x6a, 3),
+    (0x6b, 2),
+    (0xbc, 2),
+    (0xd1, 2),
+    (0xd4, 12),
+    (0xd5, 9),
+    (0xd6, 2),
+    (0xd7, 2),
+    (0xda, 1),
+    (0xe0, 5),
+    (0xe8, 2),
+    (0xee, 32),
+    (0xf0, 4),
+    (0xf1, 1),
+    (0xf9, 4),
 ];
-const NORMAL1: &'static [u16] = &[
+const SINGLETONS1L: &'static [u8] = &[
+    0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e,
+    0x9e, 0x9f, 0x06, 0x07, 0x09, 0x36, 0x3d, 0x3e,
+    0x56, 0xf3, 0xd0, 0xd1, 0x04, 0x14, 0x18, 0x56,
+    0x57, 0xbd, 0x35, 0xce, 0xcf, 0xe0, 0x12, 0x87,
+    0x89, 0x8e, 0x9e, 0x04, 0x0d, 0x0e, 0x11, 0x12,
+    0x29, 0x31, 0x34, 0x3a, 0x3b, 0x45, 0x46, 0x49,
+    0x4a, 0x4e, 0x4f, 0x64, 0x65, 0x5a, 0x5c, 0xb6,
+    0xb7, 0x09, 0x37, 0x90, 0x91, 0xa8, 0x6f, 0x5f,
+    0xee, 0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27, 0x28,
+    0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8,
+    0xad, 0xba, 0xbc, 0xc4, 0x06, 0x0b, 0x0c, 0x15,
+    0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7, 0xcc,
+    0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0xc5,
+    0xc6, 0x04, 0x20, 0x23, 0x25, 0x26, 0x28, 0x33,
+    0x38, 0x3a, 0x48, 0x4a, 0x4c, 0x50, 0x53, 0x55,
+    0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, 0x65,
+    0x66, 0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, 0xa4,
+    0xaa, 0xaf, 0xb0, 0xc0, 0xd0, 0x2f, 0x1f, 0x31,
+    0x32, 0x3f,
+];
+const NORMAL0: &'static [u8] = &[
+    0x00, 0x20,
+    0x5f, 0x22,
+    0x82, 0xdf, 0x04,
+    0x82, 0x44, 0x08,
+    0x1b, 0x05,
+    0x05, 0x11,
+    0x81, 0xac, 0x0e,
+    0x3b, 0x05,
+    0x5f, 0x41,
+    0x1e, 0x16,
+    0x80, 0xdf, 0x03,
+    0x19, 0x08,
+    0x01, 0x04,
+    0x20, 0x05,
+    0x0a, 0x04,
+    0x34, 0x04,
+    0x07, 0x03,
+    0x01, 0x07,
+    0x06, 0x07,
+    0x10, 0x0b,
+    0x50, 0x0f,
+    0x12, 0x07,
+    0x01, 0x07,
+    0x4d, 0x08,
+    0x02, 0x04,
+    0x1c, 0x0a,
+    0x09, 0x03,
+    0x08, 0x03,
+    0x07, 0x03,
+    0x02, 0x03,
+    0x03, 0x03,
+    0x0c, 0x04,
+    0x05, 0x03,
+    0x0b, 0x06,
+    0x01, 0x0e,
+    0x15, 0x05,
+    0x3a, 0x03,
+    0x11, 0x07,
+    0x06, 0x05,
+    0x10, 0x08,
+    0x56, 0x07,
+    0x02, 0x07,
+    0x15, 0x0e,
+    0x4f, 0x04,
+    0x43, 0x03,
+    0x2d, 0x03,
+    0x01, 0x04,
+    0x11, 0x06,
+    0x0f, 0x0c,
+    0x3a, 0x04,
+    0x1d, 0x25,
+    0x0d, 0x06,
+    0x4c, 0x20,
+    0x6d, 0x04,
+    0x6a, 0x25,
+    0x80, 0xc8, 0x05,
+    0x82, 0xb0, 0x03,
+    0x1a, 0x06,
+    0x82, 0xfd, 0x03,
+    0x59, 0x07,
+    0x15, 0x0b,
+    0x17, 0x09,
+    0x14, 0x0c,
+    0x14, 0x0c,
+    0x6a, 0x06,
+    0x0a, 0x06,
+    0x1a, 0x06,
+    0x58, 0x08,
+    0x2b, 0x05,
+    0x46, 0x0a,
+    0x2c, 0x04,
+    0x0c, 0x04,
+    0x01, 0x03,
+    0x31, 0x0b,
+    0x2c, 0x04,
+    0x1a, 0x06,
+    0x0b, 0x03,
+    0x80, 0xac, 0x06,
+    0x0a, 0x06,
+    0x1f, 0x41,
+    0x4c, 0x04,
+    0x2d, 0x03,
+    0x74, 0x08,
+    0x3c, 0x03,
+    0x0f, 0x03,
+    0x3c, 0x37,
+    0x08, 0x08,
+    0x2a, 0x06,
+    0x80, 0xf6, 0x05,
+    0x82, 0x04, 0x11,
+    0x18, 0x08,
+    0x2f, 0x11,
+    0x2d, 0x03,
+    0x1f, 0x11,
+    0x21, 0x0f,
+    0x80, 0x8c, 0x04,
+    0x82, 0x97, 0x19,
+    0x0b, 0x15,
+    0x87, 0x5a, 0x03,
+    0x15, 0x1a,
+    0x04, 0x10,
+    0x80, 0xf4, 0x05,
+    0x2f, 0x05,
+    0x3b, 0x07,
+    0x02, 0x0e,
+    0x18, 0x09,
+    0x80, 0xa5, 0x3b,
+    0x74, 0x0c,
+    0x80, 0xd6, 0x1a,
+    0x0c, 0x05,
+    0x80, 0xff, 0x05,
+    0x29, 0x03,
+    0x80, 0x8a, 0x05,
+    0x24, 0x0c,
+    0x9b, 0xc6, 0x0a,
+    0xd2, 0x16, 0x2a,
+    0x84, 0x8d, 0x03,
+    0x37, 0x09,
+    0x81, 0x5c, 0x14,
+    0x80, 0xb8, 0x08,
+    0x80, 0xb8, 0x3f,
+    0x35, 0x04,
+    0x0a, 0x06,
+    0x38, 0x08,
+    0x46, 0x08,
+    0x0c, 0x06,
+    0x74, 0x0b,
+    0x1e, 0x03,
+    0x5a, 0x04,
+    0x59, 0x09,
+    0x80, 0x83, 0x18,
+    0x1c, 0x0a,
+    0x16, 0x09,
+    0x46, 0x0a,
+    0x80, 0x8a, 0x06,
+    0xab, 0xa4, 0x0c,
+    0x17, 0x04,
+    0x31, 0xa1, 0x04,
+    0x81, 0xda, 0x26,
+    0x07, 0x0c,
+    0x05, 0x05,
+    0x80, 0xa5, 0x11,
+    0x81, 0x6d, 0x10,
+    0x78, 0x28,
+    0x2a, 0x06,
+    0x4c, 0x04,
+    0x80, 0x8d, 0x04,
+    0x80, 0xbe, 0x03,
+    0x1b, 0x03,
+    0x0f, 0x0d,
+];
+const NORMAL1: &'static [u8] = &[
+    0x5e, 0x22,
+    0x7b, 0x05,
+    0x03, 0x04,
+    0x2d, 0x03,
+    0x65, 0x04,
+    0x01, 0x2f,
+    0x2e, 0x80, 0x82,
+    0x1d, 0x03,
+    0x31, 0x0f,
+    0x1c, 0x04,
+    0x24, 0x0c,
+    0x1b, 0x05,
+    0x2b, 0x05,
+    0x44, 0x04,
+    0x0e, 0x2a,
+    0x80, 0xaa, 0x06,
+    0x24, 0x04,
+    0x24, 0x04,
+    0x28, 0x08,
+    0x34, 0x0b,
+    0x01, 0x80, 0x90,
+    0x81, 0x37, 0x09,
+    0x16, 0x0a,
+    0x08, 0x80, 0x98,
+    0x39, 0x03,
+    0x63, 0x08,
+    0x09, 0x30,
+    0x16, 0x05,
+    0x21, 0x03,
+    0x1b, 0x05,
+    0x01, 0x40,
+    0x38, 0x04,
+    0x4b, 0x05,
+    0x28, 0x04,
+    0x03, 0x04,
+    0x09, 0x08,
+    0x09, 0x07,
+    0x40, 0x20,
+    0x27, 0x04,
+    0x0c, 0x09,
+    0x36, 0x03,
+    0x3a, 0x05,
+    0x1a, 0x07,
+    0x04, 0x0c,
+    0x07, 0x50,
+    0x49, 0x37,
+    0x33, 0x0d,
+    0x33, 0x07,
+    0x06, 0x81, 0x60,
+    0x1f, 0x81, 0x81,
+    0x4e, 0x04,
+    0x1e, 0x0f,
+    0x43, 0x0e,
+    0x19, 0x07,
+    0x0a, 0x06,
+    0x44, 0x0c,
+    0x27, 0x09,
+    0x75, 0x0b,
+    0x3f, 0x41,
+    0x2a, 0x06,
+    0x3b, 0x05,
+    0x0a, 0x06,
+    0x51, 0x06,
+    0x01, 0x05,
+    0x10, 0x03,
+    0x05, 0x80, 0x8b,
+    0x5e, 0x22,
+    0x48, 0x08,
+    0x0a, 0x80, 0xa6,
     0x5e, 0x22,
-    0xfb, 0x5,
-    0x103, 0x4,
-    0x134, 0x3,
-    0x19c, 0x4,
-    0x1a1, 0x2f,
-    0x1fe, 0x82,
-    0x29d, 0x3,
-    0x2d1, 0xf,
-    0x2fc, 0x4,
-    0x324, 0xc,
-    0x34b, 0x5,
-    0x37b, 0x5,
-    0x3c4, 0x4,
-    0x3d6, 0x2a,
-    0x4aa, 0x6,
-    0x4d4, 0x4,
-    0x4fc, 0x4,
-    0x528, 0x8,
-    0x564, 0xb,
-    0x570, 0x90,
-    0x737, 0x9,
-    0x756, 0xa,
-    0x768, 0x98,
-    0x839, 0x3,
-    0x89f, 0x8,
-    0x8b0, 0x30,
-    0x8f6, 0x5,
-    0x91c, 0x3,
-    0x93a, 0x5,
-    0x940, 0x40,
-    0x9b8, 0x4,
-    0xa07, 0x5,
-    0xa34, 0x4,
-    0xa3b, 0x4,
-    0xa48, 0x8,
-    0xa59, 0x7,
-    0xaa0, 0x20,
-    0xae7, 0x4,
-    0xaf7, 0x9,
-    0xb36, 0x3,
-    0xb73, 0x5,
-    0xb92, 0x7,
-    0xb9d, 0xc,
-    0xbb0, 0x50,
-    0xc49, 0x37,
-    0xcb3, 0xd,
-    0xcf3, 0x7,
-    0xd00, 0x160,
-    0xe7f, 0x181,
-    0x104e, 0x4,
-    0x1070, 0xf,
-    0x10c2, 0xe,
-    0x10e9, 0x7,
-    0x10fa, 0x6,
-    0x1144, 0xc,
-    0x1177, 0x9,
-    0x11f5, 0xb,
-    0x123f, 0x41,
-    0x12aa, 0x6,
-    0x12eb, 0x5,
-    0x12fa, 0x6,
-    0x1351, 0x6,
-    0x1358, 0x5,
-    0x136d, 0x3,
-    0x1375, 0x8b,
-    0x145e, 0x22,
-    0x14c8, 0x8,
-    0x14da, 0xa6,
-    0x15de, 0x22,
-    0x1645, 0xb,
-    0x165a, 0x6,
-    0x166d, 0x13,
-    0x16b8, 0x8,
-    0x16ca, 0x36,
-    0x171a, 0x3,
-    0x172c, 0x4,
-    0x1740, 0x160,
-    0x18f3, 0xc,
-    0x1900, 0x1c0,
-    0x1af9, 0x107,
-    0x1c46, 0xa,
-    0x1c6d, 0x3,
-    0x1cb7, 0x349,
-    0x239a, 0x66,
-    0x2475, 0xb,
-    0x2544, 0xabc,
-    0x342f, 0xfd1,
-    0x4647, 0x21b9,
-    0x6a39, 0x7,
-    0x6a6a, 0x4,
-    0x6a70, 0x60,
-    0x6af6, 0xa,
-    0x6b46, 0xa,
-    0x6b78, 0x5,
-    0x6b90, 0x370,
-    0x6f45, 0xb,
-    0x6f7f, 0x10,
-    0x6fa0, 0x40,
-    0x6fe1, 0x1f,
-    0x87ed, 0x13,
-    0x8af3, 0x250d,
-    0xb002, 0xbfe,
-    0xbc6b, 0x5,
-    0xbc7d, 0x3,
-    0xbc89, 0x7,
-    0xbca0, 0x1360,
-    0xd0f6, 0xa,
-    0xd173, 0x8,
-    0xd1e9, 0x17,
-    0xd246, 0xba,
-    0xd357, 0x9,
-    0xd372, 0x8e,
-    0xd547, 0x3,
-    0xda8c, 0xf,
-    0xdab0, 0x550,
-    0xe02b, 0x7d5,
-    0xe8d7, 0x29,
-    0xe94b, 0x5,
-    0xe95a, 0x4,
-    0xe960, 0x4a0,
-    0xee3c, 0x6,
-    0xee43, 0x4,
-    0xee9c, 0x5,
-    0xeebc, 0x34,
-    0xeef2, 0x10e,
-    0xf02c, 0x4,
-    0xf094, 0xc,
-    0xf0f6, 0xa,
-    0xf10d, 0x3,
-    0xf16c, 0x4,
-    0xf1ad, 0x39,
-    0xf203, 0xd,
-    0xf23c, 0x4,
-    0xf249, 0x7,
-    0xf252, 0xae,
-    0xf6d3, 0xd,
-    0xf6ed, 0x3,
-    0xf6f7, 0x9,
-    0xf774, 0xc,
-    0xf7d5, 0x2b,
-    0xf80c, 0x4,
-    0xf848, 0x8,
-    0xf85a, 0x6,
-    0xf888, 0x8,
-    0xf8ae, 0x62,
-    0xf928, 0x8,
-    0xf94c, 0x4,
-    0xf95f, 0x21,
-    0xf992, 0x2e,
-    0xf9c1, 0x63f,
+    0x45, 0x0b,
+    0x0a, 0x06,
+    0x0d, 0x13,
+    0x38, 0x08,
+    0x0a, 0x36,
+    0x1a, 0x03,
+    0x0f, 0x04,
+    0x10, 0x81, 0x60,
+    0x53, 0x0c,
+    0x01, 0x81, 0xc0,
+    0x39, 0x81, 0x07,
+    0x46, 0x0a,
+    0x1d, 0x03,
+    0x47, 0x83, 0x49,
+    0x83, 0x9a, 0x66,
+    0x75, 0x0b,
+    0x80, 0xc4, 0x8a, 0xbc,
+    0x84, 0x2f, 0x8f, 0xd1,
+    0x82, 0x47, 0xa1, 0xb9,
+    0x82, 0x39, 0x07,
+    0x2a, 0x04,
+    0x02, 0x60,
+    0x26, 0x0a,
+    0x46, 0x0a,
+    0x28, 0x05,
+    0x13, 0x83, 0x70,
+    0x45, 0x0b,
+    0x2f, 0x10,
+    0x11, 0x40,
+    0x01, 0x1f,
+    0x97, 0xed, 0x13,
+    0x82, 0xf3, 0xa5, 0x0d,
+    0x02, 0x8b, 0xfe,
+    0x6b, 0x05,
+    0x0d, 0x03,
+    0x09, 0x07,
+    0x10, 0x93, 0x60,
+    0x80, 0xf6, 0x0a,
+    0x73, 0x08,
+    0x6e, 0x17,
+    0x46, 0x80, 0xba,
+    0x57, 0x09,
+    0x12, 0x80, 0x8e,
+    0x81, 0x47, 0x03,
+    0x85, 0x42, 0x0f,
+    0x15, 0x85, 0x50,
+    0x2b, 0x87, 0xd5,
+    0x80, 0xd7, 0x29,
+    0x4b, 0x05,
+    0x0a, 0x04,
+    0x02, 0x84, 0xa0,
+    0x3c, 0x06,
+    0x01, 0x04,
+    0x55, 0x05,
+    0x1b, 0x34,
+    0x02, 0x81, 0x0e,
+    0x2c, 0x04,
+    0x64, 0x0c,
+    0x56, 0x0a,
+    0x0d, 0x03,
+    0x5c, 0x04,
+    0x3d, 0x39,
+    0x1d, 0x0d,
+    0x2c, 0x04,
+    0x09, 0x07,
+    0x02, 0x80, 0xae,
+    0x83, 0xd3, 0x0d,
+    0x0d, 0x03,
+    0x07, 0x09,
+    0x74, 0x0c,
+    0x55, 0x2b,
+    0x0c, 0x04,
+    0x38, 0x08,
+    0x0a, 0x06,
+    0x28, 0x08,
+    0x1e, 0x62,
+    0x18, 0x08,
+    0x1c, 0x04,
+    0x0f, 0x21,
+    0x12, 0x2e,
+    0x01, 0x86, 0x3f,
 ];
diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs
index 8dbbc5928f4..97b9525da67 100644
--- a/src/libcore/clone.rs
+++ b/src/libcore/clone.rs
@@ -61,7 +61,7 @@
 /// ## Derivable
 ///
 /// This trait can be used with `#[derive]` if all fields are `Clone`. The `derive`d
-/// implementation of [`clone()`] calls [`clone()`] on each field.
+/// implementation of [`clone`] calls [`clone`] on each field.
 ///
 /// ## How can I implement `Clone`?
 ///
@@ -75,7 +75,7 @@
 /// `Clone` cannot be `derive`d, but can be implemented as:
 ///
 /// [`Copy`]: ../../std/marker/trait.Copy.html
-/// [`clone()`]: trait.Clone.html#tymethod.clone
+/// [`clone`]: trait.Clone.html#tymethod.clone
 ///
 /// ```
 /// #[derive(Copy)]
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index cc066099cf8..74ded948b18 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -210,7 +210,7 @@ pub enum Ordering {
 }
 
 impl Ordering {
-    /// Reverse the `Ordering`.
+    /// Reverses the `Ordering`.
     ///
     /// * `Less` becomes `Greater`.
     /// * `Greater` becomes `Less`.
@@ -255,8 +255,6 @@ impl Ordering {
     /// # Examples
     ///
     /// ```
-    /// #![feature(ordering_chaining)]
-    ///
     /// use std::cmp::Ordering;
     ///
     /// let result = Ordering::Equal.then(Ordering::Less);
@@ -277,7 +275,8 @@ impl Ordering {
     ///
     /// assert_eq!(result, Ordering::Less);
     /// ```
-    #[unstable(feature = "ordering_chaining", issue = "37053")]
+    #[inline]
+    #[stable(feature = "ordering_chaining", since = "1.17.0")]
     pub fn then(self, other: Ordering) -> Ordering {
         match self {
             Equal => other,
@@ -293,8 +292,6 @@ impl Ordering {
     /// # Examples
     ///
     /// ```
-    /// #![feature(ordering_chaining)]
-    ///
     /// use std::cmp::Ordering;
     ///
     /// let result = Ordering::Equal.then_with(|| Ordering::Less);
@@ -315,7 +312,8 @@ impl Ordering {
     ///
     /// assert_eq!(result, Ordering::Less);
     /// ```
-    #[unstable(feature = "ordering_chaining", issue = "37053")]
+    #[inline]
+    #[stable(feature = "ordering_chaining", since = "1.17.0")]
     pub fn then_with<F: FnOnce() -> Ordering>(self, f: F) -> Ordering {
         match self {
             Equal => f(),
@@ -324,6 +322,50 @@ impl Ordering {
     }
 }
 
+/// A helper struct for reverse ordering.
+///
+/// This struct is a helper to be used with functions like `Vec::sort_by_key` and
+/// can be used to reverse order a part of a key.
+///
+/// Example usage:
+///
+/// ```
+/// #![feature(reverse_cmp_key)]
+/// use std::cmp::Reverse;
+///
+/// let mut v = vec![1, 2, 3, 4, 5, 6];
+/// v.sort_by_key(|&num| (num > 3, Reverse(num)));
+/// assert_eq!(v, vec![3, 2, 1, 6, 5, 4]);
+/// ```
+#[derive(PartialEq, Eq, Debug)]
+#[unstable(feature = "reverse_cmp_key", issue = "40893")]
+pub struct Reverse<T>(pub T);
+
+#[unstable(feature = "reverse_cmp_key", issue = "40893")]
+impl<T: PartialOrd> PartialOrd for Reverse<T> {
+    #[inline]
+    fn partial_cmp(&self, other: &Reverse<T>) -> Option<Ordering> {
+        other.0.partial_cmp(&self.0)
+    }
+
+    #[inline]
+    fn lt(&self, other: &Self) -> bool { other.0 < self.0 }
+    #[inline]
+    fn le(&self, other: &Self) -> bool { other.0 <= self.0 }
+    #[inline]
+    fn ge(&self, other: &Self) -> bool { other.0 >= self.0 }
+    #[inline]
+    fn gt(&self, other: &Self) -> bool { other.0 > self.0 }
+}
+
+#[unstable(feature = "reverse_cmp_key", issue = "40893")]
+impl<T: Ord> Ord for Reverse<T> {
+    #[inline]
+    fn cmp(&self, other: &Reverse<T>) -> Ordering {
+        other.0.cmp(&self.0)
+    }
+}
+
 /// Trait for types that form a [total order](https://en.wikipedia.org/wiki/Total_order).
 ///
 /// An order is a total order if it is (for all `a`, `b` and `c`):
@@ -618,7 +660,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
     }
 }
 
-/// Compare and return the minimum of two values.
+/// Compares and returns the minimum of two values.
 ///
 /// Returns the first argument if the comparison determines them to be equal.
 ///
@@ -636,7 +678,7 @@ pub fn min<T: Ord>(v1: T, v2: T) -> T {
     if v1 <= v2 { v1 } else { v2 }
 }
 
-/// Compare and return the maximum of two values.
+/// Compares and returns the maximum of two values.
 ///
 /// Returns the second argument if the comparison determines them to be equal.
 ///
diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs
index 4e170794c1d..0b0f831f093 100644
--- a/src/libcore/convert.rs
+++ b/src/libcore/convert.rs
@@ -48,6 +48,8 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+use str::FromStr;
+
 /// A cheap, reference-to-reference conversion.
 ///
 /// `AsRef` is very similar to, but different than, [`Borrow`]. See
@@ -154,14 +156,14 @@ pub trait AsMut<T: ?Sized> {
 /// # Generic Impls
 ///
 /// - [`From<T>`][From]` for U` implies `Into<U> for T`
-/// - [`into()`] is reflexive, which means that `Into<T> for T` is implemented
+/// - [`into`] is reflexive, which means that `Into<T> for T` is implemented
 ///
 /// [`TryInto`]: trait.TryInto.html
 /// [`Option<T>`]: ../../std/option/enum.Option.html
 /// [`Result<T, E>`]: ../../std/result/enum.Result.html
 /// [`String`]: ../../std/string/struct.String.html
 /// [From]: trait.From.html
-/// [`into()`]: trait.Into.html#tymethod.into
+/// [`into`]: trait.Into.html#tymethod.into
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Into<T>: Sized {
     /// Performs the conversion.
@@ -187,14 +189,14 @@ pub trait Into<T>: Sized {
 /// # Generic impls
 ///
 /// - `From<T> for U` implies [`Into<U>`]` for T`
-/// - [`from()`] is reflexive, which means that `From<T> for T` is implemented
+/// - [`from`] is reflexive, which means that `From<T> for T` is implemented
 ///
 /// [`TryFrom`]: trait.TryFrom.html
 /// [`Option<T>`]: ../../std/option/enum.Option.html
 /// [`Result<T, E>`]: ../../std/result/enum.Result.html
 /// [`String`]: ../../std/string/struct.String.html
 /// [`Into<U>`]: trait.Into.html
-/// [`from()`]: trait.From.html#tymethod.from
+/// [`from`]: trait.From.html#tymethod.from
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait From<T>: Sized {
     /// Performs the conversion.
@@ -212,20 +214,20 @@ pub trait From<T>: Sized {
 #[unstable(feature = "try_from", issue = "33417")]
 pub trait TryInto<T>: Sized {
     /// The type returned in the event of a conversion error.
-    type Err;
+    type Error;
 
     /// Performs the conversion.
-    fn try_into(self) -> Result<T, Self::Err>;
+    fn try_into(self) -> Result<T, Self::Error>;
 }
 
 /// Attempt to construct `Self` via a conversion.
 #[unstable(feature = "try_from", issue = "33417")]
 pub trait TryFrom<T>: Sized {
     /// The type returned in the event of a conversion error.
-    type Err;
+    type Error;
 
     /// Performs the conversion.
-    fn try_from(value: T) -> Result<Self, Self::Err>;
+    fn try_from(value: T) -> Result<Self, Self::Error>;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -290,9 +292,9 @@ impl<T> From<T> for T {
 // TryFrom implies TryInto
 #[unstable(feature = "try_from", issue = "33417")]
 impl<T, U> TryInto<U> for T where U: TryFrom<T> {
-    type Err = U::Err;
+    type Error = U::Error;
 
-    fn try_into(self) -> Result<U, U::Err> {
+    fn try_into(self) -> Result<U, U::Error> {
         U::try_from(self)
     }
 }
@@ -322,3 +324,13 @@ impl AsRef<str> for str {
         self
     }
 }
+
+// FromStr implies TryFrom<&str>
+#[unstable(feature = "try_from", issue = "33417")]
+impl<'a, T> TryFrom<&'a str> for T where T: FromStr {
+    type Error = <T as FromStr>::Err;
+
+    fn try_from(s: &'a str) -> Result<T, Self::Error> {
+        FromStr::from_str(s)
+    }
+}
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 1657342ff6a..0bfab92fa5d 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -1045,6 +1045,7 @@ impl<'a> Formatter<'a> {
             // is zero
             Some(min) if self.sign_aware_zero_pad() => {
                 self.fill = '0';
+                self.align = rt::v1::Alignment::Right;
                 write_prefix(self)?;
                 self.with_padding(min - width, rt::v1::Alignment::Right, |f| {
                     f.buf.write_str(buf)
@@ -1153,8 +1154,9 @@ impl<'a> Formatter<'a> {
             // for the sign-aware zero padding, we render the sign first and
             // behave as if we had no sign from the beginning.
             let mut formatted = formatted.clone();
-            let mut align = self.align;
             let old_fill = self.fill;
+            let old_align = self.align;
+            let mut align = old_align;
             if self.sign_aware_zero_pad() {
                 // a sign always goes first
                 let sign = unsafe { str::from_utf8_unchecked(formatted.sign) };
@@ -1165,6 +1167,7 @@ impl<'a> Formatter<'a> {
                 width = if width < sign.len() { 0 } else { width - sign.len() };
                 align = rt::v1::Alignment::Right;
                 self.fill = '0';
+                self.align = rt::v1::Alignment::Right;
             }
 
             // remaining parts go through the ordinary padding process.
@@ -1177,6 +1180,7 @@ impl<'a> Formatter<'a> {
                 })
             };
             self.fill = old_fill;
+            self.align = old_align;
             ret
         } else {
             // this is the common case and we take a shortcut
diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs
index f0d8d1a3219..756d472eca8 100644
--- a/src/libcore/hash/mod.rs
+++ b/src/libcore/hash/mod.rs
@@ -16,7 +16,8 @@
 //! # Examples
 //!
 //! ```rust
-//! use std::hash::{Hash, SipHasher, Hasher};
+//! use std::collections::hash_map::DefaultHasher;
+//! use std::hash::{Hash, Hasher};
 //!
 //! #[derive(Hash)]
 //! struct Person {
@@ -25,13 +26,21 @@
 //!     phone: u64,
 //! }
 //!
-//! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
-//! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
+//! let person1 = Person {
+//!     id: 5,
+//!     name: "Janet".to_string(),
+//!     phone: 555_666_7777,
+//! };
+//! let person2 = Person {
+//!     id: 5,
+//!     name: "Bob".to_string(),
+//!     phone: 555_666_7777,
+//! };
 //!
-//! assert!(hash(&person1) != hash(&person2));
+//! assert!(calculate_hash(&person1) != calculate_hash(&person2));
 //!
-//! fn hash<T: Hash>(t: &T) -> u64 {
-//!     let mut s = SipHasher::new();
+//! fn calculate_hash<T: Hash>(t: &T) -> u64 {
+//!     let mut s = DefaultHasher::new();
 //!     t.hash(&mut s);
 //!     s.finish()
 //! }
@@ -43,11 +52,12 @@
 //! [`Hash`]: trait.Hash.html
 //!
 //! ```rust
-//! use std::hash::{Hash, Hasher, SipHasher};
+//! use std::collections::hash_map::DefaultHasher;
+//! use std::hash::{Hash, Hasher};
 //!
 //! struct Person {
 //!     id: u32,
-//! # #[allow(dead_code)]
+//!     # #[allow(dead_code)]
 //!     name: String,
 //!     phone: u64,
 //! }
@@ -59,13 +69,21 @@
 //!     }
 //! }
 //!
-//! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
-//! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
+//! let person1 = Person {
+//!     id: 5,
+//!     name: "Janet".to_string(),
+//!     phone: 555_666_7777,
+//! };
+//! let person2 = Person {
+//!     id: 5,
+//!     name: "Bob".to_string(),
+//!     phone: 555_666_7777,
+//! };
 //!
-//! assert_eq!(hash(&person1), hash(&person2));
+//! assert_eq!(calculate_hash(&person1), calculate_hash(&person2));
 //!
-//! fn hash<T: Hash>(t: &T) -> u64 {
-//!     let mut s = SipHasher::new();
+//! fn calculate_hash<T: Hash>(t: &T) -> u64 {
+//!     let mut s = DefaultHasher::new();
 //!     t.hash(&mut s);
 //!     s.finish()
 //! }
@@ -106,7 +124,7 @@ mod sip;
 ///
 /// This trait can be used with `#[derive]` if all fields implement `Hash`.
 /// When `derive`d, the resulting hash will be the combination of the values
-/// from calling [`.hash()`] on each field.
+/// from calling [`.hash`] on each field.
 ///
 /// ## How can I implement `Hash`?
 ///
@@ -133,7 +151,7 @@ mod sip;
 /// [`Eq`]: ../../std/cmp/trait.Eq.html
 /// [`HashMap`]: ../../std/collections/struct.HashMap.html
 /// [`HashSet`]: ../../std/collections/struct.HashSet.html
-/// [`.hash()`]: #tymethod.hash
+/// [`.hash`]: #tymethod.hash
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Hash {
     /// Feeds this value into the state given, updating the hasher as necessary.
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 12410c08f39..e0a4707ff66 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -46,8 +46,13 @@
             issue = "0")]
 #![allow(missing_docs)]
 
-extern "rust-intrinsic" {
+#[cfg(not(stage0))]
+#[stable(feature = "drop_in_place", since = "1.8.0")]
+#[rustc_deprecated(reason = "no longer an intrinsic - use `ptr::drop_in_place` directly",
+                   since = "1.18.0")]
+pub use ptr::drop_in_place;
 
+extern "rust-intrinsic" {
     // NB: These intrinsics take raw pointers because they mutate aliased
     // memory, which is not valid for either `&` or `&mut`.
 
@@ -56,16 +61,18 @@ extern "rust-intrinsic" {
     /// `std::sync::atomic` types via the `compare_exchange` method by passing
     /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html)
     /// as both the `success` and `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange`]
-    /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange).
+    /// [`AtomicBool::compare_exchange`][compare_exchange].
+    ///
+    /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
     pub fn atomic_cxchg<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange` method by passing
     /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
     /// as both the `success` and `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange`]
-    /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange).
+    /// [`AtomicBool::compare_exchange`][compare_exchange].
+    ///
+    /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
     pub fn atomic_cxchg_acq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     /// The stabilized version of this intrinsic is available on the
@@ -74,8 +81,9 @@ extern "rust-intrinsic" {
     /// as the `success` and
     /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
     /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange`]
-    /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange).
+    /// [`AtomicBool::compare_exchange`][compare_exchange].
+    ///
+    /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
     pub fn atomic_cxchg_rel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     /// The stabilized version of this intrinsic is available on the
@@ -84,16 +92,18 @@ extern "rust-intrinsic" {
     /// as the `success` and
     /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
     /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange`]
-    /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange).
+    /// [`AtomicBool::compare_exchange`][compare_exchange].
+    ///
+    /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
     pub fn atomic_cxchg_acqrel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange` method by passing
     /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
     /// as both the `success` and `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange`]
-    /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange).
+    /// [`AtomicBool::compare_exchange`][compare_exchange].
+    ///
+    /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
     pub fn atomic_cxchg_relaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     /// The stabilized version of this intrinsic is available on the
@@ -102,8 +112,9 @@ extern "rust-intrinsic" {
     /// as the `success` and
     /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
     /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange`]
-    /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange).
+    /// [`AtomicBool::compare_exchange`][compare_exchange].
+    ///
+    /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
     pub fn atomic_cxchg_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     /// The stabilized version of this intrinsic is available on the
@@ -112,8 +123,9 @@ extern "rust-intrinsic" {
     /// as the `success` and
     /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
     /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange`]
-    /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange).
+    /// [`AtomicBool::compare_exchange`][compare_exchange].
+    ///
+    /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
     pub fn atomic_cxchg_failacq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     /// The stabilized version of this intrinsic is available on the
@@ -122,8 +134,9 @@ extern "rust-intrinsic" {
     /// as the `success` and
     /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
     /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange`]
-    /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange).
+    /// [`AtomicBool::compare_exchange`][compare_exchange].
+    ///
+    /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
     pub fn atomic_cxchg_acq_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     /// The stabilized version of this intrinsic is available on the
@@ -132,8 +145,9 @@ extern "rust-intrinsic" {
     /// as the `success` and
     /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
     /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange`]
-    /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange).
+    /// [`AtomicBool::compare_exchange`][compare_exchange].
+    ///
+    /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange
     pub fn atomic_cxchg_acqrel_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
 
     /// Stores a value if the current value is the same as the `old` value.
@@ -141,16 +155,18 @@ extern "rust-intrinsic" {
     /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing
     /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html)
     /// as both the `success` and `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange_weak`]
-    /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak).
+    /// [`AtomicBool::compare_exchange_weak`][cew].
+    ///
+    /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
     pub fn atomic_cxchgweak<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing
     /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
     /// as both the `success` and `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange_weak`]
-    /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak).
+    /// [`AtomicBool::compare_exchange_weak`][cew].
+    ///
+    /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
     pub fn atomic_cxchgweak_acq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     /// The stabilized version of this intrinsic is available on the
@@ -159,8 +175,9 @@ extern "rust-intrinsic" {
     /// as the `success` and
     /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
     /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange_weak`]
-    /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak).
+    /// [`AtomicBool::compare_exchange_weak`][cew].
+    ///
+    /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
     pub fn atomic_cxchgweak_rel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     /// The stabilized version of this intrinsic is available on the
@@ -169,16 +186,18 @@ extern "rust-intrinsic" {
     /// as the `success` and
     /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
     /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange_weak`]
-    /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak).
+    /// [`AtomicBool::compare_exchange_weak`][cew].
+    ///
+    /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
     pub fn atomic_cxchgweak_acqrel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     /// The stabilized version of this intrinsic is available on the
     /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing
     /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
     /// as both the `success` and `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange_weak`]
-    /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak).
+    /// [`AtomicBool::compare_exchange_weak`][cew].
+    ///
+    /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
     pub fn atomic_cxchgweak_relaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     /// The stabilized version of this intrinsic is available on the
@@ -187,8 +206,9 @@ extern "rust-intrinsic" {
     /// as the `success` and
     /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
     /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange_weak`]
-    /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak).
+    /// [`AtomicBool::compare_exchange_weak`][cew].
+    ///
+    /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
     pub fn atomic_cxchgweak_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     /// The stabilized version of this intrinsic is available on the
@@ -197,8 +217,9 @@ extern "rust-intrinsic" {
     /// as the `success` and
     /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html)
     /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange_weak`]
-    /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak).
+    /// [`AtomicBool::compare_exchange_weak`][cew].
+    ///
+    /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
     pub fn atomic_cxchgweak_failacq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     /// The stabilized version of this intrinsic is available on the
@@ -207,8 +228,9 @@ extern "rust-intrinsic" {
     /// as the `success` and
     /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
     /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange_weak`]
-    /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak).
+    /// [`AtomicBool::compare_exchange_weak`][cew].
+    ///
+    /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
     pub fn atomic_cxchgweak_acq_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
     /// Stores a value if the current value is the same as the `old` value.
     /// The stabilized version of this intrinsic is available on the
@@ -217,8 +239,9 @@ extern "rust-intrinsic" {
     /// as the `success` and
     /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html)
     /// as the `failure` parameters. For example,
-    /// [`AtomicBool::compare_exchange_weak`]
-    /// (../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak).
+    /// [`AtomicBool::compare_exchange_weak`][cew].
+    ///
+    /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak
     pub fn atomic_cxchgweak_acqrel_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
 
     /// Loads the current value of the pointer.
@@ -622,6 +645,7 @@ extern "rust-intrinsic" {
     pub fn size_of_val<T: ?Sized>(_: &T) -> usize;
     pub fn min_align_of_val<T: ?Sized>(_: &T) -> usize;
 
+    #[cfg(stage0)]
     /// Executes the destructor (if any) of the pointed-to value.
     ///
     /// This has two use cases:
@@ -1238,17 +1262,26 @@ extern "rust-intrinsic" {
     /// undefined behavior where y = 0 or x = `T::min_value()` and y = -1
     pub fn unchecked_rem<T>(x: T, y: T) -> T;
 
-    /// Returns (a + b) mod 2^N, where N is the width of T in bits.
+    /// Performs an unchecked left shift, resulting in undefined behavior when
+    /// y < 0 or y >= N, where N is the width of T in bits.
+    #[cfg(not(stage0))]
+    pub fn unchecked_shl<T>(x: T, y: T) -> T;
+    /// Performs an unchecked right shift, resulting in undefined behavior when
+    /// y < 0 or y >= N, where N is the width of T in bits.
+    #[cfg(not(stage0))]
+    pub fn unchecked_shr<T>(x: T, y: T) -> T;
+
+    /// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_add` method. For example,
     /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add)
     pub fn overflowing_add<T>(a: T, b: T) -> T;
-    /// Returns (a - b) mod 2^N, where N is the width of T in bits.
+    /// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_sub` method. For example,
     /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub)
     pub fn overflowing_sub<T>(a: T, b: T) -> T;
-    /// Returns (a * b) mod 2^N, where N is the width of T in bits.
+    /// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_mul` method. For example,
     /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul)
diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs
index 0f47378aebb..618edf48abd 100644
--- a/src/libcore/iter/iterator.rs
+++ b/src/libcore/iter/iterator.rs
@@ -140,11 +140,11 @@ pub trait Iterator {
 
     /// Consumes the iterator, counting the number of iterations and returning it.
     ///
-    /// This method will evaluate the iterator until its [`next()`] returns
+    /// This method will evaluate the iterator until its [`next`] returns
     /// [`None`]. Once [`None`] is encountered, `count()` returns the number of
-    /// times it called [`next()`].
+    /// times it called [`next`].
     ///
-    /// [`next()`]: #tymethod.next
+    /// [`next`]: #tymethod.next
     /// [`None`]: ../../std/option/enum.Option.html#variant.None
     ///
     /// # Overflow Behavior
@@ -323,7 +323,7 @@ pub trait Iterator {
     ///
     /// In other words, it zips two iterators together, into a single one.
     ///
-    /// When either iterator returns [`None`], all further calls to [`next()`]
+    /// When either iterator returns [`None`], all further calls to [`next`]
     /// will return [`None`].
     ///
     /// # Examples
@@ -364,7 +364,7 @@ pub trait Iterator {
     ///
     /// `zip()` is often used to zip an infinite iterator to a finite one.
     /// This works because the finite iterator will eventually return [`None`],
-    /// ending the zipper. Zipping with `(0..)` can look a lot like [`enumerate()`]:
+    /// ending the zipper. Zipping with `(0..)` can look a lot like [`enumerate`]:
     ///
     /// ```
     /// let enumerate: Vec<_> = "foo".chars().enumerate().collect();
@@ -381,8 +381,8 @@ pub trait Iterator {
     /// assert_eq!((2, 'o'), zipper[2]);
     /// ```
     ///
-    /// [`enumerate()`]: trait.Iterator.html#method.enumerate
-    /// [`next()`]: ../../std/iter/trait.Iterator.html#tymethod.next
+    /// [`enumerate`]: trait.Iterator.html#method.enumerate
+    /// [`next`]: ../../std/iter/trait.Iterator.html#tymethod.next
     /// [`None`]: ../../std/option/enum.Option.html#variant.None
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -409,7 +409,7 @@ pub trait Iterator {
     /// If you're doing some sort of looping for a side effect, it's considered
     /// more idiomatic to use [`for`] than `map()`.
     ///
-    /// [`for`]: ../../book/loops.html#for
+    /// [`for`]: ../../book/first-edition/loops.html#for
     ///
     /// # Examples
     ///
@@ -518,23 +518,23 @@ pub trait Iterator {
 
     /// Creates an iterator that both filters and maps.
     ///
-    /// The closure must return an [`Option<T>`]. `filter_map()` creates an
+    /// The closure must return an [`Option<T>`]. `filter_map` creates an
     /// iterator which calls this closure on each element. If the closure
     /// returns [`Some(element)`][`Some`], then that element is returned. If the
     /// closure returns [`None`], it will try again, and call the closure on the
     /// next element, seeing if it will return [`Some`].
     ///
-    /// Why `filter_map()` and not just [`filter()`].[`map()`]? The key is in this
+    /// Why `filter_map` and not just [`filter`].[`map`]? The key is in this
     /// part:
     ///
-    /// [`filter()`]: #method.filter
-    /// [`map()`]: #method.map
+    /// [`filter`]: #method.filter
+    /// [`map`]: #method.map
     ///
     /// > If the closure returns [`Some(element)`][`Some`], then that element is returned.
     ///
     /// In other words, it removes the [`Option<T>`] layer automatically. If your
     /// mapping is already returning an [`Option<T>`] and you want to skip over
-    /// [`None`]s, then `filter_map()` is much, much nicer to use.
+    /// [`None`]s, then `filter_map` is much, much nicer to use.
     ///
     /// # Examples
     ///
@@ -550,7 +550,7 @@ pub trait Iterator {
     /// assert_eq!(iter.next(), None);
     /// ```
     ///
-    /// Here's the same example, but with [`filter()`] and [`map()`]:
+    /// Here's the same example, but with [`filter`] and [`map`]:
     ///
     /// ```
     /// let a = ["1", "2", "lol"];
@@ -585,7 +585,7 @@ pub trait Iterator {
     /// iterator.
     ///
     /// `enumerate()` keeps its count as a [`usize`]. If you want to count by a
-    /// different sized integer, the [`zip()`] function provides similar
+    /// different sized integer, the [`zip`] function provides similar
     /// functionality.
     ///
     /// # Overflow Behavior
@@ -601,7 +601,7 @@ pub trait Iterator {
     ///
     /// [`usize::MAX`]: ../../std/usize/constant.MAX.html
     /// [`usize`]: ../../std/primitive.usize.html
-    /// [`zip()`]: #method.zip
+    /// [`zip`]: #method.zip
     ///
     /// # Examples
     ///
@@ -624,16 +624,16 @@ pub trait Iterator {
     /// Creates an iterator which can use `peek` to look at the next element of
     /// the iterator without consuming it.
     ///
-    /// Adds a [`peek()`] method to an iterator. See its documentation for
+    /// Adds a [`peek`] method to an iterator. See its documentation for
     /// more information.
     ///
-    /// Note that the underlying iterator is still advanced when [`peek()`] is
+    /// Note that the underlying iterator is still advanced when [`peek`] is
     /// called for the first time: In order to retrieve the next element,
-    /// [`next()`] is called on the underlying iterator, hence any side effects of
-    /// the [`next()`] method will occur.
+    /// [`next`] is called on the underlying iterator, hence any side effects of
+    /// the [`next`] method will occur.
     ///
-    /// [`peek()`]: struct.Peekable.html#method.peek
-    /// [`next()`]: ../../std/iter/trait.Iterator.html#tymethod.next
+    /// [`peek`]: struct.Peekable.html#method.peek
+    /// [`next`]: ../../std/iter/trait.Iterator.html#tymethod.next
     ///
     /// # Examples
     ///
@@ -666,9 +666,9 @@ pub trait Iterator {
         Peekable{iter: self, peeked: None}
     }
 
-    /// Creates an iterator that [`skip()`]s elements based on a predicate.
+    /// Creates an iterator that [`skip`]s elements based on a predicate.
     ///
-    /// [`skip()`]: #method.skip
+    /// [`skip`]: #method.skip
     ///
     /// `skip_while()` takes a closure as an argument. It will call this
     /// closure on each element of the iterator, and ignore elements
@@ -863,10 +863,10 @@ pub trait Iterator {
         Take{iter: self, n: n}
     }
 
-    /// An iterator adaptor similar to [`fold()`] that holds internal state and
+    /// An iterator adaptor similar to [`fold`] that holds internal state and
     /// produces a new iterator.
     ///
-    /// [`fold()`]: #method.fold
+    /// [`fold`]: #method.fold
     ///
     /// `scan()` takes two arguments: an initial value which seeds the internal
     /// state, and a closure with two arguments, the first being a mutable
@@ -910,16 +910,16 @@ pub trait Iterator {
 
     /// Creates an iterator that works like map, but flattens nested structure.
     ///
-    /// The [`map()`] adapter is very useful, but only when the closure
+    /// The [`map`] adapter is very useful, but only when the closure
     /// argument produces values. If it produces an iterator instead, there's
     /// an extra layer of indirection. `flat_map()` will remove this extra layer
     /// on its own.
     ///
-    /// Another way of thinking about `flat_map()`: [`map()`]'s closure returns
+    /// Another way of thinking about `flat_map()`: [`map`]'s closure returns
     /// one item for each element, and `flat_map()`'s closure returns an
     /// iterator for each element.
     ///
-    /// [`map()`]: #method.map
+    /// [`map`]: #method.map
     ///
     /// # Examples
     ///
@@ -1106,7 +1106,7 @@ pub trait Iterator {
     /// library, used in a variety of contexts.
     ///
     /// The most basic pattern in which `collect()` is used is to turn one
-    /// collection into another. You take a collection, call [`iter()`] on it,
+    /// collection into another. You take a collection, call [`iter`] on it,
     /// do a bunch of transformations, and then `collect()` at the end.
     ///
     /// One of the keys to `collect()`'s power is that many things you might
@@ -1211,7 +1211,7 @@ pub trait Iterator {
     /// assert_eq!(Ok(vec![1, 3]), result);
     /// ```
     ///
-    /// [`iter()`]: ../../std/iter/trait.Iterator.html#tymethod.next
+    /// [`iter`]: ../../std/iter/trait.Iterator.html#tymethod.next
     /// [`String`]: ../../std/string/struct.String.html
     /// [`char`]: ../../std/primitive.char.html
     /// [`Result`]: ../../std/result/enum.Result.html
@@ -1306,7 +1306,7 @@ pub trait Iterator {
     /// use a `for` loop with a list of things to build up a result. Those
     /// can be turned into `fold()`s:
     ///
-    /// [`for`]: ../../book/loops.html#for
+    /// [`for`]: ../../book/first-edition/loops.html#for
     ///
     /// ```
     /// let numbers = [1, 2, 3, 4, 5];
@@ -1816,9 +1816,9 @@ pub trait Iterator {
     /// collections: one from the left elements of the pairs, and one
     /// from the right elements.
     ///
-    /// This function is, in some sense, the opposite of [`zip()`].
+    /// This function is, in some sense, the opposite of [`zip`].
     ///
-    /// [`zip()`]: #method.zip
+    /// [`zip`]: #method.zip
     ///
     /// # Examples
     ///
@@ -1849,12 +1849,12 @@ pub trait Iterator {
         (ts, us)
     }
 
-    /// Creates an iterator which [`clone()`]s all of its elements.
+    /// Creates an iterator which [`clone`]s all of its elements.
     ///
     /// This is useful when you have an iterator over `&T`, but you need an
     /// iterator over `T`.
     ///
-    /// [`clone()`]: ../../std/clone/trait.Clone.html#tymethod.clone
+    /// [`clone`]: ../../std/clone/trait.Clone.html#tymethod.clone
     ///
     /// # Examples
     ///
diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs
index df4aef08871..273f9d0e6f6 100644
--- a/src/libcore/iter/mod.rs
+++ b/src/libcore/iter/mod.rs
@@ -48,15 +48,15 @@
 //! }
 //! ```
 //!
-//! An iterator has a method, [`next()`], which when called, returns an
-//! [`Option`]`<Item>`. [`next()`] will return `Some(Item)` as long as there
+//! An iterator has a method, [`next`], which when called, returns an
+//! [`Option`]`<Item>`. [`next`] will return `Some(Item)` as long as there
 //! are elements, and once they've all been exhausted, will return `None` to
 //! indicate that iteration is finished. Individual iterators may choose to
-//! resume iteration, and so calling [`next()`] again may or may not eventually
+//! resume iteration, and so calling [`next`] again may or may not eventually
 //! start returning `Some(Item)` again at some point.
 //!
 //! [`Iterator`]'s full definition includes a number of other methods as well,
-//! but they are default methods, built on top of [`next()`], and so you get
+//! but they are default methods, built on top of [`next`], and so you get
 //! them for free.
 //!
 //! Iterators are also composable, and it's common to chain them together to do
@@ -64,7 +64,7 @@
 //! below for more details.
 //!
 //! [`Iterator`]: trait.Iterator.html
-//! [`next()`]: trait.Iterator.html#tymethod.next
+//! [`next`]: trait.Iterator.html#tymethod.next
 //! [`Option`]: ../../std/option/enum.Option.html
 //!
 //! # The three forms of iteration
@@ -168,13 +168,13 @@
 //! produce an iterator. What gives?
 //!
 //! There's a trait in the standard library for converting something into an
-//! iterator: [`IntoIterator`]. This trait has one method, [`into_iter()`],
+//! iterator: [`IntoIterator`]. This trait has one method, [`into_iter`],
 //! which converts the thing implementing [`IntoIterator`] into an iterator.
 //! Let's take a look at that `for` loop again, and what the compiler converts
 //! it into:
 //!
 //! [`IntoIterator`]: trait.IntoIterator.html
-//! [`into_iter()`]: trait.IntoIterator.html#tymethod.into_iter
+//! [`into_iter`]: trait.IntoIterator.html#tymethod.into_iter
 //!
 //! ```
 //! let values = vec![1, 2, 3, 4, 5];
@@ -202,7 +202,7 @@
 //! ```
 //!
 //! First, we call `into_iter()` on the value. Then, we match on the iterator
-//! that returns, calling [`next()`] over and over until we see a `None`. At
+//! that returns, calling [`next`] over and over until we see a `None`. At
 //! that point, we `break` out of the loop, and we're done iterating.
 //!
 //! There's one more subtle bit here: the standard library contains an
@@ -225,19 +225,19 @@
 //! often called 'iterator adapters', as they're a form of the 'adapter
 //! pattern'.
 //!
-//! Common iterator adapters include [`map()`], [`take()`], and [`filter()`].
+//! Common iterator adapters include [`map`], [`take`], and [`filter`].
 //! For more, see their documentation.
 //!
-//! [`map()`]: trait.Iterator.html#method.map
-//! [`take()`]: trait.Iterator.html#method.take
-//! [`filter()`]: trait.Iterator.html#method.filter
+//! [`map`]: trait.Iterator.html#method.map
+//! [`take`]: trait.Iterator.html#method.take
+//! [`filter`]: trait.Iterator.html#method.filter
 //!
 //! # Laziness
 //!
 //! Iterators (and iterator [adapters](#adapters)) are *lazy*. This means that
 //! just creating an iterator doesn't _do_ a whole lot. Nothing really happens
-//! until you call [`next()`]. This is sometimes a source of confusion when
-//! creating an iterator solely for its side effects. For example, the [`map()`]
+//! until you call [`next`]. This is sometimes a source of confusion when
+//! creating an iterator solely for its side effects. For example, the [`map`]
 //! method calls a closure on each element it iterates over:
 //!
 //! ```
@@ -254,7 +254,7 @@
 //! do nothing unless consumed
 //! ```
 //!
-//! The idiomatic way to write a [`map()`] for its side effects is to use a
+//! The idiomatic way to write a [`map`] for its side effects is to use a
 //! `for` loop instead:
 //!
 //! ```
@@ -265,12 +265,12 @@
 //! }
 //! ```
 //!
-//! [`map()`]: trait.Iterator.html#method.map
+//! [`map`]: trait.Iterator.html#method.map
 //!
 //! The two most common ways to evaluate an iterator are to use a `for` loop
-//! like this, or using the [`collect()`] method to produce a new collection.
+//! like this, or using the [`collect`] method to produce a new collection.
 //!
-//! [`collect()`]: trait.Iterator.html#method.collect
+//! [`collect`]: trait.Iterator.html#method.collect
 //!
 //! # Infinity
 //!
@@ -281,7 +281,7 @@
 //! let numbers = 0..;
 //! ```
 //!
-//! It is common to use the [`take()`] iterator adapter to turn an infinite
+//! It is common to use the [`take`] iterator adapter to turn an infinite
 //! iterator into a finite one:
 //!
 //! ```
@@ -295,7 +295,7 @@
 //!
 //! This will print the numbers `0` through `4`, each on their own line.
 //!
-//! [`take()`]: trait.Iterator.html#method.take
+//! [`take`]: trait.Iterator.html#method.take
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -338,10 +338,10 @@ mod traits;
 
 /// A double-ended iterator with the direction inverted.
 ///
-/// This `struct` is created by the [`rev()`] method on [`Iterator`]. See its
+/// This `struct` is created by the [`rev`] method on [`Iterator`]. See its
 /// documentation for more.
 ///
-/// [`rev()`]: trait.Iterator.html#method.rev
+/// [`rev`]: trait.Iterator.html#method.rev
 /// [`Iterator`]: trait.Iterator.html
 #[derive(Clone, Debug)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
@@ -358,12 +358,24 @@ impl<I> Iterator for Rev<I> where I: DoubleEndedIterator {
     fn next(&mut self) -> Option<<I as Iterator>::Item> { self.iter.next_back() }
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+
+    fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
+        where P: FnMut(&Self::Item) -> bool
+    {
+        self.iter.rfind(predicate)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<I> DoubleEndedIterator for Rev<I> where I: DoubleEndedIterator {
     #[inline]
     fn next_back(&mut self) -> Option<<I as Iterator>::Item> { self.iter.next() }
+
+    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
+        where P: FnMut(&Self::Item) -> bool
+    {
+        self.iter.find(predicate)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -389,10 +401,10 @@ unsafe impl<I> TrustedLen for Rev<I>
 
 /// An iterator that clones the elements of an underlying iterator.
 ///
-/// This `struct` is created by the [`cloned()`] method on [`Iterator`]. See its
+/// This `struct` is created by the [`cloned`] method on [`Iterator`]. See its
 /// documentation for more.
 ///
-/// [`cloned()`]: trait.Iterator.html#method.cloned
+/// [`cloned`]: trait.Iterator.html#method.cloned
 /// [`Iterator`]: trait.Iterator.html
 #[stable(feature = "iter_cloned", since = "1.1.0")]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
@@ -469,10 +481,10 @@ unsafe impl<'a, I, T: 'a> TrustedLen for Cloned<I>
 
 /// An iterator that repeats endlessly.
 ///
-/// This `struct` is created by the [`cycle()`] method on [`Iterator`]. See its
+/// This `struct` is created by the [`cycle`] method on [`Iterator`]. See its
 /// documentation for more.
 ///
-/// [`cycle()`]: trait.Iterator.html#method.cycle
+/// [`cycle`]: trait.Iterator.html#method.cycle
 /// [`Iterator`]: trait.Iterator.html
 #[derive(Clone, Debug)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
@@ -510,10 +522,10 @@ impl<I> FusedIterator for Cycle<I> where I: Clone + Iterator {}
 
 /// An iterator that strings two iterators together.
 ///
-/// This `struct` is created by the [`chain()`] method on [`Iterator`]. See its
+/// This `struct` is created by the [`chain`] method on [`Iterator`]. See its
 /// documentation for more.
 ///
-/// [`chain()`]: trait.Iterator.html#method.chain
+/// [`chain`]: trait.Iterator.html#method.chain
 /// [`Iterator`]: trait.Iterator.html
 #[derive(Clone, Debug)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
@@ -703,10 +715,10 @@ unsafe impl<A, B> TrustedLen for Chain<A, B>
 
 /// An iterator that iterates two other iterators simultaneously.
 ///
-/// This `struct` is created by the [`zip()`] method on [`Iterator`]. See its
+/// This `struct` is created by the [`zip`] method on [`Iterator`]. See its
 /// documentation for more.
 ///
-/// [`zip()`]: trait.Iterator.html#method.zip
+/// [`zip`]: trait.Iterator.html#method.zip
 /// [`Iterator`]: trait.Iterator.html
 #[derive(Clone, Debug)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
@@ -925,16 +937,16 @@ unsafe impl<A, B> TrustedLen for Zip<A, B>
 
 /// An iterator that maps the values of `iter` with `f`.
 ///
-/// This `struct` is created by the [`map()`] method on [`Iterator`]. See its
+/// This `struct` is created by the [`map`] method on [`Iterator`]. See its
 /// documentation for more.
 ///
-/// [`map()`]: trait.Iterator.html#method.map
+/// [`map`]: trait.Iterator.html#method.map
 /// [`Iterator`]: trait.Iterator.html
 ///
 /// # Notes about side effects
 ///
-/// The [`map()`] iterator implements [`DoubleEndedIterator`], meaning that
-/// you can also [`map()`] backwards:
+/// The [`map`] iterator implements [`DoubleEndedIterator`], meaning that
+/// you can also [`map`] backwards:
 ///
 /// ```rust
 /// let v: Vec<i32> = vec![1, 2, 3].into_iter().map(|x| x + 1).rev().collect();
@@ -1058,10 +1070,10 @@ unsafe impl<B, I, F> TrustedRandomAccess for Map<I, F>
 
 /// An iterator that filters the elements of `iter` with `predicate`.
 ///
-/// This `struct` is created by the [`filter()`] method on [`Iterator`]. See its
+/// This `struct` is created by the [`filter`] method on [`Iterator`]. See its
 /// documentation for more.
 ///
-/// [`filter()`]: trait.Iterator.html#method.filter
+/// [`filter`]: trait.Iterator.html#method.filter
 /// [`Iterator`]: trait.Iterator.html
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1142,10 +1154,10 @@ impl<I: FusedIterator, P> FusedIterator for Filter<I, P>
 
 /// An iterator that uses `f` to both filter and map elements from `iter`.
 ///
-/// This `struct` is created by the [`filter_map()`] method on [`Iterator`]. See its
+/// This `struct` is created by the [`filter_map`] method on [`Iterator`]. See its
 /// documentation for more.
 ///
-/// [`filter_map()`]: trait.Iterator.html#method.filter_map
+/// [`filter_map`]: trait.Iterator.html#method.filter_map
 /// [`Iterator`]: trait.Iterator.html
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1208,10 +1220,10 @@ impl<B, I: FusedIterator, F> FusedIterator for FilterMap<I, F>
 
 /// An iterator that yields the current count and the element during iteration.
 ///
-/// This `struct` is created by the [`enumerate()`] method on [`Iterator`]. See its
+/// This `struct` is created by the [`enumerate`] method on [`Iterator`]. See its
 /// documentation for more.
 ///
-/// [`enumerate()`]: trait.Iterator.html#method.enumerate
+/// [`enumerate`]: trait.Iterator.html#method.enumerate
 /// [`Iterator`]: trait.Iterator.html
 #[derive(Clone, Debug)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
@@ -1317,10 +1329,10 @@ unsafe impl<I> TrustedLen for Enumerate<I>
 /// An iterator with a `peek()` that returns an optional reference to the next
 /// element.
 ///
-/// This `struct` is created by the [`peekable()`] method on [`Iterator`]. See its
+/// This `struct` is created by the [`peekable`] method on [`Iterator`]. See its
 /// documentation for more.
 ///
-/// [`peekable()`]: trait.Iterator.html#method.peekable
+/// [`peekable`]: trait.Iterator.html#method.peekable
 /// [`Iterator`]: trait.Iterator.html
 #[derive(Clone, Debug)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
@@ -1401,10 +1413,10 @@ impl<I: FusedIterator> FusedIterator for Peekable<I> {}
 impl<I: Iterator> Peekable<I> {
     /// Returns a reference to the next() value without advancing the iterator.
     ///
-    /// Like [`next()`], if there is a value, it is wrapped in a `Some(T)`.
+    /// Like [`next`], if there is a value, it is wrapped in a `Some(T)`.
     /// But if the iteration is over, `None` is returned.
     ///
-    /// [`next()`]: trait.Iterator.html#tymethod.next
+    /// [`next`]: trait.Iterator.html#tymethod.next
     ///
     /// Because `peek()` returns a reference, and many iterators iterate over
     /// references, there can be a possibly confusing situation where the
@@ -1452,10 +1464,10 @@ impl<I: Iterator> Peekable<I> {
 
 /// An iterator that rejects elements while `predicate` is true.
 ///
-/// This `struct` is created by the [`skip_while()`] method on [`Iterator`]. See its
+/// This `struct` is created by the [`skip_while`] method on [`Iterator`]. See its
 /// documentation for more.
 ///
-/// [`skip_while()`]: trait.Iterator.html#method.skip_while
+/// [`skip_while`]: trait.Iterator.html#method.skip_while
 /// [`Iterator`]: trait.Iterator.html
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1506,10 +1518,10 @@ impl<I, P> FusedIterator for SkipWhile<I, P>
 
 /// An iterator that only accepts elements while `predicate` is true.
 ///
-/// This `struct` is created by the [`take_while()`] method on [`Iterator`]. See its
+/// This `struct` is created by the [`take_while`] method on [`Iterator`]. See its
 /// documentation for more.
 ///
-/// [`take_while()`]: trait.Iterator.html#method.take_while
+/// [`take_while`]: trait.Iterator.html#method.take_while
 /// [`Iterator`]: trait.Iterator.html
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1565,10 +1577,10 @@ impl<I, P> FusedIterator for TakeWhile<I, P>
 
 /// An iterator that skips over `n` elements of `iter`.
 ///
-/// This `struct` is created by the [`skip()`] method on [`Iterator`]. See its
+/// This `struct` is created by the [`skip`] method on [`Iterator`]. See its
 /// documentation for more.
 ///
-/// [`skip()`]: trait.Iterator.html#method.skip
+/// [`skip`]: trait.Iterator.html#method.skip
 /// [`Iterator`]: trait.Iterator.html
 #[derive(Clone, Debug)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
@@ -1659,10 +1671,10 @@ impl<I> FusedIterator for Skip<I> where I: FusedIterator {}
 
 /// An iterator that only iterates over the first `n` iterations of `iter`.
 ///
-/// This `struct` is created by the [`take()`] method on [`Iterator`]. See its
+/// This `struct` is created by the [`take`] method on [`Iterator`]. See its
 /// documentation for more.
 ///
-/// [`take()`]: trait.Iterator.html#method.take
+/// [`take`]: trait.Iterator.html#method.take
 /// [`Iterator`]: trait.Iterator.html
 #[derive(Clone, Debug)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
@@ -1723,10 +1735,10 @@ impl<I> FusedIterator for Take<I> where I: FusedIterator {}
 
 /// An iterator to maintain state while iterating another iterator.
 ///
-/// This `struct` is created by the [`scan()`] method on [`Iterator`]. See its
+/// This `struct` is created by the [`scan`] method on [`Iterator`]. See its
 /// documentation for more.
 ///
-/// [`scan()`]: trait.Iterator.html#method.scan
+/// [`scan`]: trait.Iterator.html#method.scan
 /// [`Iterator`]: trait.Iterator.html
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1773,10 +1785,10 @@ impl<B, I, St, F> FusedIterator for Scan<I, St, F>
 /// An iterator that maps each element to an iterator, and yields the elements
 /// of the produced iterators.
 ///
-/// This `struct` is created by the [`flat_map()`] method on [`Iterator`]. See its
+/// This `struct` is created by the [`flat_map`] method on [`Iterator`]. See its
 /// documentation for more.
 ///
-/// [`flat_map()`]: trait.Iterator.html#method.flat_map
+/// [`flat_map`]: trait.Iterator.html#method.flat_map
 /// [`Iterator`]: trait.Iterator.html
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1863,10 +1875,10 @@ impl<I, U, F> FusedIterator for FlatMap<I, U, F>
 /// An iterator that yields `None` forever after the underlying iterator
 /// yields `None` once.
 ///
-/// This `struct` is created by the [`fuse()`] method on [`Iterator`]. See its
+/// This `struct` is created by the [`fuse`] method on [`Iterator`]. See its
 /// documentation for more.
 ///
-/// [`fuse()`]: trait.Iterator.html#method.fuse
+/// [`fuse`]: trait.Iterator.html#method.fuse
 /// [`Iterator`]: trait.Iterator.html
 #[derive(Clone, Debug)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
@@ -2012,10 +2024,10 @@ impl<I> ExactSizeIterator for Fuse<I> where I: ExactSizeIterator {
 /// An iterator that calls a function with a reference to each element before
 /// yielding it.
 ///
-/// This `struct` is created by the [`inspect()`] method on [`Iterator`]. See its
+/// This `struct` is created by the [`inspect`] method on [`Iterator`]. See its
 /// documentation for more.
 ///
-/// [`inspect()`]: trait.Iterator.html#method.inspect
+/// [`inspect`]: trait.Iterator.html#method.inspect
 /// [`Iterator`]: trait.Iterator.html
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs
index b988ce73bde..b405f35d5e4 100644
--- a/src/libcore/iter/sources.rs
+++ b/src/libcore/iter/sources.rs
@@ -16,9 +16,9 @@ use super::{FusedIterator, TrustedLen};
 
 /// An iterator that repeats an element endlessly.
 ///
-/// This `struct` is created by the [`repeat()`] function. See its documentation for more.
+/// This `struct` is created by the [`repeat`] function. See its documentation for more.
 ///
-/// [`repeat()`]: fn.repeat.html
+/// [`repeat`]: fn.repeat.html
 #[derive(Clone, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Repeat<A> {
@@ -50,9 +50,9 @@ impl<A: Clone> FusedIterator for Repeat<A> {}
 /// over and over and 🔁.
 ///
 /// Infinite iterators like `repeat()` are often used with adapters like
-/// [`take()`], in order to make them finite.
+/// [`take`], in order to make them finite.
 ///
-/// [`take()`]: trait.Iterator.html#method.take
+/// [`take`]: trait.Iterator.html#method.take
 ///
 /// # Examples
 ///
@@ -74,7 +74,7 @@ impl<A: Clone> FusedIterator for Repeat<A> {}
 /// assert_eq!(Some(4), fours.next());
 /// ```
 ///
-/// Going finite with [`take()`]:
+/// Going finite with [`take`]:
 ///
 /// ```
 /// use std::iter;
@@ -98,9 +98,9 @@ pub fn repeat<T: Clone>(elt: T) -> Repeat<T> {
 
 /// An iterator that yields nothing.
 ///
-/// This `struct` is created by the [`empty()`] function. See its documentation for more.
+/// This `struct` is created by the [`empty`] function. See its documentation for more.
 ///
-/// [`empty()`]: fn.empty.html
+/// [`empty`]: fn.empty.html
 #[stable(feature = "iter_empty", since = "1.2.0")]
 pub struct Empty<T>(marker::PhantomData<T>);
 
@@ -183,9 +183,9 @@ pub fn empty<T>() -> Empty<T> {
 
 /// An iterator that yields an element exactly once.
 ///
-/// This `struct` is created by the [`once()`] function. See its documentation for more.
+/// This `struct` is created by the [`once`] function. See its documentation for more.
 ///
-/// [`once()`]: fn.once.html
+/// [`once`]: fn.once.html
 #[derive(Clone, Debug)]
 #[stable(feature = "iter_once", since = "1.2.0")]
 pub struct Once<T> {
@@ -227,12 +227,12 @@ impl<T> FusedIterator for Once<T> {}
 
 /// Creates an iterator that yields an element exactly once.
 ///
-/// This is commonly used to adapt a single value into a [`chain()`] of other
+/// This is commonly used to adapt a single value into a [`chain`] of other
 /// kinds of iteration. Maybe you have an iterator that covers almost
 /// everything, but you need an extra special case. Maybe you have a function
 /// which works on iterators, but you only need to process one value.
 ///
-/// [`chain()`]: trait.Iterator.html#method.chain
+/// [`chain`]: trait.Iterator.html#method.chain
 ///
 /// # Examples
 ///
diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs
index cb180110d3c..798dda19928 100644
--- a/src/libcore/iter/traits.rs
+++ b/src/libcore/iter/traits.rs
@@ -16,13 +16,13 @@ use num::Wrapping;
 /// created from an iterator. This is common for types which describe a
 /// collection of some kind.
 ///
-/// `FromIterator`'s [`from_iter()`] is rarely called explicitly, and is instead
-/// used through [`Iterator`]'s [`collect()`] method. See [`collect()`]'s
+/// `FromIterator`'s [`from_iter`] is rarely called explicitly, and is instead
+/// used through [`Iterator`]'s [`collect`] method. See [`collect`]'s
 /// documentation for more examples.
 ///
-/// [`from_iter()`]: #tymethod.from_iter
+/// [`from_iter`]: #tymethod.from_iter
 /// [`Iterator`]: trait.Iterator.html
-/// [`collect()`]: trait.Iterator.html#method.collect
+/// [`collect`]: trait.Iterator.html#method.collect
 ///
 /// See also: [`IntoIterator`].
 ///
@@ -42,7 +42,7 @@ use num::Wrapping;
 /// assert_eq!(v, vec![5, 5, 5, 5, 5]);
 /// ```
 ///
-/// Using [`collect()`] to implicitly use `FromIterator`:
+/// Using [`collect`] to implicitly use `FromIterator`:
 ///
 /// ```
 /// let five_fives = std::iter::repeat(5).take(5);
@@ -467,7 +467,7 @@ pub trait DoubleEndedIterator: Iterator {
         Self: Sized,
         P: FnMut(&Self::Item) -> bool
     {
-        for x in self.by_ref().rev() {
+        while let Some(x) = self.next_back() {
             if predicate(&x) { return Some(x) }
         }
         None
@@ -487,17 +487,17 @@ impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I {
 /// backwards, a good start is to know where the end is.
 ///
 /// When implementing an `ExactSizeIterator`, You must also implement
-/// [`Iterator`]. When doing so, the implementation of [`size_hint()`] *must*
+/// [`Iterator`]. When doing so, the implementation of [`size_hint`] *must*
 /// return the exact size of the iterator.
 ///
 /// [`Iterator`]: trait.Iterator.html
-/// [`size_hint()`]: trait.Iterator.html#method.size_hint
+/// [`size_hint`]: trait.Iterator.html#method.size_hint
 ///
-/// The [`len()`] method has a default implementation, so you usually shouldn't
+/// The [`len`] method has a default implementation, so you usually shouldn't
 /// implement it. However, you may be able to provide a more performant
 /// implementation than the default, so overriding it in this case makes sense.
 ///
-/// [`len()`]: #method.len
+/// [`len`]: #method.len
 ///
 /// # Examples
 ///
@@ -536,9 +536,9 @@ impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I {
 /// #     }
 /// # }
 /// impl ExactSizeIterator for Counter {
-///     // We already have the number of iterations, so we can use it directly.
+///     // We can easily calculate the remaining number of iterations.
 ///     fn len(&self) -> usize {
-///         self.count
+///         5 - self.count
 ///     }
 /// }
 ///
@@ -546,7 +546,7 @@ impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I {
 ///
 /// let counter = Counter::new();
 ///
-/// assert_eq!(0, counter.len());
+/// assert_eq!(5, counter.len());
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait ExactSizeIterator: Iterator {
@@ -557,11 +557,11 @@ pub trait ExactSizeIterator: Iterator {
     /// implementation, you can do so. See the [trait-level] docs for an
     /// example.
     ///
-    /// This function has the same safety guarantees as the [`size_hint()`]
+    /// This function has the same safety guarantees as the [`size_hint`]
     /// function.
     ///
     /// [trait-level]: trait.ExactSizeIterator.html
-    /// [`size_hint()`]: trait.Iterator.html#method.size_hint
+    /// [`size_hint`]: trait.Iterator.html#method.size_hint
     ///
     /// # Examples
     ///
@@ -624,14 +624,14 @@ impl<'a, I: ExactSizeIterator + ?Sized> ExactSizeIterator for &'a mut I {
 
 /// Trait to represent types that can be created by summing up an iterator.
 ///
-/// This trait is used to implement the [`sum()`] method on iterators. Types which
-/// implement the trait can be generated by the [`sum()`] method. Like
+/// This trait is used to implement the [`sum`] method on iterators. Types which
+/// implement the trait can be generated by the [`sum`] method. Like
 /// [`FromIterator`] this trait should rarely be called directly and instead
-/// interacted with through [`Iterator::sum()`].
+/// interacted with through [`Iterator::sum`].
 ///
-/// [`sum()`]: ../../std/iter/trait.Sum.html#tymethod.sum
+/// [`sum`]: ../../std/iter/trait.Sum.html#tymethod.sum
 /// [`FromIterator`]: ../../std/iter/trait.FromIterator.html
-/// [`Iterator::sum()`]: ../../std/iter/trait.Iterator.html#method.sum
+/// [`Iterator::sum`]: ../../std/iter/trait.Iterator.html#method.sum
 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
 pub trait Sum<A = Self>: Sized {
     /// Method which takes an iterator and generates `Self` from the elements by
@@ -643,14 +643,14 @@ pub trait Sum<A = Self>: Sized {
 /// Trait to represent types that can be created by multiplying elements of an
 /// iterator.
 ///
-/// This trait is used to implement the [`product()`] method on iterators. Types
-/// which implement the trait can be generated by the [`product()`] method. Like
+/// This trait is used to implement the [`product`] method on iterators. Types
+/// which implement the trait can be generated by the [`product`] method. Like
 /// [`FromIterator`] this trait should rarely be called directly and instead
-/// interacted with through [`Iterator::product()`].
+/// interacted with through [`Iterator::product`].
 ///
-/// [`product()`]: ../../std/iter/trait.Product.html#tymethod.product
+/// [`product`]: ../../std/iter/trait.Product.html#tymethod.product
 /// [`FromIterator`]: ../../std/iter/trait.FromIterator.html
-/// [`Iterator::product()`]: ../../std/iter/trait.Iterator.html#method.product
+/// [`Iterator::product`]: ../../std/iter/trait.Iterator.html#method.product
 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
 pub trait Product<A = Self>: Sized {
     /// Method which takes an iterator and generates `Self` from the elements by
@@ -823,12 +823,12 @@ impl<T, U, E> Product<Result<U, E>> for Result<T, E>
 /// that behave this way because it allows for some significant optimizations.
 ///
 /// Note: In general, you should not use `FusedIterator` in generic bounds if
-/// you need a fused iterator. Instead, you should just call [`Iterator::fuse()`]
+/// you need a fused iterator. Instead, you should just call [`Iterator::fuse`]
 /// on the iterator. If the iterator is already fused, the additional [`Fuse`]
 /// wrapper will be a no-op with no performance penalty.
 ///
 /// [`None`]: ../../std/option/enum.Option.html#variant.None
-/// [`Iterator::fuse()`]: ../../std/iter/trait.Iterator.html#method.fuse
+/// [`Iterator::fuse`]: ../../std/iter/trait.Iterator.html#method.fuse
 /// [`Fuse`]: ../../std/iter/struct.Fuse.html
 #[unstable(feature = "fused", issue = "35602")]
 pub trait FusedIterator: Iterator {}
@@ -848,11 +848,11 @@ impl<'a, I: FusedIterator + ?Sized> FusedIterator for &'a mut I {}
 /// # Safety
 ///
 /// This trait must only be implemented when the contract is upheld.
-/// Consumers of this trait must inspect [`.size_hint()`]’s upper bound.
+/// Consumers of this trait must inspect [`.size_hint`]’s upper bound.
 ///
 /// [`None`]: ../../std/option/enum.Option.html#variant.None
 /// [`usize::MAX`]: ../../std/usize/constant.MAX.html
-/// [`.size_hint()`]: ../../std/iter/trait.Iterator.html#method.size_hint
+/// [`.size_hint`]: ../../std/iter/trait.Iterator.html#method.size_hint
 #[unstable(feature = "trusted_len", issue = "37572")]
 pub unsafe trait TrustedLen : Iterator {}
 
diff --git a/src/libcore/iter_private.rs b/src/libcore/iter_private.rs
index bc1aaa09f3d..c4d54d2c7b8 100644
--- a/src/libcore/iter_private.rs
+++ b/src/libcore/iter_private.rs
@@ -22,7 +22,7 @@
 #[doc(hidden)]
 pub unsafe trait TrustedRandomAccess : ExactSizeIterator {
     unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item;
-    /// Return `true` if getting an iterator element may have
+    /// Returns `true` if getting an iterator element may have
     /// side effects. Remember to take inner iterators into account.
     fn may_have_side_effect() -> bool;
 }
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 3d124a8aa8b..af613427493 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -71,26 +71,27 @@
 #![feature(asm)]
 #![feature(associated_type_defaults)]
 #![feature(cfg_target_feature)]
+#![feature(cfg_target_has_atomic)]
 #![feature(concat_idents)]
 #![feature(const_fn)]
-#![feature(cfg_target_has_atomic)]
 #![feature(custom_attribute)]
 #![feature(fundamental)]
+#![feature(i128_type)]
 #![feature(inclusive_range_syntax)]
 #![feature(intrinsics)]
 #![feature(lang_items)]
+#![feature(never_type)]
 #![feature(no_core)]
 #![feature(on_unimplemented)]
 #![feature(optin_builtin_traits)]
-#![feature(unwind_attributes)]
+#![feature(prelude_import)]
 #![feature(repr_simd, platform_intrinsics)]
 #![feature(rustc_attrs)]
 #![feature(specialization)]
 #![feature(staged_api)]
 #![feature(unboxed_closures)]
-#![feature(never_type)]
-#![feature(i128_type)]
-#![feature(prelude_import)]
+#![feature(untagged_unions)]
+#![feature(unwind_attributes)]
 
 #[prelude_import]
 #[allow(unused)]
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index b22f7fa1707..2a28d108df7 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -90,10 +90,10 @@ macro_rules! assert {
 /// On panic, this macro will print the values of the expressions with their
 /// debug representations.
 ///
-/// Like [`assert!()`], this macro has a second version, where a custom
+/// Like [`assert!`], this macro has a second version, where a custom
 /// panic message can be provided.
 ///
-/// [`assert!()`]: macro.assert.html
+/// [`assert!`]: macro.assert.html
 ///
 /// # Examples
 ///
@@ -337,27 +337,20 @@ macro_rules! try {
 
 /// Write formatted data into a buffer
 ///
-/// This macro accepts a 'writer' (any value with a `write_fmt` method), a format string, and a
-/// list of arguments to format.
-///
-/// The `write_fmt` method usually comes from an implementation of [`std::fmt::Write`][fmt_write]
-/// or [`std::io::Write`][io_write] traits. The term 'writer' refers to an implementation of one of
-/// these two traits.
-///
-/// Passed arguments will be formatted according to the specified format string and the resulting
-/// string will be passed to the writer.
-///
-/// See [`std::fmt`][fmt] for more information on format syntax.
-///
-/// `write!` returns whatever the 'write_fmt' method returns.
+/// This macro accepts a format string, a list of arguments, and a 'writer'. Arguments will be
+/// formatted according to the specified format string and the result will be passed to the writer.
+/// The writer may be any value with a `write_fmt` method; generally this comes from an
+/// implementation of either the [`std::fmt::Write`] or the [`std::io::Write`] trait. The macro
+/// returns whatever the 'write_fmt' method returns; commonly a [`std::fmt::Result`], or an
+/// [`io::Result`].
 ///
-/// Common return values include: [`fmt::Result`][fmt_result], [`io::Result`][io_result]
+/// See [`std::fmt`] for more information on the format string syntax.
 ///
-/// [fmt]: ../std/fmt/index.html
-/// [fmt_write]: ../std/fmt/trait.Write.html
-/// [io_write]: ../std/io/trait.Write.html
-/// [fmt_result]: ../std/fmt/type.Result.html
-/// [io_result]: ../std/io/type.Result.html
+/// [`std::fmt`]: ../std/fmt/index.html
+/// [`std::fmt::Write`]: ../std/fmt/trait.Write.html
+/// [`std::io::Write`]: ../std/io/trait.Write.html
+/// [`std::fmt::Result`]: ../std/fmt/type.Result.html
+/// [`io::Result`]: ../std/io/type.Result.html
 ///
 /// # Examples
 ///
@@ -396,27 +389,12 @@ macro_rules! write {
 /// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone
 /// (no additional CARRIAGE RETURN (`\r`/`U+000D`).
 ///
-/// This macro accepts a 'writer' (any value with a `write_fmt` method), a format string, and a
-/// list of arguments to format.
-///
-/// The `write_fmt` method usually comes from an implementation of [`std::fmt::Write`][fmt_write]
-/// or [`std::io::Write`][io_write] traits. The term 'writer' refers to an implementation of one of
-/// these two traits.
-///
-/// Passed arguments will be formatted according to the specified format string and the resulting
-/// string will be passed to the writer, along with the appended newline.
-///
-/// See [`std::fmt`][fmt] for more information on format syntax.
-///
-/// `write!` returns whatever the 'write_fmt' method returns.
+/// For more information, see [`write!`]. For information on the format string syntax, see
+/// [`std::fmt`].
 ///
-/// Common return values include: [`fmt::Result`][fmt_result], [`io::Result`][io_result]
+/// [`write!`]: macro.write.html
+/// [`std::fmt`]: ../std/fmt/index.html
 ///
-/// [fmt]: ../std/fmt/index.html
-/// [fmt_write]: ../std/fmt/trait.Write.html
-/// [io_write]: ../std/io/trait.Write.html
-/// [fmt_result]: ../std/fmt/type.Result.html
-/// [io_result]: ../std/io/type.Result.html
 ///
 /// # Examples
 ///
diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index 1e9eaaf5f32..393c01b0105 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -245,7 +245,7 @@ pub trait Unsize<T: ?Sized> {
 /// [`String`]'s buffer, leading to a double free.
 ///
 /// Generalizing the latter case, any type implementing [`Drop`] can't be `Copy`, because it's
-/// managing some resource besides its own [`size_of::<T>()`] bytes.
+/// managing some resource besides its own [`size_of::<T>`] bytes.
 ///
 /// If you try to implement `Copy` on a struct or enum containing non-`Copy` data, you will get
 /// the error [E0204].
@@ -262,7 +262,7 @@ pub trait Unsize<T: ?Sized> {
 /// [`Vec<T>`]: ../../std/vec/struct.Vec.html
 /// [`String`]: ../../std/string/struct.String.html
 /// [`Drop`]: ../../std/ops/trait.Drop.html
-/// [`size_of::<T>()`]: ../../std/mem/fn.size_of.html
+/// [`size_of::<T>`]: ../../std/mem/fn.size_of.html
 /// [`Clone`]: ../clone/trait.Clone.html
 /// [`String`]: ../../std/string/struct.String.html
 /// [`i32`]: ../../std/primitive.i32.html
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index f4ce4697d7c..f5cf3724d07 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -164,7 +164,7 @@ pub use intrinsics::transmute;
 /// [uninit]: fn.uninitialized.html
 /// [clone]: ../clone/trait.Clone.html
 /// [swap]: fn.swap.html
-/// [FFI]: ../../book/ffi.html
+/// [FFI]: ../../book/first-edition/ffi.html
 /// [box]: ../../std/boxed/struct.Box.html
 /// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw
 /// [ub]: ../../reference/behavior-considered-undefined.html
@@ -199,7 +199,7 @@ pub fn size_of<T>() -> usize {
 /// then `size_of_val` can be used to get the dynamically-known size.
 ///
 /// [slice]: ../../std/primitive.slice.html
-/// [trait object]: ../../book/trait-objects.html
+/// [trait object]: ../../book/first-edition/trait-objects.html
 ///
 /// # Examples
 ///
@@ -317,7 +317,7 @@ pub fn align_of_val<T: ?Sized>(val: &T) -> usize {
 /// many of the same caveats.
 ///
 /// [uninit]: fn.uninitialized.html
-/// [FFI]: ../../book/ffi.html
+/// [FFI]: ../../book/first-edition/ffi.html
 /// [ub]: ../../reference/behavior-considered-undefined.html
 ///
 /// # Examples
@@ -343,7 +343,7 @@ pub unsafe fn zeroed<T>() -> T {
 /// This is useful for [FFI] functions and initializing arrays sometimes,
 /// but should generally be avoided.
 ///
-/// [FFI]: ../../book/ffi.html
+/// [FFI]: ../../book/first-edition/ffi.html
 ///
 /// # Undefined behavior
 ///
@@ -525,7 +525,7 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
 /// it will not release any borrows, as borrows are based on lexical scope.
 ///
 /// This effectively does nothing for
-/// [types which implement `Copy`](../../book/ownership.html#copy-types),
+/// [types which implement `Copy`](../../book/first-edition/ownership.html#copy-types),
 /// e.g. integers. Such values are copied and _then_ moved into the function,
 /// so the value persists after this function call.
 ///
@@ -617,7 +617,7 @@ pub fn drop<T>(_x: T) { }
 /// the contained value.
 ///
 /// This function will unsafely assume the pointer `src` is valid for
-/// [`size_of::<U>()`][size_of] bytes by transmuting `&T` to `&U` and then reading
+/// [`size_of::<U>`][size_of] bytes by transmuting `&T` to `&U` and then reading
 /// the `&U`. It will also unsafely create a copy of the contained value instead of
 /// moving out of `src`.
 ///
diff --git a/src/libcore/num/bignum.rs b/src/libcore/num/bignum.rs
index a1f4630c304..b5553fb2947 100644
--- a/src/libcore/num/bignum.rs
+++ b/src/libcore/num/bignum.rs
@@ -19,7 +19,7 @@
 //! inputs, but we don't do so to avoid the code bloat. Each bignum is still
 //! tracked for the actual usages, so it normally doesn't matter.
 
-// This module is only for dec2flt and flt2dec, and only public because of libcoretest.
+// This module is only for dec2flt and flt2dec, and only public because of coretests.
 // It is not intended to ever be stabilized.
 #![doc(hidden)]
 #![unstable(feature = "core_private_bignum",
@@ -148,14 +148,14 @@ macro_rules! define_bignum {
                 $name { size: sz, base: base }
             }
 
-            /// Return the internal digits as a slice `[a, b, c, ...]` such that the numeric
+            /// Returns the internal digits as a slice `[a, b, c, ...]` such that the numeric
             /// value is `a + b * 2^W + c * 2^(2W) + ...` where `W` is the number of bits in
             /// the digit type.
             pub fn digits(&self) -> &[$ty] {
                 &self.base[..self.size]
             }
 
-            /// Return the `i`-th bit where bit 0 is the least significant one.
+            /// Returns the `i`-th bit where bit 0 is the least significant one.
             /// In other words, the bit with weight `2^i`.
             pub fn get_bit(&self, i: usize) -> u8 {
                 use mem;
@@ -166,7 +166,7 @@ macro_rules! define_bignum {
                 ((self.base[d] >> b) & 1) as u8
             }
 
-            /// Returns true if the bignum is zero.
+            /// Returns `true` if the bignum is zero.
             pub fn is_zero(&self) -> bool {
                 self.digits().iter().all(|&v| v == 0)
             }
diff --git a/src/libcore/num/dec2flt/algorithm.rs b/src/libcore/num/dec2flt/algorithm.rs
index 604bc7c10de..60dab943a3a 100644
--- a/src/libcore/num/dec2flt/algorithm.rs
+++ b/src/libcore/num/dec2flt/algorithm.rs
@@ -141,7 +141,7 @@ pub fn fast_path<T: RawFloat>(integral: &[u8], fractional: &[u8], e: i64) -> Opt
 ///
 /// It rounds ``f`` to a float with 64 bit significand and multiplies it by the best approximation
 /// of `10^e` (in the same floating point format). This is often enough to get the correct result.
-/// However, when the result is close to halfway between two adjecent (ordinary) floats, the
+/// However, when the result is close to halfway between two adjacent (ordinary) floats, the
 /// compound rounding error from multiplying two approximation means the result may be off by a
 /// few bits. When this happens, the iterative Algorithm R fixes things up.
 ///
@@ -392,7 +392,7 @@ fn underflow<T: RawFloat>(x: Big, v: Big, rem: Big) -> T {
     //
     // Therefore, when the rounded-off bits are != 0.5 ULP, they decide the rounding
     // on their own. When they are equal and the remainder is non-zero, the value still
-    // needs to be rounded up. Only when the rounded off bits are 1/2 and the remainer
+    // needs to be rounded up. Only when the rounded off bits are 1/2 and the remainder
     // is zero, we have a half-to-even situation.
     let bits = x.bit_length();
     let lsb = bits - T::sig_bits() as usize;
diff --git a/src/libcore/num/dec2flt/rawfp.rs b/src/libcore/num/dec2flt/rawfp.rs
index e3b58b6cc7c..45fa721a5a3 100644
--- a/src/libcore/num/dec2flt/rawfp.rs
+++ b/src/libcore/num/dec2flt/rawfp.rs
@@ -10,12 +10,12 @@
 
 //! Bit fiddling on positive IEEE 754 floats. Negative numbers aren't and needn't be handled.
 //! Normal floating point numbers have a canonical representation as (frac, exp) such that the
-//! value is 2^exp * (1 + sum(frac[N-i] / 2^i)) where N is the number of bits. Subnormals are
-//! slightly different and weird, but the same principle applies.
+//! value is 2<sup>exp</sup> * (1 + sum(frac[N-i] / 2<sup>i</sup>)) where N is the number of bits.
+//! Subnormals are slightly different and weird, but the same principle applies.
 //!
-//! Here, however, we represent them as (sig, k) with f positive, such that the value is f * 2^e.
-//! Besides making the "hidden bit" explicit, this changes the exponent by the so-called
-//! mantissa shift.
+//! Here, however, we represent them as (sig, k) with f positive, such that the value is f *
+//! 2<sup>e</sup>. Besides making the "hidden bit" explicit, this changes the exponent by the
+//! so-called mantissa shift.
 //!
 //! Put another way, normally floats are written as (1) but here they are written as (2):
 //!
@@ -94,7 +94,8 @@ pub trait RawFloat : Float + Copy + Debug + LowerExp
     /// represented, the other code in this module makes sure to never let that happen.
     fn from_int(x: u64) -> Self;
 
-    /// Get the value 10^e from a pre-computed table. Panics for e >= ceil_log5_of_max_sig().
+    /// Get the value 10<sup>e</sup> from a pre-computed table. Panics for e >=
+    /// ceil_log5_of_max_sig().
     fn short_fast_pow10(e: usize) -> Self;
 
     // FIXME Everything that follows should be associated constants, but taking the value of an
diff --git a/src/libcore/num/diy_float.rs b/src/libcore/num/diy_float.rs
index 11eea753f93..6635d95155f 100644
--- a/src/libcore/num/diy_float.rs
+++ b/src/libcore/num/diy_float.rs
@@ -10,7 +10,7 @@
 
 //! Extended precision "soft float", for internal use only.
 
-// This module is only for dec2flt and flt2dec, and only public because of libcoretest.
+// This module is only for dec2flt and flt2dec, and only public because of coretests.
 // It is not intended to ever be stabilized.
 #![doc(hidden)]
 #![unstable(feature = "core_private_diy_float",
diff --git a/src/libcore/num/flt2dec/mod.rs b/src/libcore/num/flt2dec/mod.rs
index f6c03a59f81..5123e42df61 100644
--- a/src/libcore/num/flt2dec/mod.rs
+++ b/src/libcore/num/flt2dec/mod.rs
@@ -118,7 +118,7 @@ provide a large enough buffer and `Part` array, and to assemble the final
 string from resulting `Part`s itself.
 
 All algorithms and formatting functions are accompanied by extensive tests
-in `coretest::num::flt2dec` module. It also shows how to use individual
+in `coretests::num::flt2dec` module. It also shows how to use individual
 functions.
 
 */
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 97ea6bb347b..f665cfdee77 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -90,7 +90,7 @@ impl<T: fmt::UpperHex> fmt::UpperHex for Wrapping<T> {
 
 mod wrapping;
 
-// All these modules are technically private and only exposed for libcoretest:
+// All these modules are technically private and only exposed for coretests:
 pub mod flt2dec;
 pub mod dec2flt;
 pub mod bignum;
@@ -177,7 +177,7 @@ macro_rules! checked_op {
 
 // `Int` + `SignedInt` implemented for signed integers
 macro_rules! int_impl {
-    ($ActualT:ident, $UnsignedT:ty, $BITS:expr,
+    ($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr,
      $add_with_overflow:path,
      $sub_with_overflow:path,
      $mul_with_overflow:path) => {
@@ -850,6 +850,17 @@ macro_rules! int_impl {
         /// ```
         #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[inline(always)]
+        #[cfg(not(stage0))]
+        pub fn wrapping_shl(self, rhs: u32) -> Self {
+            unsafe {
+                intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT)
+            }
+        }
+
+        /// Stage 0
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
+        #[inline(always)]
+        #[cfg(stage0)]
         pub fn wrapping_shl(self, rhs: u32) -> Self {
             self.overflowing_shl(rhs).0
         }
@@ -875,6 +886,17 @@ macro_rules! int_impl {
         /// ```
         #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[inline(always)]
+        #[cfg(not(stage0))]
+        pub fn wrapping_shr(self, rhs: u32) -> Self {
+            unsafe {
+                intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
+            }
+        }
+
+        /// Stage 0
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
+        #[inline(always)]
+        #[cfg(stage0)]
         pub fn wrapping_shr(self, rhs: u32) -> Self {
             self.overflowing_shr(rhs).0
         }
@@ -1089,6 +1111,15 @@ macro_rules! int_impl {
         /// ```
         #[inline]
         #[stable(feature = "wrapping", since = "1.7.0")]
+        #[cfg(not(stage0))]
+        pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
+            (self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
+        }
+
+        /// Stage 0
+        #[inline]
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[cfg(stage0)]
         pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
             (self << (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
         }
@@ -1111,6 +1142,15 @@ macro_rules! int_impl {
         /// ```
         #[inline]
         #[stable(feature = "wrapping", since = "1.7.0")]
+        #[cfg(not(stage0))]
+        pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
+            (self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
+        }
+
+        /// Stage 0
+        #[inline]
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[cfg(stage0)]
         pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
             (self >> (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
         }
@@ -1268,7 +1308,7 @@ macro_rules! int_impl {
 
 #[lang = "i8"]
 impl i8 {
-    int_impl! { i8, u8, 8,
+    int_impl! { i8, i8, u8, 8,
         intrinsics::add_with_overflow,
         intrinsics::sub_with_overflow,
         intrinsics::mul_with_overflow }
@@ -1276,7 +1316,7 @@ impl i8 {
 
 #[lang = "i16"]
 impl i16 {
-    int_impl! { i16, u16, 16,
+    int_impl! { i16, i16, u16, 16,
         intrinsics::add_with_overflow,
         intrinsics::sub_with_overflow,
         intrinsics::mul_with_overflow }
@@ -1284,7 +1324,7 @@ impl i16 {
 
 #[lang = "i32"]
 impl i32 {
-    int_impl! { i32, u32, 32,
+    int_impl! { i32, i32, u32, 32,
         intrinsics::add_with_overflow,
         intrinsics::sub_with_overflow,
         intrinsics::mul_with_overflow }
@@ -1292,7 +1332,7 @@ impl i32 {
 
 #[lang = "i64"]
 impl i64 {
-    int_impl! { i64, u64, 64,
+    int_impl! { i64, i64, u64, 64,
         intrinsics::add_with_overflow,
         intrinsics::sub_with_overflow,
         intrinsics::mul_with_overflow }
@@ -1300,7 +1340,7 @@ impl i64 {
 
 #[lang = "i128"]
 impl i128 {
-    int_impl! { i128, u128, 128,
+    int_impl! { i128, i128, u128, 128,
         intrinsics::add_with_overflow,
         intrinsics::sub_with_overflow,
         intrinsics::mul_with_overflow }
@@ -1309,7 +1349,7 @@ impl i128 {
 #[cfg(target_pointer_width = "16")]
 #[lang = "isize"]
 impl isize {
-    int_impl! { i16, u16, 16,
+    int_impl! { isize, i16, u16, 16,
         intrinsics::add_with_overflow,
         intrinsics::sub_with_overflow,
         intrinsics::mul_with_overflow }
@@ -1318,7 +1358,7 @@ impl isize {
 #[cfg(target_pointer_width = "32")]
 #[lang = "isize"]
 impl isize {
-    int_impl! { i32, u32, 32,
+    int_impl! { isize, i32, u32, 32,
         intrinsics::add_with_overflow,
         intrinsics::sub_with_overflow,
         intrinsics::mul_with_overflow }
@@ -1327,7 +1367,7 @@ impl isize {
 #[cfg(target_pointer_width = "64")]
 #[lang = "isize"]
 impl isize {
-    int_impl! { i64, u64, 64,
+    int_impl! { isize, i64, u64, 64,
         intrinsics::add_with_overflow,
         intrinsics::sub_with_overflow,
         intrinsics::mul_with_overflow }
@@ -1335,7 +1375,7 @@ impl isize {
 
 // `Int` + `UnsignedInt` implemented for unsigned integers
 macro_rules! uint_impl {
-    ($ActualT:ty, $BITS:expr,
+    ($SelfT:ty, $ActualT:ty, $BITS:expr,
      $ctpop:path,
      $ctlz:path,
      $cttz:path,
@@ -1978,6 +2018,17 @@ macro_rules! uint_impl {
         /// ```
         #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[inline(always)]
+        #[cfg(not(stage0))]
+        pub fn wrapping_shl(self, rhs: u32) -> Self {
+            unsafe {
+                intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT)
+            }
+        }
+
+        /// Stage 0
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
+        #[inline(always)]
+        #[cfg(stage0)]
         pub fn wrapping_shl(self, rhs: u32) -> Self {
             self.overflowing_shl(rhs).0
         }
@@ -2003,6 +2054,17 @@ macro_rules! uint_impl {
         /// ```
         #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[inline(always)]
+        #[cfg(not(stage0))]
+        pub fn wrapping_shr(self, rhs: u32) -> Self {
+            unsafe {
+                intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
+            }
+        }
+
+        /// Stage 0
+        #[stable(feature = "num_wrapping", since = "1.2.0")]
+        #[inline(always)]
+        #[cfg(stage0)]
         pub fn wrapping_shr(self, rhs: u32) -> Self {
             self.overflowing_shr(rhs).0
         }
@@ -2170,6 +2232,15 @@ macro_rules! uint_impl {
         /// ```
         #[inline]
         #[stable(feature = "wrapping", since = "1.7.0")]
+        #[cfg(not(stage0))]
+        pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
+            (self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
+        }
+
+        /// Stage 0
+        #[inline]
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[cfg(stage0)]
         pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
             (self << (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
         }
@@ -2192,6 +2263,16 @@ macro_rules! uint_impl {
         /// ```
         #[inline]
         #[stable(feature = "wrapping", since = "1.7.0")]
+        #[cfg(not(stage0))]
+        pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
+            (self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
+
+        }
+
+        /// Stage 0
+        #[inline]
+        #[stable(feature = "wrapping", since = "1.7.0")]
+        #[cfg(stage0)]
         pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
             (self >> (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
         }
@@ -2292,7 +2373,7 @@ macro_rules! uint_impl {
 
 #[lang = "u8"]
 impl u8 {
-    uint_impl! { u8, 8,
+    uint_impl! { u8, u8, 8,
         intrinsics::ctpop,
         intrinsics::ctlz,
         intrinsics::cttz,
@@ -2304,7 +2385,7 @@ impl u8 {
 
 #[lang = "u16"]
 impl u16 {
-    uint_impl! { u16, 16,
+    uint_impl! { u16, u16, 16,
         intrinsics::ctpop,
         intrinsics::ctlz,
         intrinsics::cttz,
@@ -2316,7 +2397,7 @@ impl u16 {
 
 #[lang = "u32"]
 impl u32 {
-    uint_impl! { u32, 32,
+    uint_impl! { u32, u32, 32,
         intrinsics::ctpop,
         intrinsics::ctlz,
         intrinsics::cttz,
@@ -2328,7 +2409,7 @@ impl u32 {
 
 #[lang = "u64"]
 impl u64 {
-    uint_impl! { u64, 64,
+    uint_impl! { u64, u64, 64,
         intrinsics::ctpop,
         intrinsics::ctlz,
         intrinsics::cttz,
@@ -2340,7 +2421,7 @@ impl u64 {
 
 #[lang = "u128"]
 impl u128 {
-    uint_impl! { u128, 128,
+    uint_impl! { u128, u128, 128,
         intrinsics::ctpop,
         intrinsics::ctlz,
         intrinsics::cttz,
@@ -2353,7 +2434,7 @@ impl u128 {
 #[cfg(target_pointer_width = "16")]
 #[lang = "usize"]
 impl usize {
-    uint_impl! { u16, 16,
+    uint_impl! { usize, u16, 16,
         intrinsics::ctpop,
         intrinsics::ctlz,
         intrinsics::cttz,
@@ -2365,7 +2446,7 @@ impl usize {
 #[cfg(target_pointer_width = "32")]
 #[lang = "usize"]
 impl usize {
-    uint_impl! { u32, 32,
+    uint_impl! { usize, u32, 32,
         intrinsics::ctpop,
         intrinsics::ctlz,
         intrinsics::cttz,
@@ -2378,7 +2459,7 @@ impl usize {
 #[cfg(target_pointer_width = "64")]
 #[lang = "usize"]
 impl usize {
-    uint_impl! { u64, 64,
+    uint_impl! { usize, u64, 64,
         intrinsics::ctpop,
         intrinsics::ctlz,
         intrinsics::cttz,
@@ -2390,11 +2471,11 @@ impl usize {
 
 /// A classification of floating point numbers.
 ///
-/// This `enum` is used as the return type for [`f32::classify()`] and [`f64::classify()`]. See
+/// This `enum` is used as the return type for [`f32::classify`] and [`f64::classify`]. See
 /// their documentation for more.
 ///
-/// [`f32::classify()`]: ../../std/primitive.f32.html#method.classify
-/// [`f64::classify()`]: ../../std/primitive.f64.html#method.classify
+/// [`f32::classify`]: ../../std/primitive.f32.html#method.classify
+/// [`f64::classify`]: ../../std/primitive.f64.html#method.classify
 ///
 /// # Examples
 ///
@@ -2487,17 +2568,17 @@ pub trait Float: Sized {
                                  implementable outside the standard library")]
     fn one() -> Self;
 
-    /// Returns true if this value is NaN and false otherwise.
+    /// Returns `true` if this value is NaN and false otherwise.
     #[stable(feature = "core", since = "1.6.0")]
     fn is_nan(self) -> bool;
-    /// Returns true if this value is positive infinity or negative infinity and
+    /// Returns `true` if this value is positive infinity or negative infinity and
     /// false otherwise.
     #[stable(feature = "core", since = "1.6.0")]
     fn is_infinite(self) -> bool;
-    /// Returns true if this number is neither infinite nor NaN.
+    /// Returns `true` if this number is neither infinite nor NaN.
     #[stable(feature = "core", since = "1.6.0")]
     fn is_finite(self) -> bool;
-    /// Returns true if this number is neither zero, infinite, denormal, or NaN.
+    /// Returns `true` if this number is neither zero, infinite, denormal, or NaN.
     #[stable(feature = "core", since = "1.6.0")]
     fn is_normal(self) -> bool;
     /// Returns the category that this number falls into.
@@ -2591,7 +2672,7 @@ macro_rules! same_sign_try_from_int_impl {
     ($storage:ty, $target:ty, $($source:ty),*) => {$(
         #[unstable(feature = "try_from", issue = "33417")]
         impl TryFrom<$source> for $target {
-            type Err = TryFromIntError;
+            type Error = TryFromIntError;
 
             fn try_from(u: $source) -> Result<$target, TryFromIntError> {
                 let min = <$target as FromStrRadixHelper>::min_value() as $storage;
@@ -2623,7 +2704,7 @@ macro_rules! cross_sign_from_int_impl {
     ($unsigned:ty, $($signed:ty),*) => {$(
         #[unstable(feature = "try_from", issue = "33417")]
         impl TryFrom<$unsigned> for $signed {
-            type Err = TryFromIntError;
+            type Error = TryFromIntError;
 
             fn try_from(u: $unsigned) -> Result<$signed, TryFromIntError> {
                 let max = <$signed as FromStrRadixHelper>::max_value() as u128;
@@ -2637,7 +2718,7 @@ macro_rules! cross_sign_from_int_impl {
 
         #[unstable(feature = "try_from", issue = "33417")]
         impl TryFrom<$signed> for $unsigned {
-            type Err = TryFromIntError;
+            type Error = TryFromIntError;
 
             fn try_from(u: $signed) -> Result<$unsigned, TryFromIntError> {
                 let max = <$unsigned as FromStrRadixHelper>::max_value() as u128;
@@ -2756,9 +2837,9 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par
 /// An error which can be returned when parsing an integer.
 ///
 /// This error is used as the error type for the `from_str_radix()` functions
-/// on the primitive integer types, such as [`i8::from_str_radix()`].
+/// on the primitive integer types, such as [`i8::from_str_radix`].
 ///
-/// [`i8::from_str_radix()`]: ../../std/primitive.i8.html#method.from_str_radix
+/// [`i8::from_str_radix`]: ../../std/primitive.i8.html#method.from_str_radix
 #[derive(Debug, Clone, PartialEq, Eq)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct ParseIntError {
diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs
index 59bcb340ec9..d203b68c0df 100644
--- a/src/libcore/ops.rs
+++ b/src/libcore/ops.rs
@@ -30,7 +30,7 @@
 //! contexts involving built-in types, this is usually not a problem.
 //! However, using these operators in generic code, requires some
 //! attention if values have to be reused as opposed to letting the operators
-//! consume them. One option is to occasionally use [`clone()`].
+//! consume them. One option is to occasionally use [`clone`].
 //! Another option is to rely on the types involved providing additional
 //! operator implementations for references. For example, for a user-defined
 //! type `T` which is supposed to support addition, it is probably a good
@@ -143,7 +143,7 @@
 //! [`FnOnce`]: trait.FnOnce.html
 //! [`Add`]: trait.Add.html
 //! [`Sub`]: trait.Sub.html
-//! [`clone()`]: ../clone/trait.Clone.html#tymethod.clone
+//! [`clone`]: ../clone/trait.Clone.html#tymethod.clone
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -196,7 +196,7 @@ pub trait Drop {
     fn drop(&mut self);
 }
 
-/// The `Add` trait is used to specify the functionality of `+`.
+/// The addition operator `+`.
 ///
 /// # Examples
 ///
@@ -269,7 +269,7 @@ macro_rules! add_impl {
 
 add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 
-/// The `Sub` trait is used to specify the functionality of `-`.
+/// The subtraction operator `-`.
 ///
 /// # Examples
 ///
@@ -342,7 +342,7 @@ macro_rules! sub_impl {
 
 sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 
-/// The `Mul` trait is used to specify the functionality of `*`.
+/// The multiplication operator `*`.
 ///
 /// # Examples
 ///
@@ -464,7 +464,7 @@ macro_rules! mul_impl {
 
 mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 
-/// The `Div` trait is used to specify the functionality of `/`.
+/// The division operator `/`.
 ///
 /// # Examples
 ///
@@ -609,7 +609,7 @@ macro_rules! div_impl_float {
 
 div_impl_float! { f32 f64 }
 
-/// The `Rem` trait is used to specify the functionality of `%`.
+/// The remainder operator `%`.
 ///
 /// # Examples
 ///
@@ -689,7 +689,7 @@ macro_rules! rem_impl_float {
 
 rem_impl_float! { f32 f64 }
 
-/// The `Neg` trait is used to specify the functionality of unary `-`.
+/// The unary negation operator `-`.
 ///
 /// # Examples
 ///
@@ -768,7 +768,7 @@ macro_rules! neg_impl_unsigned {
 // neg_impl_unsigned! { usize u8 u16 u32 u64 }
 neg_impl_numeric! { isize i8 i16 i32 i64 i128 f32 f64 }
 
-/// The `Not` trait is used to specify the functionality of unary `!`.
+/// The unary logical negation operator `!`.
 ///
 /// # Examples
 ///
@@ -826,7 +826,7 @@ macro_rules! not_impl {
 
 not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
-/// The `BitAnd` trait is used to specify the functionality of `&`.
+/// The bitwise AND operator `&`.
 ///
 /// # Examples
 ///
@@ -909,7 +909,7 @@ macro_rules! bitand_impl {
 
 bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
-/// The `BitOr` trait is used to specify the functionality of `|`.
+/// The bitwise OR operator `|`.
 ///
 /// # Examples
 ///
@@ -992,7 +992,7 @@ macro_rules! bitor_impl {
 
 bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
-/// The `BitXor` trait is used to specify the functionality of `^`.
+/// The bitwise XOR operator `^`.
 ///
 /// # Examples
 ///
@@ -1078,7 +1078,7 @@ macro_rules! bitxor_impl {
 
 bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
-/// The `Shl` trait is used to specify the functionality of `<<`.
+/// The left shift operator `<<`.
 ///
 /// # Examples
 ///
@@ -1181,7 +1181,7 @@ macro_rules! shl_impl_all {
 
 shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
 
-/// The `Shr` trait is used to specify the functionality of `>>`.
+/// The right shift operator `>>`.
 ///
 /// # Examples
 ///
@@ -1284,7 +1284,7 @@ macro_rules! shr_impl_all {
 
 shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
 
-/// The `AddAssign` trait is used to specify the functionality of `+=`.
+/// The addition assignment operator `+=`.
 ///
 /// # Examples
 ///
@@ -1340,7 +1340,7 @@ macro_rules! add_assign_impl {
 
 add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 
-/// The `SubAssign` trait is used to specify the functionality of `-=`.
+/// The subtraction assignment operator `-=`.
 ///
 /// # Examples
 ///
@@ -1396,7 +1396,7 @@ macro_rules! sub_assign_impl {
 
 sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 
-/// The `MulAssign` trait is used to specify the functionality of `*=`.
+/// The multiplication assignment operator `*=`.
 ///
 /// # Examples
 ///
@@ -1441,7 +1441,7 @@ macro_rules! mul_assign_impl {
 
 mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 
-/// The `DivAssign` trait is used to specify the functionality of `/=`.
+/// The division assignment operator `/=`.
 ///
 /// # Examples
 ///
@@ -1485,7 +1485,7 @@ macro_rules! div_assign_impl {
 
 div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 
-/// The `RemAssign` trait is used to specify the functionality of `%=`.
+/// The remainder assignment operator `%=`.
 ///
 /// # Examples
 ///
@@ -1529,7 +1529,7 @@ macro_rules! rem_assign_impl {
 
 rem_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 
-/// The `BitAndAssign` trait is used to specify the functionality of `&=`.
+/// The bitwise AND assignment operator `&=`.
 ///
 /// # Examples
 ///
@@ -1615,7 +1615,7 @@ macro_rules! bitand_assign_impl {
 
 bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
-/// The `BitOrAssign` trait is used to specify the functionality of `|=`.
+/// The bitwise OR assignment operator `|=`.
 ///
 /// # Examples
 ///
@@ -1659,7 +1659,7 @@ macro_rules! bitor_assign_impl {
 
 bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
-/// The `BitXorAssign` trait is used to specify the functionality of `^=`.
+/// The bitwise XOR assignment operator `^=`.
 ///
 /// # Examples
 ///
@@ -1703,7 +1703,7 @@ macro_rules! bitxor_assign_impl {
 
 bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
-/// The `ShlAssign` trait is used to specify the functionality of `<<=`.
+/// The left shift assignment operator `<<=`.
 ///
 /// # Examples
 ///
@@ -1768,7 +1768,7 @@ macro_rules! shl_assign_impl_all {
 
 shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
 
-/// The `ShrAssign` trait is used to specify the functionality of `>>=`.
+/// The right shift assignment operator `>>=`.
 ///
 /// # Examples
 ///
@@ -2027,7 +2027,7 @@ impl fmt::Debug for RangeFull {
 /// A (half-open) range which is bounded at both ends: { x | start <= x < end }.
 /// Use `start..end` (two dots) for its shorthand.
 ///
-/// See the [`contains()`](#method.contains) method for its characterization.
+/// See the [`contains`](#method.contains) method for its characterization.
 ///
 /// # Examples
 ///
@@ -2085,7 +2085,7 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
 /// A range which is only bounded below: { x | start <= x }.
 /// Use `start..` for its shorthand.
 ///
-/// See the [`contains()`](#method.contains) method for its characterization.
+/// See the [`contains`](#method.contains) method for its characterization.
 ///
 /// Note: Currently, no overflow checking is done for the iterator
 /// implementation; if you use an integer range and the integer overflows, it
@@ -2141,7 +2141,7 @@ impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
 /// A range which is only bounded above: { x | x < end }.
 /// Use `..end` (two dots) for its shorthand.
 ///
-/// See the [`contains()`](#method.contains) method for its characterization.
+/// See the [`contains`](#method.contains) method for its characterization.
 ///
 /// It cannot serve as an iterator because it doesn't have a starting point.
 ///
@@ -2207,7 +2207,7 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
 /// An inclusive range which is bounded at both ends: { x | start <= x <= end }.
 /// Use `start...end` (three dots) for its shorthand.
 ///
-/// See the [`contains()`](#method.contains) method for its characterization.
+/// See the [`contains`](#method.contains) method for its characterization.
 ///
 /// # Examples
 ///
@@ -2293,7 +2293,7 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
 /// An inclusive range which is only bounded above: { x | x <= end }.
 /// Use `...end` (three dots) for its shorthand.
 ///
-/// See the [`contains()`](#method.contains) method for its characterization.
+/// See the [`contains`](#method.contains) method for its characterization.
 ///
 /// It cannot serve as an iterator because it doesn't have a starting point.
 ///
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 9df8350d90f..1a48f277625 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -219,12 +219,14 @@ impl<T> Option<T> {
     ///
     /// # Examples
     ///
-    /// Convert an `Option<String>` into an `Option<usize>`, preserving the original.
+    /// Convert an `Option<`[`String`]`>` into an `Option<`[`usize`]`>`, preserving the original.
     /// The [`map`] method takes the `self` argument by value, consuming the original,
     /// so this technique uses `as_ref` to first take an `Option` to a reference
     /// to the value inside the original.
     ///
     /// [`map`]: enum.Option.html#method.map
+    /// [`String`]: ../../std/string/struct.String.html
+    /// [`usize`]: ../../std/primitive.usize.html
     ///
     /// ```
     /// let num_as_str: Option<String> = Some("10".to_string());
@@ -271,9 +273,11 @@ impl<T> Option<T> {
     ///
     /// # Panics
     ///
-    /// Panics if the value is a `None` with a custom panic message provided by
+    /// Panics if the value is a [`None`] with a custom panic message provided by
     /// `msg`.
     ///
+    /// [`None`]: #variant.None
+    ///
     /// # Examples
     ///
     /// ```
@@ -302,7 +306,9 @@ impl<T> Option<T> {
     ///
     /// # Panics
     ///
-    /// Panics if the self value equals `None`.
+    /// Panics if the self value equals [`None`].
+    ///
+    /// [`None`]: #variant.None
     ///
     /// # Examples
     ///
@@ -367,7 +373,10 @@ impl<T> Option<T> {
     ///
     /// # Examples
     ///
-    /// Convert an `Option<String>` into an `Option<usize>`, consuming the original:
+    /// Convert an `Option<`[`String`]`>` into an `Option<`[`usize`]`>`, consuming the original:
+    ///
+    /// [`String`]: ../../std/string/struct.String.html
+    /// [`usize`]: ../../std/primitive.usize.html
     ///
     /// ```
     /// let maybe_some_string = Some(String::from("Hello, World!"));
@@ -885,9 +894,15 @@ impl<A> ExactSizeIterator for Item<A> {}
 impl<A> FusedIterator for Item<A> {}
 unsafe impl<A> TrustedLen for Item<A> {}
 
-/// An iterator over a reference of the contained item in an [`Option`].
+/// An iterator over a reference to the [`Some`] variant of an [`Option`].
+///
+/// The iterator yields one value if the [`Option`] is a [`Some`], otherwise none.
+///
+/// This `struct` is created by the [`Option::iter`] function.
 ///
 /// [`Option`]: enum.Option.html
+/// [`Some`]: enum.Option.html#variant.Some
+/// [`Option::iter`]: enum.Option.html#method.iter
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
 pub struct Iter<'a, A: 'a> { inner: Item<&'a A> }
@@ -924,9 +939,15 @@ impl<'a, A> Clone for Iter<'a, A> {
     }
 }
 
-/// An iterator over a mutable reference of the contained item in an [`Option`].
+/// An iterator over a mutable reference to the [`Some`] variant of an [`Option`].
+///
+/// The iterator yields one value if the [`Option`] is a [`Some`], otherwise none.
+///
+/// This `struct` is created by the [`Option::iter_mut`] function.
 ///
 /// [`Option`]: enum.Option.html
+/// [`Some`]: enum.Option.html#variant.Some
+/// [`Option::iter_mut`]: enum.Option.html#method.iter_mut
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
 pub struct IterMut<'a, A: 'a> { inner: Item<&'a mut A> }
@@ -955,9 +976,15 @@ impl<'a, A> FusedIterator for IterMut<'a, A> {}
 #[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<'a, A> TrustedLen for IterMut<'a, A> {}
 
-/// An iterator over the item contained inside an [`Option`].
+/// An iterator over the value in [`Some`] variant of an [`Option`].
+///
+/// The iterator yields one value if the [`Option`] is a [`Some`], otherwise none.
+///
+/// This `struct` is created by the [`Option::into_iter`] function.
 ///
 /// [`Option`]: enum.Option.html
+/// [`Some`]: enum.Option.html#variant.Some
+/// [`Option::into_iter`]: enum.Option.html#method.into_iter
 #[derive(Clone, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<A> { inner: Item<A> }
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 260fdab9d58..04480fc5d31 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -37,9 +37,38 @@ pub use intrinsics::copy;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use intrinsics::write_bytes;
 
+#[cfg(stage0)]
 #[stable(feature = "drop_in_place", since = "1.8.0")]
 pub use intrinsics::drop_in_place;
 
+#[cfg(not(stage0))]
+/// Executes the destructor (if any) of the pointed-to value.
+///
+/// This has two use cases:
+///
+/// * It is *required* to use `drop_in_place` to drop unsized types like
+///   trait objects, because they can't be read out onto the stack and
+///   dropped normally.
+///
+/// * It is friendlier to the optimizer to do this over `ptr::read` when
+///   dropping manually allocated memory (e.g. when writing Box/Rc/Vec),
+///   as the compiler doesn't need to prove that it's sound to elide the
+///   copy.
+///
+/// # Undefined Behavior
+///
+/// This has all the same safety problems as `ptr::read` with respect to
+/// invalid pointers, types, and double drops.
+#[stable(feature = "drop_in_place", since = "1.8.0")]
+#[lang="drop_in_place"]
+#[inline]
+#[allow(unconditional_recursion)]
+pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+    // Code here does not matter - this is replaced by the
+    // real drop glue by the compiler.
+    drop_in_place(to_drop);
+}
+
 /// Creates a null raw pointer.
 ///
 /// # Examples
@@ -161,8 +190,6 @@ pub unsafe fn read<T>(src: *const T) -> T {
 /// Basic usage:
 ///
 /// ```
-/// #![feature(ptr_unaligned)]
-///
 /// let x = 12;
 /// let y = &x as *const i32;
 ///
@@ -171,7 +198,7 @@ pub unsafe fn read<T>(src: *const T) -> T {
 /// }
 /// ```
 #[inline(always)]
-#[unstable(feature = "ptr_unaligned", issue = "37955")]
+#[stable(feature = "ptr_unaligned", since = "1.17.0")]
 pub unsafe fn read_unaligned<T>(src: *const T) -> T {
     let mut tmp: T = mem::uninitialized();
     copy_nonoverlapping(src as *const u8,
@@ -191,9 +218,8 @@ pub unsafe fn read_unaligned<T>(src: *const T) -> T {
 /// allocations or resources, so care must be taken not to overwrite an object
 /// that should be dropped.
 ///
-/// It does not immediately drop the contents of `src` either; it is rather
-/// *moved* into the memory location `dst` and will be dropped whenever that
-/// location goes out of scope.
+/// Additionally, it does not drop `src`. Semantically, `src` is moved into the
+/// location pointed to by `dst`.
 ///
 /// This is appropriate for initializing uninitialized memory, or overwriting
 /// memory that has previously been `read` from.
@@ -233,6 +259,9 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
 /// allocations or resources, so care must be taken not to overwrite an object
 /// that should be dropped.
 ///
+/// Additionally, it does not drop `src`. Semantically, `src` is moved into the
+/// location pointed to by `dst`.
+///
 /// This is appropriate for initializing uninitialized memory, or overwriting
 /// memory that has previously been `read` from.
 ///
@@ -241,8 +270,6 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
 /// Basic usage:
 ///
 /// ```
-/// #![feature(ptr_unaligned)]
-///
 /// let mut x = 0;
 /// let y = &mut x as *mut i32;
 /// let z = 12;
@@ -253,7 +280,7 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
 /// }
 /// ```
 #[inline]
-#[unstable(feature = "ptr_unaligned", issue = "37955")]
+#[stable(feature = "ptr_unaligned", since = "1.17.0")]
 pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
     copy_nonoverlapping(&src as *const T as *const u8,
                         dst as *mut u8,
@@ -353,7 +380,7 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
 
 #[lang = "const_ptr"]
 impl<T: ?Sized> *const T {
-    /// Returns true if the pointer is null.
+    /// Returns `true` if the pointer is null.
     ///
     /// # Examples
     ///
@@ -407,7 +434,7 @@ impl<T: ?Sized> *const T {
     }
 
     /// Calculates the offset from a pointer. `count` is in units of T; e.g. a
-    /// `count` of 3 represents a pointer offset of `3 * sizeof::<T>()` bytes.
+    /// `count` of 3 represents a pointer offset of `3 * size_of::<T>()` bytes.
     ///
     /// # Safety
     ///
@@ -437,7 +464,7 @@ impl<T: ?Sized> *const T {
 
     /// Calculates the offset from a pointer using wrapping arithmetic.
     /// `count` is in units of T; e.g. a `count` of 3 represents a pointer
-    /// offset of `3 * sizeof::<T>()` bytes.
+    /// offset of `3 * size_of::<T>()` bytes.
     ///
     /// # Safety
     ///
@@ -473,11 +500,49 @@ impl<T: ?Sized> *const T {
             intrinsics::arith_offset(self, count)
         }
     }
+
+    /// Calculates the distance between two pointers. The returned value is in
+    /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
+    ///
+    /// If the address different between the two pointers ia not a multiple of
+    /// `mem::size_of::<T>()` then the result of the division is rounded towards
+    /// zero.
+    ///
+    /// This function returns `None` if `T` is a zero-sized typed.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(offset_to)]
+    ///
+    /// fn main() {
+    ///     let a = [0; 5];
+    ///     let ptr1: *const i32 = &a[1];
+    ///     let ptr2: *const i32 = &a[3];
+    ///     assert_eq!(ptr1.offset_to(ptr2), Some(2));
+    ///     assert_eq!(ptr2.offset_to(ptr1), Some(-2));
+    ///     assert_eq!(unsafe { ptr1.offset(2) }, ptr2);
+    ///     assert_eq!(unsafe { ptr2.offset(-2) }, ptr1);
+    /// }
+    /// ```
+    #[unstable(feature = "offset_to", issue = "41079")]
+    #[inline]
+    pub fn offset_to(self, other: *const T) -> Option<isize> where T: Sized {
+        let size = mem::size_of::<T>();
+        if size == 0 {
+            None
+        } else {
+            let diff = (other as isize).wrapping_sub(self as isize);
+            Some(diff / size as isize)
+        }
+    }
 }
 
 #[lang = "mut_ptr"]
 impl<T: ?Sized> *mut T {
-    /// Returns true if the pointer is null.
+    /// Returns `true` if the pointer is null.
     ///
     /// # Examples
     ///
@@ -531,7 +596,7 @@ impl<T: ?Sized> *mut T {
     }
 
     /// Calculates the offset from a pointer. `count` is in units of T; e.g. a
-    /// `count` of 3 represents a pointer offset of `3 * sizeof::<T>()` bytes.
+    /// `count` of 3 represents a pointer offset of `3 * size_of::<T>()` bytes.
     ///
     /// # Safety
     ///
@@ -560,7 +625,7 @@ impl<T: ?Sized> *mut T {
 
     /// Calculates the offset from a pointer using wrapping arithmetic.
     /// `count` is in units of T; e.g. a `count` of 3 represents a pointer
-    /// offset of `3 * sizeof::<T>()` bytes.
+    /// offset of `3 * size_of::<T>()` bytes.
     ///
     /// # Safety
     ///
@@ -626,6 +691,44 @@ impl<T: ?Sized> *mut T {
             Some(&mut *self)
         }
     }
+
+    /// Calculates the distance between two pointers. The returned value is in
+    /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
+    ///
+    /// If the address different between the two pointers ia not a multiple of
+    /// `mem::size_of::<T>()` then the result of the division is rounded towards
+    /// zero.
+    ///
+    /// This function returns `None` if `T` is a zero-sized typed.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(offset_to)]
+    ///
+    /// fn main() {
+    ///     let mut a = [0; 5];
+    ///     let ptr1: *mut i32 = &mut a[1];
+    ///     let ptr2: *mut i32 = &mut a[3];
+    ///     assert_eq!(ptr1.offset_to(ptr2), Some(2));
+    ///     assert_eq!(ptr2.offset_to(ptr1), Some(-2));
+    ///     assert_eq!(unsafe { ptr1.offset(2) }, ptr2);
+    ///     assert_eq!(unsafe { ptr2.offset(-2) }, ptr1);
+    /// }
+    /// ```
+    #[unstable(feature = "offset_to", issue = "41079")]
+    #[inline]
+    pub fn offset_to(self, other: *const T) -> Option<isize> where T: Sized {
+        let size = mem::size_of::<T>();
+        if size == 0 {
+            None
+        } else {
+            let diff = (other as isize).wrapping_sub(self as isize);
+            Some(diff / size as isize)
+        }
+    }
 }
 
 // Equality for pointers
@@ -660,7 +763,6 @@ impl<T: ?Sized> Eq for *mut T {}
 /// # Examples
 ///
 /// ```
-/// #![feature(ptr_eq)]
 /// use std::ptr;
 ///
 /// let five = 5;
@@ -675,7 +777,7 @@ impl<T: ?Sized> Eq for *mut T {}
 /// assert!(ptr::eq(five_ref, same_five_ref));
 /// assert!(!ptr::eq(five_ref, other_five_ref));
 /// ```
-#[unstable(feature = "ptr_eq", reason = "newly added", issue = "36497")]
+#[stable(feature = "ptr_eq", since = "1.17.0")]
 #[inline]
 pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
     a == b
@@ -970,12 +1072,20 @@ impl<T: ?Sized> Shared<T> {
     /// # Safety
     ///
     /// `ptr` must be non-null.
-    pub unsafe fn new(ptr: *mut T) -> Self {
+    pub unsafe fn new(ptr: *const T) -> Self {
         Shared { pointer: NonZero::new(ptr), _marker: PhantomData }
     }
 }
 
 #[unstable(feature = "shared", issue = "27730")]
+impl<T: ?Sized> Shared<T> {
+    /// Acquires the underlying pointer as a `*mut` pointer.
+    pub unsafe fn as_mut_ptr(&self) -> *mut T {
+        **self as _
+    }
+}
+
+#[unstable(feature = "shared", issue = "27730")]
 impl<T: ?Sized> Clone for Shared<T> {
     fn clone(&self) -> Self {
         *self
@@ -990,10 +1100,10 @@ impl<T: ?Sized, U: ?Sized> CoerceUnsized<Shared<U>> for Shared<T> where T: Unsiz
 
 #[unstable(feature = "shared", issue = "27730")]
 impl<T: ?Sized> Deref for Shared<T> {
-    type Target = *mut T;
+    type Target = *const T;
 
     #[inline]
-    fn deref(&self) -> &*mut T {
+    fn deref(&self) -> &*const T {
         unsafe { mem::transmute(&*self.pointer) }
     }
 }
diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs
index a7d0d3899b1..a95f05227fb 100644
--- a/src/libcore/raw.rs
+++ b/src/libcore/raw.rs
@@ -25,7 +25,7 @@
 /// Book][moreinfo] contains more details about the precise nature of
 /// these internals.
 ///
-/// [moreinfo]: ../../book/trait-objects.html#representation
+/// [moreinfo]: ../../book/first-edition/trait-objects.html#representation
 ///
 /// `TraitObject` is guaranteed to match layouts, but it is not the
 /// type of trait objects (e.g. the fields are not directly accessible
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index a05db9b489c..c46b0c1324d 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -268,7 +268,7 @@ impl<T, E> Result<T, E> {
     // Querying the contained values
     /////////////////////////////////////////////////////////////////////////
 
-    /// Returns true if the result is `Ok`.
+    /// Returns `true` if the result is `Ok`.
     ///
     /// # Examples
     ///
@@ -290,7 +290,7 @@ impl<T, E> Result<T, E> {
         }
     }
 
-    /// Returns true if the result is `Err`.
+    /// Returns `true` if the result is `Err`.
     ///
     /// # Examples
     ///
@@ -803,12 +803,11 @@ impl<T: fmt::Debug, E> Result<T, E> {
     /// Basic usage:
     ///
     /// ```{.should_panic}
-    /// # #![feature(result_expect_err)]
     /// let x: Result<u32, &str> = Ok(10);
     /// x.expect_err("Testing expect_err"); // panics with `Testing expect_err: 10`
     /// ```
     #[inline]
-    #[unstable(feature = "result_expect_err", issue = "39041")]
+    #[stable(feature = "result_expect_err", since = "1.17.0")]
     pub fn expect_err(self, msg: &str) -> E {
         match self {
             Ok(t) => unwrap_failed(msg, t),
@@ -839,10 +838,10 @@ impl<T: Default, E> Result<T, E> {
     ///
     /// assert_eq!(1909, good_year);
     /// assert_eq!(0, bad_year);
+    /// ```
     ///
     /// [`parse`]: ../../std/primitive.str.html#method.parse
     /// [`FromStr`]: ../../std/str/trait.FromStr.html
-    /// ```
     #[inline]
     #[stable(feature = "result_unwrap_or_default", since = "1.16.0")]
     pub fn unwrap_or_default(self) -> T {
diff --git a/src/libcore/slice.rs b/src/libcore/slice/mod.rs
index 0331c5d4ba4..87dfdfe57b6 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice/mod.rs
@@ -1,4 +1,4 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -10,7 +10,9 @@
 
 //! Slice management and manipulation
 //!
-//! For more details `std::slice`.
+//! For more details see [`std::slice`].
+//!
+//! [`std::slice`]: ../../std/slice/index.html
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -49,6 +51,8 @@ use mem;
 use marker::{Copy, Send, Sync, Sized, self};
 use iter_private::TrustedRandomAccess;
 
+mod sort;
+
 #[repr(C)]
 struct Repr<T> {
     pub data: *const T,
@@ -69,86 +73,123 @@ pub trait SliceExt {
 
     #[stable(feature = "core", since = "1.6.0")]
     fn split_at(&self, mid: usize) -> (&[Self::Item], &[Self::Item]);
+
     #[stable(feature = "core", since = "1.6.0")]
     fn iter(&self) -> Iter<Self::Item>;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn split<P>(&self, pred: P) -> Split<Self::Item, P>
-                    where P: FnMut(&Self::Item) -> bool;
+        where P: FnMut(&Self::Item) -> bool;
+
+    #[unstable(feature = "slice_rsplit", issue = "41020")]
+    fn rsplit<P>(&self, pred: P) -> RSplit<Self::Item, P>
+        where P: FnMut(&Self::Item) -> bool;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn splitn<P>(&self, n: usize, pred: P) -> SplitN<Self::Item, P>
-                     where P: FnMut(&Self::Item) -> bool;
+        where P: FnMut(&Self::Item) -> bool;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn rsplitn<P>(&self,  n: usize, pred: P) -> RSplitN<Self::Item, P>
-                      where P: FnMut(&Self::Item) -> bool;
+        where P: FnMut(&Self::Item) -> bool;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn windows(&self, size: usize) -> Windows<Self::Item>;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn chunks(&self, size: usize) -> Chunks<Self::Item>;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn get<I>(&self, index: I) -> Option<&I::Output>
-        where I: SliceIndex<Self::Item>;
+        where I: SliceIndex<Self>;
     #[stable(feature = "core", since = "1.6.0")]
     fn first(&self) -> Option<&Self::Item>;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn split_first(&self) -> Option<(&Self::Item, &[Self::Item])>;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn split_last(&self) -> Option<(&Self::Item, &[Self::Item])>;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn last(&self) -> Option<&Self::Item>;
+
     #[stable(feature = "core", since = "1.6.0")]
     unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
-        where I: SliceIndex<Self::Item>;
+        where I: SliceIndex<Self>;
     #[stable(feature = "core", since = "1.6.0")]
     fn as_ptr(&self) -> *const Self::Item;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn binary_search<Q: ?Sized>(&self, x: &Q) -> Result<usize, usize>
         where Self::Item: Borrow<Q>,
               Q: Ord;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn binary_search_by<'a, F>(&'a self, f: F) -> Result<usize, usize>
         where F: FnMut(&'a Self::Item) -> Ordering;
+
     #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")]
     fn binary_search_by_key<'a, B, F, Q: ?Sized>(&'a self, b: &Q, f: F) -> Result<usize, usize>
         where F: FnMut(&'a Self::Item) -> B,
               B: Borrow<Q>,
               Q: Ord;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn len(&self) -> usize;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn is_empty(&self) -> bool { self.len() == 0 }
+
     #[stable(feature = "core", since = "1.6.0")]
     fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
-        where I: SliceIndex<Self::Item>;
+        where I: SliceIndex<Self>;
     #[stable(feature = "core", since = "1.6.0")]
     fn iter_mut(&mut self) -> IterMut<Self::Item>;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn first_mut(&mut self) -> Option<&mut Self::Item>;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn split_first_mut(&mut self) -> Option<(&mut Self::Item, &mut [Self::Item])>;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn split_last_mut(&mut self) -> Option<(&mut Self::Item, &mut [Self::Item])>;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn last_mut(&mut self) -> Option<&mut Self::Item>;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn split_mut<P>(&mut self, pred: P) -> SplitMut<Self::Item, P>
-                        where P: FnMut(&Self::Item) -> bool;
+        where P: FnMut(&Self::Item) -> bool;
+
+    #[unstable(feature = "slice_rsplit", issue = "41020")]
+    fn rsplit_mut<P>(&mut self, pred: P) -> RSplitMut<Self::Item, P>
+        where P: FnMut(&Self::Item) -> bool;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn splitn_mut<P>(&mut self, n: usize, pred: P) -> SplitNMut<Self::Item, P>
-                     where P: FnMut(&Self::Item) -> bool;
+        where P: FnMut(&Self::Item) -> bool;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn rsplitn_mut<P>(&mut self,  n: usize, pred: P) -> RSplitNMut<Self::Item, P>
-                      where P: FnMut(&Self::Item) -> bool;
+        where P: FnMut(&Self::Item) -> bool;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<Self::Item>;
+
     #[stable(feature = "core", since = "1.6.0")]
     fn swap(&mut self, a: usize, b: usize);
+
     #[stable(feature = "core", since = "1.6.0")]
     fn split_at_mut(&mut self, mid: usize) -> (&mut [Self::Item], &mut [Self::Item]);
+
     #[stable(feature = "core", since = "1.6.0")]
     fn reverse(&mut self);
+
     #[stable(feature = "core", since = "1.6.0")]
     unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
-        where I: SliceIndex<Self::Item>;
+        where I: SliceIndex<Self>;
     #[stable(feature = "core", since = "1.6.0")]
     fn as_mut_ptr(&mut self) -> *mut Self::Item;
 
@@ -163,8 +204,22 @@ pub trait SliceExt {
 
     #[stable(feature = "clone_from_slice", since = "1.7.0")]
     fn clone_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Clone;
+
     #[stable(feature = "copy_from_slice", since = "1.9.0")]
     fn copy_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Copy;
+
+    #[unstable(feature = "sort_unstable", issue = "40585")]
+    fn sort_unstable(&mut self)
+        where Self::Item: Ord;
+
+    #[unstable(feature = "sort_unstable", issue = "40585")]
+    fn sort_unstable_by<F>(&mut self, compare: F)
+        where F: FnMut(&Self::Item, &Self::Item) -> Ordering;
+
+    #[unstable(feature = "sort_unstable", issue = "40585")]
+    fn sort_unstable_by_key<B, F>(&mut self, f: F)
+        where F: FnMut(&Self::Item) -> B,
+              B: Ord;
 }
 
 // Use macros to be generic over const/mut
@@ -236,7 +291,9 @@ impl<T> SliceExt for [T] {
     }
 
     #[inline]
-    fn split<P>(&self, pred: P) -> Split<T, P> where P: FnMut(&T) -> bool {
+    fn split<P>(&self, pred: P) -> Split<T, P>
+        where P: FnMut(&T) -> bool
+    {
         Split {
             v: self,
             pred: pred,
@@ -245,27 +302,32 @@ impl<T> SliceExt for [T] {
     }
 
     #[inline]
-    fn splitn<P>(&self, n: usize, pred: P) -> SplitN<T, P> where
-        P: FnMut(&T) -> bool,
+    fn rsplit<P>(&self, pred: P) -> RSplit<T, P>
+        where P: FnMut(&T) -> bool
+    {
+        RSplit { inner: self.split(pred) }
+    }
+
+    #[inline]
+    fn splitn<P>(&self, n: usize, pred: P) -> SplitN<T, P>
+        where P: FnMut(&T) -> bool
     {
         SplitN {
             inner: GenericSplitN {
                 iter: self.split(pred),
-                count: n,
-                invert: false
+                count: n
             }
         }
     }
 
     #[inline]
-    fn rsplitn<P>(&self, n: usize, pred: P) -> RSplitN<T, P> where
-        P: FnMut(&T) -> bool,
+    fn rsplitn<P>(&self, n: usize, pred: P) -> RSplitN<T, P>
+        where P: FnMut(&T) -> bool
     {
         RSplitN {
             inner: GenericSplitN {
-                iter: self.split(pred),
-                count: n,
-                invert: true
+                iter: self.rsplit(pred),
+                count: n
             }
         }
     }
@@ -284,7 +346,7 @@ impl<T> SliceExt for [T] {
 
     #[inline]
     fn get<I>(&self, index: I) -> Option<&I::Output>
-        where I: SliceIndex<T>
+        where I: SliceIndex<[T]>
     {
         index.get(self)
     }
@@ -312,7 +374,7 @@ impl<T> SliceExt for [T] {
 
     #[inline]
     unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
-        where I: SliceIndex<T>
+        where I: SliceIndex<[T]>
     {
         index.get_unchecked(self)
     }
@@ -353,7 +415,7 @@ impl<T> SliceExt for [T] {
 
     #[inline]
     fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
-        where I: SliceIndex<T>
+        where I: SliceIndex<[T]>
     {
         index.get_mut(self)
     }
@@ -420,19 +482,27 @@ impl<T> SliceExt for [T] {
     }
 
     #[inline]
-    fn split_mut<P>(&mut self, pred: P) -> SplitMut<T, P> where P: FnMut(&T) -> bool {
+    fn split_mut<P>(&mut self, pred: P) -> SplitMut<T, P>
+        where P: FnMut(&T) -> bool
+    {
         SplitMut { v: self, pred: pred, finished: false }
     }
 
     #[inline]
-    fn splitn_mut<P>(&mut self, n: usize, pred: P) -> SplitNMut<T, P> where
-        P: FnMut(&T) -> bool
+    fn rsplit_mut<P>(&mut self, pred: P) -> RSplitMut<T, P>
+        where P: FnMut(&T) -> bool
+    {
+        RSplitMut { inner: self.split_mut(pred) }
+    }
+
+    #[inline]
+    fn splitn_mut<P>(&mut self, n: usize, pred: P) -> SplitNMut<T, P>
+        where P: FnMut(&T) -> bool
     {
         SplitNMut {
             inner: GenericSplitN {
                 iter: self.split_mut(pred),
-                count: n,
-                invert: false
+                count: n
             }
         }
     }
@@ -443,12 +513,11 @@ impl<T> SliceExt for [T] {
     {
         RSplitNMut {
             inner: GenericSplitN {
-                iter: self.split_mut(pred),
-                count: n,
-                invert: true
+                iter: self.rsplit_mut(pred),
+                count: n
             }
         }
-   }
+    }
 
     #[inline]
     fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<T> {
@@ -483,7 +552,7 @@ impl<T> SliceExt for [T] {
 
     #[inline]
     unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
-        where I: SliceIndex<T>
+        where I: SliceIndex<[T]>
     {
         index.get_unchecked_mut(self)
     }
@@ -510,7 +579,10 @@ impl<T> SliceExt for [T] {
         m >= n && needle == &self[m-n..]
     }
 
-    fn binary_search<Q: ?Sized>(&self, x: &Q) -> Result<usize, usize> where T: Borrow<Q>, Q: Ord {
+    fn binary_search<Q: ?Sized>(&self, x: &Q) -> Result<usize, usize>
+        where T: Borrow<Q>,
+              Q: Ord
+    {
         self.binary_search_by(|p| p.borrow().cmp(x))
     }
 
@@ -546,12 +618,34 @@ impl<T> SliceExt for [T] {
     {
         self.binary_search_by(|k| f(k).borrow().cmp(b))
     }
+
+    #[inline]
+    fn sort_unstable(&mut self)
+        where Self::Item: Ord
+    {
+        sort::quicksort(self, |a, b| a.lt(b));
+    }
+
+    #[inline]
+    fn sort_unstable_by<F>(&mut self, mut compare: F)
+        where F: FnMut(&Self::Item, &Self::Item) -> Ordering
+    {
+        sort::quicksort(self, |a, b| compare(a, b) == Ordering::Less);
+    }
+
+    #[inline]
+    fn sort_unstable_by_key<B, F>(&mut self, mut f: F)
+        where F: FnMut(&Self::Item) -> B,
+              B: Ord
+    {
+        sort::quicksort(self, |a, b| f(a).lt(&f(b)));
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
 impl<T, I> ops::Index<I> for [T]
-    where I: SliceIndex<T>
+    where I: SliceIndex<[T]>
 {
     type Output = I::Output;
 
@@ -564,7 +658,7 @@ impl<T, I> ops::Index<I> for [T]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
 impl<T, I> ops::IndexMut<I> for [T]
-    where I: SliceIndex<T>
+    where I: SliceIndex<[T]>
 {
     #[inline]
     fn index_mut(&mut self, index: I) -> &mut I::Output {
@@ -587,37 +681,37 @@ fn slice_index_order_fail(index: usize, end: usize) -> ! {
 /// A helper trait used for indexing operations.
 #[unstable(feature = "slice_get_slice", issue = "35729")]
 #[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
-pub trait SliceIndex<T> {
+pub trait SliceIndex<T: ?Sized> {
     /// The output type returned by methods.
     type Output: ?Sized;
 
     /// Returns a shared reference to the output at this location, if in
     /// bounds.
-    fn get(self, slice: &[T]) -> Option<&Self::Output>;
+    fn get(self, slice: &T) -> Option<&Self::Output>;
 
     /// Returns a mutable reference to the output at this location, if in
     /// bounds.
-    fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output>;
+    fn get_mut(self, slice: &mut T) -> Option<&mut Self::Output>;
 
     /// Returns a shared reference to the output at this location, without
     /// performing any bounds checking.
-    unsafe fn get_unchecked(self, slice: &[T]) -> &Self::Output;
+    unsafe fn get_unchecked(self, slice: &T) -> &Self::Output;
 
     /// Returns a mutable reference to the output at this location, without
     /// performing any bounds checking.
-    unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut Self::Output;
+    unsafe fn get_unchecked_mut(self, slice: &mut T) -> &mut Self::Output;
 
     /// Returns a shared reference to the output at this location, panicking
     /// if out of bounds.
-    fn index(self, slice: &[T]) -> &Self::Output;
+    fn index(self, slice: &T) -> &Self::Output;
 
     /// Returns a mutable reference to the output at this location, panicking
     /// if out of bounds.
-    fn index_mut(self, slice: &mut [T]) -> &mut Self::Output;
+    fn index_mut(self, slice: &mut T) -> &mut Self::Output;
 }
 
 #[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
-impl<T> SliceIndex<T> for usize {
+impl<T> SliceIndex<[T]> for usize {
     type Output = T;
 
     #[inline]
@@ -666,7 +760,7 @@ impl<T> SliceIndex<T> for usize {
 }
 
 #[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
-impl<T> SliceIndex<T> for  ops::Range<usize> {
+impl<T> SliceIndex<[T]> for  ops::Range<usize> {
     type Output = [T];
 
     #[inline]
@@ -727,7 +821,7 @@ impl<T> SliceIndex<T> for  ops::Range<usize> {
 }
 
 #[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
-impl<T> SliceIndex<T> for ops::RangeTo<usize> {
+impl<T> SliceIndex<[T]> for ops::RangeTo<usize> {
     type Output = [T];
 
     #[inline]
@@ -762,7 +856,7 @@ impl<T> SliceIndex<T> for ops::RangeTo<usize> {
 }
 
 #[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
-impl<T> SliceIndex<T> for ops::RangeFrom<usize> {
+impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {
     type Output = [T];
 
     #[inline]
@@ -797,7 +891,7 @@ impl<T> SliceIndex<T> for ops::RangeFrom<usize> {
 }
 
 #[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
-impl<T> SliceIndex<T> for ops::RangeFull {
+impl<T> SliceIndex<[T]> for ops::RangeFull {
     type Output = [T];
 
     #[inline]
@@ -833,7 +927,7 @@ impl<T> SliceIndex<T> for ops::RangeFull {
 
 
 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
-impl<T> SliceIndex<T> for ops::RangeInclusive<usize> {
+impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
     type Output = [T];
 
     #[inline]
@@ -896,7 +990,7 @@ impl<T> SliceIndex<T> for ops::RangeInclusive<usize> {
 }
 
 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
-impl<T> SliceIndex<T> for ops::RangeToInclusive<usize> {
+impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
     type Output = [T];
 
     #[inline]
@@ -1096,6 +1190,19 @@ macro_rules! iterator {
                     }
                 }
             }
+
+            fn rfind<F>(&mut self, mut predicate: F) -> Option<Self::Item>
+                where F: FnMut(&Self::Item) -> bool,
+            {
+                self.rsearch_while(None, move |elt| {
+                    if predicate(&elt) {
+                        SearchWhile::Done(Some(elt))
+                    } else {
+                        SearchWhile::Continue
+                    }
+                })
+            }
+
         }
 
         // search_while is a generalization of the internal iteration methods.
@@ -1422,16 +1529,17 @@ unsafe impl<'a, T> TrustedLen for IterMut<'a, T> {}
 // Return the arithmetic difference if `T` is zero size.
 #[inline(always)]
 fn ptrdistance<T>(start: *const T, end: *const T) -> usize {
-    let diff = (end as usize).wrapping_sub(start as usize);
-    let size = mem::size_of::<T>();
-    diff / (if size == 0 { 1 } else { size })
+    match start.offset_to(end) {
+        Some(x) => x as usize,
+        None => (end as usize).wrapping_sub(start as usize),
+    }
 }
 
 // Extension methods for raw pointers, used by the iterators
 trait PointerExt : Copy {
     unsafe fn slice_offset(self, i: isize) -> Self;
 
-    /// Increment self by 1, but return the old value
+    /// Increments `self` by 1, but returns the old value.
     #[inline(always)]
     unsafe fn post_inc(&mut self) -> Self {
         let current = *self;
@@ -1439,7 +1547,7 @@ trait PointerExt : Copy {
         current
     }
 
-    /// Decrement self by 1, and return the new value
+    /// Decrements `self` by 1, and returns the new value.
     #[inline(always)]
     unsafe fn pre_dec(&mut self) -> Self {
         *self = self.slice_offset(-1);
@@ -1465,7 +1573,7 @@ impl<T> PointerExt for *mut T {
 /// splitn, splitn_mut etc can be implemented once.
 #[doc(hidden)]
 trait SplitIter: DoubleEndedIterator {
-    /// Mark the underlying iterator as complete, extracting the remaining
+    /// Marks the underlying iterator as complete, extracting the remaining
     /// portion of the slice.
     fn finish(&mut self) -> Option<Self::Item>;
 }
@@ -1659,6 +1767,123 @@ impl<'a, T, P> DoubleEndedIterator for SplitMut<'a, T, P> where
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, T, P> FusedIterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {}
 
+/// An iterator over subslices separated by elements that match a predicate
+/// function, starting from the end of the slice.
+///
+/// This struct is created by the [`rsplit`] method on [slices].
+///
+/// [`rsplit`]: ../../std/primitive.slice.html#method.rsplit
+/// [slices]: ../../std/primitive.slice.html
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+#[derive(Clone)] // Is this correct, or does it incorrectly require `T: Clone`?
+pub struct RSplit<'a, T:'a, P> where P: FnMut(&T) -> bool {
+    inner: Split<'a, T, P>
+}
+
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("RSplit")
+            .field("v", &self.inner.v)
+            .field("finished", &self.inner.finished)
+            .finish()
+    }
+}
+
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+impl<'a, T, P> Iterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
+    type Item = &'a [T];
+
+    #[inline]
+    fn next(&mut self) -> Option<&'a [T]> {
+        self.inner.next_back()
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.inner.size_hint()
+    }
+}
+
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+impl<'a, T, P> DoubleEndedIterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a [T]> {
+        self.inner.next()
+    }
+}
+
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+impl<'a, T, P> SplitIter for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
+    #[inline]
+    fn finish(&mut self) -> Option<&'a [T]> {
+        self.inner.finish()
+    }
+}
+
+//#[unstable(feature = "fused", issue = "35602")]
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+impl<'a, T, P> FusedIterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {}
+
+/// An iterator over the subslices of the vector which are separated
+/// by elements that match `pred`, starting from the end of the slice.
+///
+/// This struct is created by the [`rsplit_mut`] method on [slices].
+///
+/// [`rsplit_mut`]: ../../std/primitive.slice.html#method.rsplit_mut
+/// [slices]: ../../std/primitive.slice.html
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+pub struct RSplitMut<'a, T:'a, P> where P: FnMut(&T) -> bool {
+    inner: SplitMut<'a, T, P>
+}
+
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("RSplitMut")
+            .field("v", &self.inner.v)
+            .field("finished", &self.inner.finished)
+            .finish()
+    }
+}
+
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+impl<'a, T, P> SplitIter for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {
+    #[inline]
+    fn finish(&mut self) -> Option<&'a mut [T]> {
+        self.inner.finish()
+    }
+}
+
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+impl<'a, T, P> Iterator for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {
+    type Item = &'a mut [T];
+
+    #[inline]
+    fn next(&mut self) -> Option<&'a mut [T]> {
+        self.inner.next_back()
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.inner.size_hint()
+    }
+}
+
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+impl<'a, T, P> DoubleEndedIterator for RSplitMut<'a, T, P> where
+    P: FnMut(&T) -> bool,
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a mut [T]> {
+        self.inner.next()
+    }
+}
+
+//#[unstable(feature = "fused", issue = "35602")]
+#[unstable(feature = "slice_rsplit", issue = "41020")]
+impl<'a, T, P> FusedIterator for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {}
+
 /// An private iterator over subslices separated by elements that
 /// match a predicate function, splitting at most a fixed number of
 /// times.
@@ -1666,7 +1891,6 @@ impl<'a, T, P> FusedIterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {
 struct GenericSplitN<I> {
     iter: I,
     count: usize,
-    invert: bool
 }
 
 impl<T, I: SplitIter<Item=T>> Iterator for GenericSplitN<I> {
@@ -1677,10 +1901,7 @@ impl<T, I: SplitIter<Item=T>> Iterator for GenericSplitN<I> {
         match self.count {
             0 => None,
             1 => { self.count -= 1; self.iter.finish() }
-            _ => {
-                self.count -= 1;
-                if self.invert {self.iter.next_back()} else {self.iter.next()}
-            }
+            _ => { self.count -= 1; self.iter.next() }
         }
     }
 
@@ -1722,7 +1943,7 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for SplitN<'a, T, P> where P: FnMut(&
 /// [slices]: ../../std/primitive.slice.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RSplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool {
-    inner: GenericSplitN<Split<'a, T, P>>
+    inner: GenericSplitN<RSplit<'a, T, P>>
 }
 
 #[stable(feature = "core_impl_debug", since = "1.9.0")]
@@ -1765,7 +1986,7 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for SplitNMut<'a, T, P> where P: FnMu
 /// [slices]: ../../std/primitive.slice.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RSplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool {
-    inner: GenericSplitN<SplitMut<'a, T, P>>
+    inner: GenericSplitN<RSplitMut<'a, T, P>>
 }
 
 #[stable(feature = "core_impl_debug", since = "1.9.0")]
@@ -2173,16 +2394,25 @@ pub unsafe fn from_raw_parts_mut<'a, T>(p: *mut T, len: usize) -> &'a mut [T] {
     mem::transmute(Repr { data: p, len: len })
 }
 
+// This function is public only because there is no other way to unit test heapsort.
+#[unstable(feature = "sort_internals", reason = "internal to sort module", issue = "0")]
+#[doc(hidden)]
+pub fn heapsort<T, F>(v: &mut [T], mut is_less: F)
+    where F: FnMut(&T, &T) -> bool
+{
+    sort::heapsort(v, &mut is_less);
+}
+
 //
 // Comparison traits
 //
 
 extern {
-    /// Call implementation provided memcmp
+    /// Calls implementation provided memcmp.
     ///
     /// Interprets the data as u8.
     ///
-    /// Return 0 for equal, < 0 for less than and > 0 for greater
+    /// Returns 0 for equal, < 0 for less than and > 0 for greater
     /// than.
     // FIXME(#32610): Return type should be c_int
     fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32;
diff --git a/src/libcore/slice/sort.rs b/src/libcore/slice/sort.rs
new file mode 100644
index 00000000000..7065fdb79fc
--- /dev/null
+++ b/src/libcore/slice/sort.rs
@@ -0,0 +1,709 @@
+// 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.
+
+//! Slice sorting
+//!
+//! This module contains an sort algorithm based on Orson Peters' pattern-defeating quicksort,
+//! published at: https://github.com/orlp/pdqsort
+//!
+//! Unstable sorting is compatible with libcore because it doesn't allocate memory, unlike our
+//! stable sorting implementation.
+
+use cmp;
+use mem;
+use ptr;
+
+/// Holds a value, but never drops it.
+#[allow(unions_with_drop_fields)]
+union NoDrop<T> {
+    value: T
+}
+
+/// When dropped, copies from `src` into `dest`.
+struct CopyOnDrop<T> {
+    src: *mut T,
+    dest: *mut T,
+}
+
+impl<T> Drop for CopyOnDrop<T> {
+    fn drop(&mut self) {
+        unsafe { ptr::copy_nonoverlapping(self.src, self.dest, 1); }
+    }
+}
+
+/// Shifts the first element to the right until it encounters a greater or equal element.
+fn shift_head<T, F>(v: &mut [T], is_less: &mut F)
+    where F: FnMut(&T, &T) -> bool
+{
+    let len = v.len();
+    unsafe {
+        // If the first two elements are out-of-order...
+        if len >= 2 && is_less(v.get_unchecked(1), v.get_unchecked(0)) {
+            // Read the first element into a stack-allocated variable. If a following comparison
+            // operation panics, `hole` will get dropped and automatically write the element back
+            // into the slice.
+            let mut tmp = NoDrop { value: ptr::read(v.get_unchecked(0)) };
+            let mut hole = CopyOnDrop {
+                src: &mut tmp.value,
+                dest: v.get_unchecked_mut(1),
+            };
+            ptr::copy_nonoverlapping(v.get_unchecked(1), v.get_unchecked_mut(0), 1);
+
+            for i in 2..len {
+                if !is_less(v.get_unchecked(i), &tmp.value) {
+                    break;
+                }
+
+                // Move `i`-th element one place to the left, thus shifting the hole to the right.
+                ptr::copy_nonoverlapping(v.get_unchecked(i), v.get_unchecked_mut(i - 1), 1);
+                hole.dest = v.get_unchecked_mut(i);
+            }
+            // `hole` gets dropped and thus copies `tmp` into the remaining hole in `v`.
+        }
+    }
+}
+
+/// Shifts the last element to the left until it encounters a smaller or equal element.
+fn shift_tail<T, F>(v: &mut [T], is_less: &mut F)
+    where F: FnMut(&T, &T) -> bool
+{
+    let len = v.len();
+    unsafe {
+        // If the last two elements are out-of-order...
+        if len >= 2 && is_less(v.get_unchecked(len - 1), v.get_unchecked(len - 2)) {
+            // Read the last element into a stack-allocated variable. If a following comparison
+            // operation panics, `hole` will get dropped and automatically write the element back
+            // into the slice.
+            let mut tmp = NoDrop { value: ptr::read(v.get_unchecked(len - 1)) };
+            let mut hole = CopyOnDrop {
+                src: &mut tmp.value,
+                dest: v.get_unchecked_mut(len - 2),
+            };
+            ptr::copy_nonoverlapping(v.get_unchecked(len - 2), v.get_unchecked_mut(len - 1), 1);
+
+            for i in (0..len-2).rev() {
+                if !is_less(&tmp.value, v.get_unchecked(i)) {
+                    break;
+                }
+
+                // Move `i`-th element one place to the right, thus shifting the hole to the left.
+                ptr::copy_nonoverlapping(v.get_unchecked(i), v.get_unchecked_mut(i + 1), 1);
+                hole.dest = v.get_unchecked_mut(i);
+            }
+            // `hole` gets dropped and thus copies `tmp` into the remaining hole in `v`.
+        }
+    }
+}
+
+/// Partially sorts a slice by shifting several out-of-order elements around.
+///
+/// Returns `true` if the slice is sorted at the end. This function is `O(n)` worst-case.
+#[cold]
+fn partial_insertion_sort<T, F>(v: &mut [T], is_less: &mut F) -> bool
+    where F: FnMut(&T, &T) -> bool
+{
+    // Maximum number of adjacent out-of-order pairs that will get shifted.
+    const MAX_STEPS: usize = 5;
+    // If the slice is shorter than this, don't shift any elements.
+    const SHORTEST_SHIFTING: usize = 50;
+
+    let len = v.len();
+    let mut i = 1;
+
+    for _ in 0..MAX_STEPS {
+        unsafe {
+            // Find the next pair of adjacent out-of-order elements.
+            while i < len && !is_less(v.get_unchecked(i), v.get_unchecked(i - 1)) {
+                i += 1;
+            }
+        }
+
+        // Are we done?
+        if i == len {
+            return true;
+        }
+
+        // Don't shift elements on short arrays, that has a performance cost.
+        if len < SHORTEST_SHIFTING {
+            return false;
+        }
+
+        // Swap the found pair of elements. This puts them in correct order.
+        v.swap(i - 1, i);
+
+        // Shift the smaller element to the left.
+        shift_tail(&mut v[..i], is_less);
+        // Shift the greater element to the right.
+        shift_head(&mut v[i..], is_less);
+    }
+
+    // Didn't manage to sort the slice in the limited number of steps.
+    false
+}
+
+/// Sorts a slice using insertion sort, which is `O(n^2)` worst-case.
+fn insertion_sort<T, F>(v: &mut [T], is_less: &mut F)
+    where F: FnMut(&T, &T) -> bool
+{
+    for i in 1..v.len() {
+        shift_tail(&mut v[..i+1], is_less);
+    }
+}
+
+/// Sorts `v` using heapsort, which guarantees `O(n log n)` worst-case.
+#[cold]
+pub fn heapsort<T, F>(v: &mut [T], is_less: &mut F)
+    where F: FnMut(&T, &T) -> bool
+{
+    // This binary heap respects the invariant `parent >= child`.
+    let mut sift_down = |v: &mut [T], mut node| {
+        loop {
+            // Children of `node`:
+            let left = 2 * node + 1;
+            let right = 2 * node + 2;
+
+            // Choose the greater child.
+            let greater = if right < v.len() && is_less(&v[left], &v[right]) {
+                right
+            } else {
+                left
+            };
+
+            // Stop if the invariant holds at `node`.
+            if greater >= v.len() || !is_less(&v[node], &v[greater]) {
+                break;
+            }
+
+            // Swap `node` with the greater child, move one step down, and continue sifting.
+            v.swap(node, greater);
+            node = greater;
+        }
+    };
+
+    // Build the heap in linear time.
+    for i in (0 .. v.len() / 2).rev() {
+        sift_down(v, i);
+    }
+
+    // Pop maximal elements from the heap.
+    for i in (1 .. v.len()).rev() {
+        v.swap(0, i);
+        sift_down(&mut v[..i], 0);
+    }
+}
+
+/// Partitions `v` into elements smaller than `pivot`, followed by elements greater than or equal
+/// to `pivot`.
+///
+/// Returns the number of elements smaller than `pivot`.
+///
+/// Partitioning is performed block-by-block in order to minimize the cost of branching operations.
+/// This idea is presented in the [BlockQuicksort][pdf] paper.
+///
+/// [pdf]: http://drops.dagstuhl.de/opus/volltexte/2016/6389/pdf/LIPIcs-ESA-2016-38.pdf
+fn partition_in_blocks<T, F>(v: &mut [T], pivot: &T, is_less: &mut F) -> usize
+    where F: FnMut(&T, &T) -> bool
+{
+    // Number of elements in a typical block.
+    const BLOCK: usize = 128;
+
+    // The partitioning algorithm repeats the following steps until completion:
+    //
+    // 1. Trace a block from the left side to identify elements greater than or equal to the pivot.
+    // 2. Trace a block from the right side to identify elements smaller than the pivot.
+    // 3. Exchange the identified elements between the left and right side.
+    //
+    // We keep the following variables for a block of elements:
+    //
+    // 1. `block` - Number of elements in the block.
+    // 2. `start` - Start pointer into the `offsets` array.
+    // 3. `end` - End pointer into the `offsets` array.
+    // 4. `offsets - Indices of out-of-order elements within the block.
+
+    // The current block on the left side (from `l` to `l.offset(block_l)`).
+    let mut l = v.as_mut_ptr();
+    let mut block_l = BLOCK;
+    let mut start_l = ptr::null_mut();
+    let mut end_l = ptr::null_mut();
+    let mut offsets_l: [u8; BLOCK] = unsafe { mem::uninitialized() };
+
+    // The current block on the right side (from `r.offset(-block_r)` to `r`).
+    let mut r = unsafe { l.offset(v.len() as isize) };
+    let mut block_r = BLOCK;
+    let mut start_r = ptr::null_mut();
+    let mut end_r = ptr::null_mut();
+    let mut offsets_r: [u8; BLOCK] = unsafe { mem::uninitialized() };
+
+    // FIXME: When we get VLAs, try creating one array of length `min(v.len(), 2 * BLOCK)` rather
+    // than two fixed-size arrays of length `BLOCK`. VLAs might be more cache-efficient.
+
+    // Returns the number of elements between pointers `l` (inclusive) and `r` (exclusive).
+    fn width<T>(l: *mut T, r: *mut T) -> usize {
+        assert!(mem::size_of::<T>() > 0);
+        (r as usize - l as usize) / mem::size_of::<T>()
+    }
+
+    loop {
+        // We are done with partitioning block-by-block when `l` and `r` get very close. Then we do
+        // some patch-up work in order to partition the remaining elements in between.
+        let is_done = width(l, r) <= 2 * BLOCK;
+
+        if is_done {
+            // Number of remaining elements (still not compared to the pivot).
+            let mut rem = width(l, r);
+            if start_l < end_l || start_r < end_r {
+                rem -= BLOCK;
+            }
+
+            // Adjust block sizes so that the left and right block don't overlap, but get perfectly
+            // aligned to cover the whole remaining gap.
+            if start_l < end_l {
+                block_r = rem;
+            } else if start_r < end_r {
+                block_l = rem;
+            } else {
+                block_l = rem / 2;
+                block_r = rem - block_l;
+            }
+            debug_assert!(block_l <= BLOCK && block_r <= BLOCK);
+            debug_assert!(width(l, r) == block_l + block_r);
+        }
+
+        if start_l == end_l {
+            // Trace `block_l` elements from the left side.
+            start_l = offsets_l.as_mut_ptr();
+            end_l = offsets_l.as_mut_ptr();
+            let mut elem = l;
+
+            for i in 0..block_l {
+                unsafe {
+                    // Branchless comparison.
+                    *end_l = i as u8;
+                    end_l = end_l.offset(!is_less(&*elem, pivot) as isize);
+                    elem = elem.offset(1);
+                }
+            }
+        }
+
+        if start_r == end_r {
+            // Trace `block_r` elements from the right side.
+            start_r = offsets_r.as_mut_ptr();
+            end_r = offsets_r.as_mut_ptr();
+            let mut elem = r;
+
+            for i in 0..block_r {
+                unsafe {
+                    // Branchless comparison.
+                    elem = elem.offset(-1);
+                    *end_r = i as u8;
+                    end_r = end_r.offset(is_less(&*elem, pivot) as isize);
+                }
+            }
+        }
+
+        // Number of out-of-order elements to swap between the left and right side.
+        let count = cmp::min(width(start_l, end_l), width(start_r, end_r));
+
+        if count > 0 {
+            macro_rules! left { () => { l.offset(*start_l as isize) } }
+            macro_rules! right { () => { r.offset(-(*start_r as isize) - 1) } }
+
+            // Instead of swapping one pair at the time, it is more efficient to perform a cyclic
+            // permutation. This is not strictly equivalent to swapping, but produces a similar
+            // result using fewer memory operations.
+            unsafe {
+                let tmp = ptr::read(left!());
+                ptr::copy_nonoverlapping(right!(), left!(), 1);
+
+                for _ in 1..count {
+                    start_l = start_l.offset(1);
+                    ptr::copy_nonoverlapping(left!(), right!(), 1);
+                    start_r = start_r.offset(1);
+                    ptr::copy_nonoverlapping(right!(), left!(), 1);
+                }
+
+                ptr::copy_nonoverlapping(&tmp, right!(), 1);
+                mem::forget(tmp);
+                start_l = start_l.offset(1);
+                start_r = start_r.offset(1);
+            }
+        }
+
+        if start_l == end_l {
+            // All out-of-order elements in the left block were moved. Move to the next block.
+            l = unsafe { l.offset(block_l as isize) };
+        }
+
+        if start_r == end_r {
+            // All out-of-order elements in the right block were moved. Move to the previous block.
+            r = unsafe { r.offset(-(block_r as isize)) };
+        }
+
+        if is_done {
+            break;
+        }
+    }
+
+    // All that remains now is at most one block (either the left or the right) with out-of-order
+    // elements that need to be moved. Such remaining elements can be simply shifted to the end
+    // within their block.
+
+    if start_l < end_l {
+        // The left block remains.
+        // Move it's remaining out-of-order elements to the far right.
+        debug_assert_eq!(width(l, r), block_l);
+        while start_l < end_l {
+            unsafe {
+                end_l = end_l.offset(-1);
+                ptr::swap(l.offset(*end_l as isize), r.offset(-1));
+                r = r.offset(-1);
+            }
+        }
+        width(v.as_mut_ptr(), r)
+    } else if start_r < end_r {
+        // The right block remains.
+        // Move it's remaining out-of-order elements to the far left.
+        debug_assert_eq!(width(l, r), block_r);
+        while start_r < end_r {
+            unsafe {
+                end_r = end_r.offset(-1);
+                ptr::swap(l, r.offset(-(*end_r as isize) - 1));
+                l = l.offset(1);
+            }
+        }
+        width(v.as_mut_ptr(), l)
+    } else {
+        // Nothing else to do, we're done.
+        width(v.as_mut_ptr(), l)
+    }
+}
+
+/// Partitions `v` into elements smaller than `v[pivot]`, followed by elements greater than or
+/// equal to `v[pivot]`.
+///
+/// Returns a tuple of:
+///
+/// 1. Number of elements smaller than `v[pivot]`.
+/// 2. True if `v` was already partitioned.
+fn partition<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> (usize, bool)
+    where F: FnMut(&T, &T) -> bool
+{
+    let (mid, was_partitioned) = {
+        // Place the pivot at the beginning of slice.
+        v.swap(0, pivot);
+        let (pivot, v) = v.split_at_mut(1);
+        let pivot = &mut pivot[0];
+
+        // Read the pivot into a stack-allocated variable for efficiency. If a following comparison
+        // operation panics, the pivot will be automatically written back into the slice.
+        let mut tmp = NoDrop { value: unsafe { ptr::read(pivot) } };
+        let _pivot_guard = CopyOnDrop {
+            src: unsafe { &mut tmp.value },
+            dest: pivot,
+        };
+        let pivot = unsafe { &tmp.value };
+
+        // Find the first pair of out-of-order elements.
+        let mut l = 0;
+        let mut r = v.len();
+        unsafe {
+            // Find the first element greater then or equal to the pivot.
+            while l < r && is_less(v.get_unchecked(l), pivot) {
+                l += 1;
+            }
+
+            // Find the last element smaller that the pivot.
+            while l < r && !is_less(v.get_unchecked(r - 1), pivot) {
+                r -= 1;
+            }
+        }
+
+        (l + partition_in_blocks(&mut v[l..r], pivot, is_less), l >= r)
+
+        // `_pivot_guard` goes out of scope and writes the pivot (which is a stack-allocated
+        // variable) back into the slice where it originally was. This step is critical in ensuring
+        // safety!
+    };
+
+    // Place the pivot between the two partitions.
+    v.swap(0, mid);
+
+    (mid, was_partitioned)
+}
+
+/// Partitions `v` into elements equal to `v[pivot]` followed by elements greater than `v[pivot]`.
+///
+/// Returns the number of elements equal to the pivot. It is assumed that `v` does not contain
+/// elements smaller than the pivot.
+fn partition_equal<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> usize
+    where F: FnMut(&T, &T) -> bool
+{
+    // Place the pivot at the beginning of slice.
+    v.swap(0, pivot);
+    let (pivot, v) = v.split_at_mut(1);
+    let pivot = &mut pivot[0];
+
+    // Read the pivot into a stack-allocated variable for efficiency. If a following comparison
+    // operation panics, the pivot will be automatically written back into the slice.
+    let mut tmp = NoDrop { value: unsafe { ptr::read(pivot) } };
+    let _pivot_guard = CopyOnDrop {
+        src: unsafe { &mut tmp.value },
+        dest: pivot,
+    };
+    let pivot = unsafe { &tmp.value };
+
+    // Now partition the slice.
+    let mut l = 0;
+    let mut r = v.len();
+    loop {
+        unsafe {
+            // Find the first element greater that the pivot.
+            while l < r && !is_less(pivot, v.get_unchecked(l)) {
+                l += 1;
+            }
+
+            // Find the last element equal to the pivot.
+            while l < r && is_less(pivot, v.get_unchecked(r - 1)) {
+                r -= 1;
+            }
+
+            // Are we done?
+            if l >= r {
+                break;
+            }
+
+            // Swap the found pair of out-of-order elements.
+            r -= 1;
+            ptr::swap(v.get_unchecked_mut(l), v.get_unchecked_mut(r));
+            l += 1;
+        }
+    }
+
+    // We found `l` elements equal to the pivot. Add 1 to account for the pivot itself.
+    l + 1
+
+    // `_pivot_guard` goes out of scope and writes the pivot (which is a stack-allocated variable)
+    // back into the slice where it originally was. This step is critical in ensuring safety!
+}
+
+/// Scatters some elements around in an attempt to break patterns that might cause imbalanced
+/// partitions in quicksort.
+#[cold]
+fn break_patterns<T>(v: &mut [T]) {
+    let len = v.len();
+    if len >= 8 {
+        // Pseudorandom number generator from the "Xorshift RNGs" paper by George Marsaglia.
+        let mut random = len as u32;
+        let mut gen_u32 = || {
+            random ^= random << 13;
+            random ^= random >> 17;
+            random ^= random << 5;
+            random
+        };
+        let mut gen_usize = || {
+            if mem::size_of::<usize>() <= 4 {
+                gen_u32() as usize
+            } else {
+                (((gen_u32() as u64) << 32) | (gen_u32() as u64)) as usize
+            }
+        };
+
+        // Take random numbers modulo this number.
+        // The number fits into `usize` because `len` is not greater than `isize::MAX`.
+        let modulus = len.next_power_of_two();
+
+        // Some pivot candidates will be in the nearby of this index. Let's randomize them.
+        let pos = len / 4 * 2;
+
+        for i in 0..3 {
+            // Generate a random number modulo `len`. However, in order to avoid costly operations
+            // we first take it modulo a power of two, and then decrease by `len` until it fits
+            // into the range `[0, len - 1]`.
+            let mut other = gen_usize() & (modulus - 1);
+
+            // `other` is guaranteed to be less than `2 * len`.
+            if other >= len {
+                other -= len;
+            }
+
+            v.swap(pos - 1 + i, other);
+        }
+    }
+}
+
+/// Chooses a pivot in `v` and returns the index and `true` if the slice is likely already sorted.
+///
+/// Elements in `v` might be reordered in the process.
+fn choose_pivot<T, F>(v: &mut [T], is_less: &mut F) -> (usize, bool)
+    where F: FnMut(&T, &T) -> bool
+{
+    // Minimum length to choose the median-of-medians method.
+    // Shorter slices use the simple median-of-three method.
+    const SHORTEST_MEDIAN_OF_MEDIANS: usize = 50;
+    // Maximum number of swaps that can be performed in this function.
+    const MAX_SWAPS: usize = 4 * 3;
+
+    let len = v.len();
+
+    // Three indices near which we are going to choose a pivot.
+    let mut a = len / 4 * 1;
+    let mut b = len / 4 * 2;
+    let mut c = len / 4 * 3;
+
+    // Counts the total number of swaps we are about to perform while sorting indices.
+    let mut swaps = 0;
+
+    if len >= 8 {
+        // Swaps indices so that `v[a] <= v[b]`.
+        let mut sort2 = |a: &mut usize, b: &mut usize| unsafe {
+            if is_less(v.get_unchecked(*b), v.get_unchecked(*a)) {
+                ptr::swap(a, b);
+                swaps += 1;
+            }
+        };
+
+        // Swaps indices so that `v[a] <= v[b] <= v[c]`.
+        let mut sort3 = |a: &mut usize, b: &mut usize, c: &mut usize| {
+            sort2(a, b);
+            sort2(b, c);
+            sort2(a, b);
+        };
+
+        if len >= SHORTEST_MEDIAN_OF_MEDIANS {
+            // Finds the median of `v[a - 1], v[a], v[a + 1]` and stores the index into `a`.
+            let mut sort_adjacent = |a: &mut usize| {
+                let tmp = *a;
+                sort3(&mut (tmp - 1), a, &mut (tmp + 1));
+            };
+
+            // Find medians in the neighborhoods of `a`, `b`, and `c`.
+            sort_adjacent(&mut a);
+            sort_adjacent(&mut b);
+            sort_adjacent(&mut c);
+        }
+
+        // Find the median among `a`, `b`, and `c`.
+        sort3(&mut a, &mut b, &mut c);
+    }
+
+    if swaps < MAX_SWAPS {
+        (b, swaps == 0)
+    } else {
+        // The maximum number of swaps was performed. Chances are the slice is descending or mostly
+        // descending, so reversing will probably help sort it faster.
+        v.reverse();
+        (len - 1 - b, true)
+    }
+}
+
+/// Sorts `v` recursively.
+///
+/// If the slice had a predecessor in the original array, it is specified as `pred`.
+///
+/// `limit` is the number of allowed imbalanced partitions before switching to `heapsort`. If zero,
+/// this function will immediately switch to heapsort.
+fn recurse<'a, T, F>(mut v: &'a mut [T], is_less: &mut F, mut pred: Option<&'a T>, mut limit: usize)
+    where F: FnMut(&T, &T) -> bool
+{
+    // Slices of up to this length get sorted using insertion sort.
+    const MAX_INSERTION: usize = 20;
+
+    // True if the last partitioning was reasonably balanced.
+    let mut was_balanced = true;
+    // True if the last partitioning didn't shuffle elements (the slice was already partitioned).
+    let mut was_partitioned = true;
+
+    loop {
+        let len = v.len();
+
+        // Very short slices get sorted using insertion sort.
+        if len <= MAX_INSERTION {
+            insertion_sort(v, is_less);
+            return;
+        }
+
+        // If too many bad pivot choices were made, simply fall back to heapsort in order to
+        // guarantee `O(n log n)` worst-case.
+        if limit == 0 {
+            heapsort(v, is_less);
+            return;
+        }
+
+        // If the last partitioning was imbalanced, try breaking patterns in the slice by shuffling
+        // some elements around. Hopefully we'll choose a better pivot this time.
+        if !was_balanced {
+            break_patterns(v);
+            limit -= 1;
+        }
+
+        // Choose a pivot and try guessing whether the slice is already sorted.
+        let (pivot, likely_sorted) = choose_pivot(v, is_less);
+
+        // If the last partitioning was decently balanced and didn't shuffle elements, and if pivot
+        // selection predicts the slice is likely already sorted...
+        if was_balanced && was_partitioned && likely_sorted {
+            // Try identifying several out-of-order elements and shifting them to correct
+            // positions. If the slice ends up being completely sorted, we're done.
+            if partial_insertion_sort(v, is_less) {
+                return;
+            }
+        }
+
+        // If the chosen pivot is equal to the predecessor, then it's the smallest element in the
+        // slice. Partition the slice into elements equal to and elements greater than the pivot.
+        // This case is usually hit when the slice contains many duplicate elements.
+        if let Some(p) = pred {
+            if !is_less(p, &v[pivot]) {
+                let mid = partition_equal(v, pivot, is_less);
+
+                // Continue sorting elements greater than the pivot.
+                v = &mut {v}[mid..];
+                continue;
+            }
+        }
+
+        // Partition the slice.
+        let (mid, was_p) = partition(v, pivot, is_less);
+        was_balanced = cmp::min(mid, len - mid) >= len / 8;
+        was_partitioned = was_p;
+
+        // Split the slice into `left`, `pivot`, and `right`.
+        let (left, right) = {v}.split_at_mut(mid);
+        let (pivot, right) = right.split_at_mut(1);
+        let pivot = &pivot[0];
+
+        // Recurse into the shorter side only in order to minimize the total number of recursive
+        // calls and consume less stack space. Then just continue with the longer side (this is
+        // akin to tail recursion).
+        if left.len() < right.len() {
+            recurse(left, is_less, pred, limit);
+            v = right;
+            pred = Some(pivot);
+        } else {
+            recurse(right, is_less, Some(pivot), limit);
+            v = left;
+        }
+    }
+}
+
+/// Sorts `v` using pattern-defeating quicksort, which is `O(n log n)` worst-case.
+pub fn quicksort<T, F>(v: &mut [T], mut is_less: F)
+    where F: FnMut(&T, &T) -> bool
+{
+    // Sorting has no meaningful behavior on zero-sized types.
+    if mem::size_of::<T>() == 0 {
+        return;
+    }
+
+    // Limit the number of imbalanced partitions to `floor(log2(len)) + 1`.
+    let limit = mem::size_of::<usize>() * 8 - v.len().leading_zeros() as usize;
+
+    recurse(v, &mut is_less, None, limit);
+}
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 2919adc1cbc..352cc926994 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -18,22 +18,56 @@ use self::pattern::Pattern;
 use self::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
 
 use char;
+use convert::TryFrom;
 use fmt;
 use iter::{Map, Cloned, FusedIterator};
 use mem;
-use slice;
+use slice::{self, SliceIndex};
 
 pub mod pattern;
 
 /// A trait to abstract the idea of creating a new instance of a type from a
 /// string.
 ///
-/// `FromStr`'s [`from_str()`] method is often used implicitly, through
-/// [`str`]'s [`parse()`] method. See [`parse()`]'s documentation for examples.
+/// `FromStr`'s [`from_str`] method is often used implicitly, through
+/// [`str`]'s [`parse`] method. See [`parse`]'s documentation for examples.
 ///
-/// [`from_str()`]: #tymethod.from_str
+/// [`from_str`]: #tymethod.from_str
 /// [`str`]: ../../std/primitive.str.html
-/// [`parse()`]: ../../std/primitive.str.html#method.parse
+/// [`parse`]: ../../std/primitive.str.html#method.parse
+///
+/// # Examples
+///
+/// Basic implementation of `FromStr` on an example `Point` type:
+///
+/// ```
+/// use std::str::FromStr;
+/// use std::num::ParseIntError;
+///
+/// #[derive(Debug, PartialEq)]
+/// struct Point {
+///     x: i32,
+///     y: i32
+/// }
+///
+/// impl FromStr for Point {
+///     type Err = ParseIntError;
+///
+///     fn from_str(s: &str) -> Result<Self, Self::Err> {
+///         let coords: Vec<&str> = s.trim_matches(|p| p == '(' || p == ')' )
+///                                  .split(",")
+///                                  .collect();
+///
+///         let x_fromstr = coords[0].parse::<i32>()?;
+///         let y_fromstr = coords[1].parse::<i32>()?;
+///
+///         Ok(Point { x: x_fromstr, y: y_fromstr })
+///     }
+/// }
+///
+/// let p = Point::from_str("(1,2)");
+/// assert_eq!(p.unwrap(), Point{ x: 1, y: 2} )
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait FromStr: Sized {
     /// The associated error which can be returned from parsing.
@@ -100,7 +134,9 @@ impl FromStr for bool {
     }
 }
 
-/// An error returned when parsing a `bool` from a string fails.
+/// An error returned when parsing a `bool` using [`from_str`] fails
+///
+/// [`from_str`]: ../../std/primitive.bool.html#method.from_str
 #[derive(Debug, Clone, PartialEq, Eq)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct ParseBoolError { _priv: () }
@@ -116,11 +152,16 @@ impl fmt::Display for ParseBoolError {
 Section: Creating a string
 */
 
-/// Errors which can occur when attempting to interpret a sequence of `u8`
+/// Errors which can occur when attempting to interpret a sequence of [`u8`]
 /// as a string.
 ///
-/// As such, the `from_utf8` family of functions and methods for both `String`s
-/// and `&str`s make use of this error, for example.
+/// [`u8`]: ../../std/primitive.u8.html
+///
+/// As such, the `from_utf8` family of functions and methods for both [`String`]s
+/// and [`&str`]s make use of this error, for example.
+///
+/// [`String`]: ../../std/string/struct.String.html#method.from_utf8
+/// [`&str`]: ../../std/str/fn.from_utf8.html
 #[derive(Copy, Eq, PartialEq, Clone, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Utf8Error {
@@ -174,27 +215,34 @@ impl Utf8Error {
 
 /// Converts a slice of bytes to a string slice.
 ///
-/// A string slice (`&str`) is made of bytes (`u8`), and a byte slice (`&[u8]`)
-/// is made of bytes, so this function converts between the two. Not all byte
-/// slices are valid string slices, however: `&str` requires that it is valid
-/// UTF-8. `from_utf8()` checks to ensure that the bytes are valid UTF-8, and
-/// then does the conversion.
+/// A string slice ([`&str`]) is made of bytes ([`u8`]), and a byte slice
+/// ([`&[u8]`][byteslice]) is made of bytes, so this function converts between
+/// the two. Not all byte slices are valid string slices, however: [`&str`] requires
+/// that it is valid UTF-8. `from_utf8()` checks to ensure that the bytes are valid
+/// UTF-8, and then does the conversion.
+///
+/// [`&str`]: ../../std/primitive.str.html
+/// [`u8`]: ../../std/primitive.u8.html
+/// [byteslice]: ../../std/primitive.slice.html
 ///
 /// If you are sure that the byte slice is valid UTF-8, and you don't want to
 /// incur the overhead of the validity check, there is an unsafe version of
-/// this function, [`from_utf8_unchecked()`][fromutf8u], which has the same
+/// this function, [`from_utf8_unchecked`][fromutf8u], which has the same
 /// behavior but skips the check.
 ///
 /// [fromutf8u]: fn.from_utf8_unchecked.html
 ///
 /// If you need a `String` instead of a `&str`, consider
-/// [`String::from_utf8()`][string].
+/// [`String::from_utf8`][string].
 ///
 /// [string]: ../../std/string/struct.String.html#method.from_utf8
 ///
-/// Because you can stack-allocate a `[u8; N]`, and you can take a `&[u8]` of
-/// it, this function is one way to have a stack-allocated string. There is
-/// an example of this in the examples section below.
+/// Because you can stack-allocate a `[u8; N]`, and you can take a
+/// [`&[u8]`][byteslice] of it, this function is one way to have a
+/// stack-allocated string. There is an example of this in the
+/// examples section below.
+///
+/// [byteslice]: ../../std/primitive.slice.html
 ///
 /// # Errors
 ///
@@ -283,7 +331,7 @@ unsafe fn from_raw_parts_mut<'a>(p: *mut u8, len: usize) -> &'a mut str {
 /// Converts a slice of bytes to a string slice without checking
 /// that the string contains valid UTF-8.
 ///
-/// See the safe version, [`from_utf8()`][fromutf8], for more information.
+/// See the safe version, [`from_utf8`][fromutf8], for more information.
 ///
 /// [fromutf8]: fn.from_utf8.html
 ///
@@ -291,7 +339,9 @@ unsafe fn from_raw_parts_mut<'a>(p: *mut u8, len: usize) -> &'a mut str {
 ///
 /// This function is unsafe because it does not check that the bytes passed to
 /// it are valid UTF-8. If this constraint is violated, undefined behavior
-/// results, as the rest of Rust assumes that `&str`s are valid UTF-8.
+/// results, as the rest of Rust assumes that [`&str`]s are valid UTF-8.
+///
+/// [`&str`]: ../../std/primitive.str.html
 ///
 /// # Examples
 ///
@@ -331,24 +381,28 @@ impl fmt::Display for Utf8Error {
 Section: Iterators
 */
 
-/// Iterator for the char (representing *Unicode Scalar Values*) of a string
+/// An iterator over the [`char`]s of a string slice.
+///
+/// [`char`]: ../../std/primitive.char.html
 ///
-/// Created with the method [`chars()`].
+/// This struct is created by the [`chars`] method on [`str`].
+/// See its documentation for more.
 ///
-/// [`chars()`]: ../../std/primitive.str.html#method.chars
+/// [`chars`]: ../../std/primitive.str.html#method.chars
+/// [`str`]: ../../std/primitive.str.html
 #[derive(Clone, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Chars<'a> {
     iter: slice::Iter<'a, u8>
 }
 
-/// Return the initial codepoint accumulator for the first byte.
+/// Returns the initial codepoint accumulator for the first byte.
 /// The first byte is special, only want bottom 5 bits for width 2, 4 bits
 /// for width 3, and 3 bits for width 4.
 #[inline]
 fn utf8_first_byte(byte: u8, width: u32) -> u32 { (byte & (0x7F >> width)) as u32 }
 
-/// Return the value of `ch` updated with continuation byte `byte`.
+/// Returns the value of `ch` updated with continuation byte `byte`.
 #[inline]
 fn utf8_acc_cont_byte(ch: u32, byte: u8) -> u32 { (ch << 6) | (byte & CONT_MASK) as u32 }
 
@@ -515,7 +569,15 @@ impl<'a> Chars<'a> {
     }
 }
 
-/// Iterator for a string's characters and their byte offsets.
+/// An iterator over the [`char`]s of a string slice, and their positions.
+///
+/// [`char`]: ../../std/primitive.char.html
+///
+/// This struct is created by the [`char_indices`] method on [`str`].
+/// See its documentation for more.
+///
+/// [`char_indices`]: ../../std/primitive.str.html#method.char_indices
+/// [`str`]: ../../std/primitive.str.html
 #[derive(Clone, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct CharIndices<'a> {
@@ -587,12 +649,13 @@ impl<'a> CharIndices<'a> {
     }
 }
 
-/// External iterator for a string's bytes.
-/// Use with the `std::iter` module.
+/// An iterator over the bytes of a string slice.
 ///
-/// Created with the method [`bytes()`].
+/// This struct is created by the [`bytes`] method on [`str`].
+/// See its documentation for more.
 ///
-/// [`bytes()`]: ../../std/primitive.str.html#method.bytes
+/// [`bytes`]: ../../std/primitive.str.html#method.bytes
+/// [`str`]: ../../std/primitive.str.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Clone, Debug)]
 pub struct Bytes<'a>(Cloned<slice::Iter<'a, u8>>);
@@ -925,14 +988,14 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> {
 
 generate_pattern_iterators! {
     forward:
-        /// Created with the method [`split()`].
+        /// Created with the method [`split`].
         ///
-        /// [`split()`]: ../../std/primitive.str.html#method.split
+        /// [`split`]: ../../std/primitive.str.html#method.split
         struct Split;
     reverse:
-        /// Created with the method [`rsplit()`].
+        /// Created with the method [`rsplit`].
         ///
-        /// [`rsplit()`]: ../../std/primitive.str.html#method.rsplit
+        /// [`rsplit`]: ../../std/primitive.str.html#method.rsplit
         struct RSplit;
     stability:
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -943,14 +1006,14 @@ generate_pattern_iterators! {
 
 generate_pattern_iterators! {
     forward:
-        /// Created with the method [`split_terminator()`].
+        /// Created with the method [`split_terminator`].
         ///
-        /// [`split_terminator()`]: ../../std/primitive.str.html#method.split_terminator
+        /// [`split_terminator`]: ../../std/primitive.str.html#method.split_terminator
         struct SplitTerminator;
     reverse:
-        /// Created with the method [`rsplit_terminator()`].
+        /// Created with the method [`rsplit_terminator`].
         ///
-        /// [`rsplit_terminator()`]: ../../std/primitive.str.html#method.rsplit_terminator
+        /// [`rsplit_terminator`]: ../../std/primitive.str.html#method.rsplit_terminator
         struct RSplitTerminator;
     stability:
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -1003,14 +1066,14 @@ impl<'a, P: Pattern<'a>> SplitNInternal<'a, P> {
 
 generate_pattern_iterators! {
     forward:
-        /// Created with the method [`splitn()`].
+        /// Created with the method [`splitn`].
         ///
-        /// [`splitn()`]: ../../std/primitive.str.html#method.splitn
+        /// [`splitn`]: ../../std/primitive.str.html#method.splitn
         struct SplitN;
     reverse:
-        /// Created with the method [`rsplitn()`].
+        /// Created with the method [`rsplitn`].
         ///
-        /// [`rsplitn()`]: ../../std/primitive.str.html#method.rsplitn
+        /// [`rsplitn`]: ../../std/primitive.str.html#method.rsplitn
         struct RSplitN;
     stability:
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -1054,14 +1117,14 @@ impl<'a, P: Pattern<'a>> MatchIndicesInternal<'a, P> {
 
 generate_pattern_iterators! {
     forward:
-        /// Created with the method [`match_indices()`].
+        /// Created with the method [`match_indices`].
         ///
-        /// [`match_indices()`]: ../../std/primitive.str.html#method.match_indices
+        /// [`match_indices`]: ../../std/primitive.str.html#method.match_indices
         struct MatchIndices;
     reverse:
-        /// Created with the method [`rmatch_indices()`].
+        /// Created with the method [`rmatch_indices`].
         ///
-        /// [`rmatch_indices()`]: ../../std/primitive.str.html#method.rmatch_indices
+        /// [`rmatch_indices`]: ../../std/primitive.str.html#method.rmatch_indices
         struct RMatchIndices;
     stability:
         #[stable(feature = "str_match_indices", since = "1.5.0")]
@@ -1107,14 +1170,14 @@ impl<'a, P: Pattern<'a>> MatchesInternal<'a, P> {
 
 generate_pattern_iterators! {
     forward:
-        /// Created with the method [`matches()`].
+        /// Created with the method [`matches`].
         ///
-        /// [`matches()`]: ../../std/primitive.str.html#method.matches
+        /// [`matches`]: ../../std/primitive.str.html#method.matches
         struct Matches;
     reverse:
-        /// Created with the method [`rmatches()`].
+        /// Created with the method [`rmatches`].
         ///
-        /// [`rmatches()`]: ../../std/primitive.str.html#method.rmatches
+        /// [`rmatches`]: ../../std/primitive.str.html#method.rmatches
         struct RMatches;
     stability:
         #[stable(feature = "str_matches", since = "1.2.0")]
@@ -1123,9 +1186,13 @@ generate_pattern_iterators! {
     delegate double ended;
 }
 
-/// Created with the method [`lines()`].
+/// An iterator over the lines of a string, as string slices.
+///
+/// This struct is created with the [`lines`] method on [`str`].
+/// See its documentation for more.
 ///
-/// [`lines()`]: ../../std/primitive.str.html#method.lines
+/// [`lines`]: ../../std/primitive.str.html#method.lines
+/// [`str`]: ../../std/primitive.str.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Clone, Debug)]
 pub struct Lines<'a>(Map<SplitTerminator<'a, char>, LinesAnyMap>);
@@ -1156,9 +1223,9 @@ impl<'a> DoubleEndedIterator for Lines<'a> {
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a> FusedIterator for Lines<'a> {}
 
-/// Created with the method [`lines_any()`].
+/// Created with the method [`lines_any`].
 ///
-/// [`lines_any()`]: ../../std/primitive.str.html#method.lines_any
+/// [`lines_any`]: ../../std/primitive.str.html#method.lines_any
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_deprecated(since = "1.4.0", reason = "use lines()/Lines instead now")]
 #[derive(Clone, Debug)]
@@ -1243,13 +1310,13 @@ Section: UTF-8 validation
 // use truncation to fit u64 into usize
 const NONASCII_MASK: usize = 0x80808080_80808080u64 as usize;
 
-/// Return `true` if any byte in the word `x` is nonascii (>= 128).
+/// Returns `true` if any byte in the word `x` is nonascii (>= 128).
 #[inline]
 fn contains_nonascii(x: usize) -> bool {
     (x & NONASCII_MASK) != 0
 }
 
-/// Walk through `iter` checking that it's a valid UTF-8 sequence,
+/// Walks through `iter` checking that it's a valid UTF-8 sequence,
 /// returning `true` in that case, or, if it is invalid, `false` with
 /// `iter` reset such that it is pointing at the first byte in the
 /// invalid sequence.
@@ -1388,16 +1455,16 @@ static UTF8_CHAR_WIDTH: [u8; 256] = [
 4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, // 0xFF
 ];
 
-/// Given a first byte, determine how many bytes are in this UTF-8 character
+/// Given a first byte, determines how many bytes are in this UTF-8 character.
 #[unstable(feature = "str_internals", issue = "0")]
 #[inline]
 pub fn utf8_char_width(b: u8) -> usize {
     return UTF8_CHAR_WIDTH[b as usize] as usize;
 }
 
-/// Mask of the value bits of a continuation byte
+/// Mask of the value bits of a continuation byte.
 const CONT_MASK: u8 = 0b0011_1111;
-/// Value of the tag bits (tag mask is !CONT_MASK) of a continuation byte
+/// Value of the tag bits (tag mask is !CONT_MASK) of a continuation byte.
 const TAG_CONT_U8: u8 = 0b1000_0000;
 
 /*
@@ -1407,6 +1474,8 @@ Section: Trait implementations
 mod traits {
     use cmp::Ordering;
     use ops;
+    use mem;
+    use slice::{self, SliceIndex};
     use str::eq_slice;
 
     /// Implements ordering of strings.
@@ -1489,14 +1558,7 @@ mod traits {
         type Output = str;
         #[inline]
         fn index(&self, index: ops::Range<usize>) -> &str {
-            // is_char_boundary checks that the index is in [0, .len()]
-            if index.start <= index.end &&
-               self.is_char_boundary(index.start) &&
-               self.is_char_boundary(index.end) {
-                unsafe { self.slice_unchecked(index.start, index.end) }
-            } else {
-                super::slice_error_fail(self, index.start, index.end)
-            }
+            index.index(self)
         }
     }
 
@@ -1518,14 +1580,7 @@ mod traits {
     impl ops::IndexMut<ops::Range<usize>> for str {
         #[inline]
         fn index_mut(&mut self, index: ops::Range<usize>) -> &mut str {
-            // is_char_boundary checks that the index is in [0, .len()]
-            if index.start <= index.end &&
-               self.is_char_boundary(index.start) &&
-               self.is_char_boundary(index.end) {
-                unsafe { self.slice_mut_unchecked(index.start, index.end) }
-            } else {
-                super::slice_error_fail(self, index.start, index.end)
-            }
+            index.index_mut(self)
         }
     }
 
@@ -1693,8 +1748,276 @@ mod traits {
             self.index_mut(0...index.end)
         }
     }
+
+    #[unstable(feature = "str_checked_slicing", issue = "39932")]
+    impl SliceIndex<str> for ops::RangeFull {
+        type Output = str;
+        #[inline]
+        fn get(self, slice: &str) -> Option<&Self::Output> {
+            Some(slice)
+        }
+        #[inline]
+        fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
+            Some(slice)
+        }
+        #[inline]
+        unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
+            slice
+        }
+        #[inline]
+        unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
+            slice
+        }
+        #[inline]
+        fn index(self, slice: &str) -> &Self::Output {
+            slice
+        }
+        #[inline]
+        fn index_mut(self, slice: &mut str) -> &mut Self::Output {
+            slice
+        }
+    }
+
+    #[unstable(feature = "str_checked_slicing", issue = "39932")]
+    impl SliceIndex<str> for ops::Range<usize> {
+        type Output = str;
+        #[inline]
+        fn get(self, slice: &str) -> Option<&Self::Output> {
+            if self.start <= self.end &&
+               slice.is_char_boundary(self.start) &&
+               slice.is_char_boundary(self.end) {
+                Some(unsafe { self.get_unchecked(slice) })
+            } else {
+                None
+            }
+        }
+        #[inline]
+        fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
+            if self.start <= self.end &&
+               slice.is_char_boundary(self.start) &&
+               slice.is_char_boundary(self.end) {
+                Some(unsafe { self.get_unchecked_mut(slice) })
+            } else {
+                None
+            }
+        }
+        #[inline]
+        unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
+            let ptr = slice.as_ptr().offset(self.start as isize);
+            let len = self.end - self.start;
+            super::from_utf8_unchecked(slice::from_raw_parts(ptr, len))
+        }
+        #[inline]
+        unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
+            let ptr = slice.as_ptr().offset(self.start as isize);
+            let len = self.end - self.start;
+            mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, len))
+        }
+        #[inline]
+        fn index(self, slice: &str) -> &Self::Output {
+            let (start, end) = (self.start, self.end);
+            self.get(slice).unwrap_or_else(|| super::slice_error_fail(slice, start, end))
+        }
+        #[inline]
+        fn index_mut(self, slice: &mut str) -> &mut Self::Output {
+            // is_char_boundary checks that the index is in [0, .len()]
+            // canot reuse `get` as above, because of NLL trouble
+            if self.start <= self.end &&
+               slice.is_char_boundary(self.start) &&
+               slice.is_char_boundary(self.end) {
+                unsafe { self.get_unchecked_mut(slice) }
+            } else {
+                super::slice_error_fail(slice, self.start, self.end)
+            }
+        }
+    }
+
+    #[unstable(feature = "str_checked_slicing", issue = "39932")]
+    impl SliceIndex<str> for ops::RangeTo<usize> {
+        type Output = str;
+        #[inline]
+        fn get(self, slice: &str) -> Option<&Self::Output> {
+            if slice.is_char_boundary(self.end) {
+                Some(unsafe { self.get_unchecked(slice) })
+            } else {
+                None
+            }
+        }
+        #[inline]
+        fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
+            if slice.is_char_boundary(self.end) {
+                Some(unsafe { self.get_unchecked_mut(slice) })
+            } else {
+                None
+            }
+        }
+        #[inline]
+        unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
+            let ptr = slice.as_ptr();
+            super::from_utf8_unchecked(slice::from_raw_parts(ptr, self.end))
+        }
+        #[inline]
+        unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
+            let ptr = slice.as_ptr();
+            mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, self.end))
+        }
+        #[inline]
+        fn index(self, slice: &str) -> &Self::Output {
+            let end = self.end;
+            self.get(slice).unwrap_or_else(|| super::slice_error_fail(slice, 0, end))
+        }
+        #[inline]
+        fn index_mut(self, slice: &mut str) -> &mut Self::Output {
+            if slice.is_char_boundary(self.end) {
+                unsafe { self.get_unchecked_mut(slice) }
+            } else {
+                super::slice_error_fail(slice, 0, self.end)
+            }
+        }
+    }
+
+    #[unstable(feature = "str_checked_slicing", issue = "39932")]
+    impl SliceIndex<str> for ops::RangeFrom<usize> {
+        type Output = str;
+        #[inline]
+        fn get(self, slice: &str) -> Option<&Self::Output> {
+            if slice.is_char_boundary(self.start) {
+                Some(unsafe { self.get_unchecked(slice) })
+            } else {
+                None
+            }
+        }
+        #[inline]
+        fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
+            if slice.is_char_boundary(self.start) {
+                Some(unsafe { self.get_unchecked_mut(slice) })
+            } else {
+                None
+            }
+        }
+        #[inline]
+        unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
+            let ptr = slice.as_ptr().offset(self.start as isize);
+            let len = slice.len() - self.start;
+            super::from_utf8_unchecked(slice::from_raw_parts(ptr, len))
+        }
+        #[inline]
+        unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
+            let ptr = slice.as_ptr().offset(self.start as isize);
+            let len = slice.len() - self.start;
+            mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, len))
+        }
+        #[inline]
+        fn index(self, slice: &str) -> &Self::Output {
+            let (start, end) = (self.start, slice.len());
+            self.get(slice).unwrap_or_else(|| super::slice_error_fail(slice, start, end))
+        }
+        #[inline]
+        fn index_mut(self, slice: &mut str) -> &mut Self::Output {
+            if slice.is_char_boundary(self.start) {
+                unsafe { self.get_unchecked_mut(slice) }
+            } else {
+                super::slice_error_fail(slice, self.start, slice.len())
+            }
+        }
+    }
+
+    #[unstable(feature = "str_checked_slicing", issue = "39932")]
+    impl SliceIndex<str> for ops::RangeInclusive<usize> {
+        type Output = str;
+        #[inline]
+        fn get(self, slice: &str) -> Option<&Self::Output> {
+            match self {
+                ops::RangeInclusive::Empty { .. } => 0..0,
+                ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
+            }.get(slice)
+        }
+        #[inline]
+        fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
+            match self {
+                ops::RangeInclusive::Empty { .. } => 0..0,
+                ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
+            }.get_mut(slice)
+        }
+        #[inline]
+        unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
+            match self {
+                ops::RangeInclusive::Empty { .. } => 0..0,
+                ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
+            }.get_unchecked(slice)
+        }
+        #[inline]
+        unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
+            match self {
+                ops::RangeInclusive::Empty { .. } => 0..0,
+                ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
+            }.get_unchecked_mut(slice)
+        }
+        #[inline]
+        fn index(self, slice: &str) -> &Self::Output {
+            match self {
+                ops::RangeInclusive::Empty { .. } => 0..0,
+                ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
+            }.index(slice)
+        }
+        #[inline]
+        fn index_mut(self, slice: &mut str) -> &mut Self::Output {
+            match self {
+                ops::RangeInclusive::Empty { .. } => 0..0,
+                ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
+            }.index_mut(slice)
+        }
+    }
+
+
+
+    #[unstable(feature = "str_checked_slicing", issue = "39932")]
+    impl SliceIndex<str> for ops::RangeToInclusive<usize> {
+        type Output = str;
+        #[inline]
+        fn get(self, slice: &str) -> Option<&Self::Output> {
+            if slice.is_char_boundary(self.end + 1) {
+                Some(unsafe { self.get_unchecked(slice) })
+            } else {
+                None
+            }
+        }
+        #[inline]
+        fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
+            if slice.is_char_boundary(self.end + 1) {
+                Some(unsafe { self.get_unchecked_mut(slice) })
+            } else {
+                None
+            }
+        }
+        #[inline]
+        unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
+            let ptr = slice.as_ptr();
+            super::from_utf8_unchecked(slice::from_raw_parts(ptr, self.end + 1))
+        }
+        #[inline]
+        unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
+            let ptr = slice.as_ptr();
+            mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, self.end + 1))
+        }
+        #[inline]
+        fn index(self, slice: &str) -> &Self::Output {
+            let end = self.end + 1;
+            self.get(slice).unwrap_or_else(|| super::slice_error_fail(slice, 0, end))
+        }
+        #[inline]
+        fn index_mut(self, slice: &mut str) -> &mut Self::Output {
+            if slice.is_char_boundary(self.end) {
+                unsafe { self.get_unchecked_mut(slice) }
+            } else {
+                super::slice_error_fail(slice, 0, self.end + 1)
+            }
+        }
+    }
+
 }
 
+
 /// Methods for string slices
 #[allow(missing_docs)]
 #[doc(hidden)]
@@ -1744,6 +2067,14 @@ pub trait StrExt {
     #[rustc_deprecated(since = "1.6.0", reason = "use lines() instead now")]
     #[allow(deprecated)]
     fn lines_any(&self) -> LinesAny;
+    #[unstable(feature = "str_checked_slicing", issue = "39932")]
+    fn get<I: SliceIndex<str>>(&self, i: I) -> Option<&I::Output>;
+    #[unstable(feature = "str_checked_slicing", issue = "39932")]
+    fn get_mut<I: SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output>;
+    #[unstable(feature = "str_checked_slicing", issue = "39932")]
+    unsafe fn get_unchecked<I: SliceIndex<str>>(&self, i: I) -> &I::Output;
+    #[unstable(feature = "str_checked_slicing", issue = "39932")]
+    unsafe fn get_unchecked_mut<I: SliceIndex<str>>(&mut self, i: I) -> &mut I::Output;
     #[stable(feature = "core", since = "1.6.0")]
     unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str;
     #[stable(feature = "core", since = "1.6.0")]
@@ -1782,7 +2113,7 @@ pub trait StrExt {
     #[stable(feature = "core", since = "1.6.0")]
     fn is_empty(&self) -> bool;
     #[stable(feature = "core", since = "1.6.0")]
-    fn parse<T: FromStr>(&self) -> Result<T, T::Err>;
+    fn parse<'a, T: TryFrom<&'a str>>(&'a self) -> Result<T, T::Error>;
 }
 
 // truncate `&str` to length at most equal to `max`
@@ -1934,17 +2265,33 @@ impl StrExt for str {
     }
 
     #[inline]
+    fn get<I: SliceIndex<str>>(&self, i: I) -> Option<&I::Output> {
+        i.get(self)
+    }
+
+    #[inline]
+    fn get_mut<I: SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> {
+        i.get_mut(self)
+    }
+
+    #[inline]
+    unsafe fn get_unchecked<I: SliceIndex<str>>(&self, i: I) -> &I::Output {
+        i.get_unchecked(self)
+    }
+
+    #[inline]
+    unsafe fn get_unchecked_mut<I: SliceIndex<str>>(&mut self, i: I) -> &mut I::Output {
+        i.get_unchecked_mut(self)
+    }
+
+    #[inline]
     unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str {
-        let ptr = self.as_ptr().offset(begin as isize);
-        let len = end - begin;
-        from_utf8_unchecked(slice::from_raw_parts(ptr, len))
+        (begin..end).get_unchecked(self)
     }
 
     #[inline]
     unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str {
-        let ptr = self.as_ptr().offset(begin as isize);
-        let len = end - begin;
-        mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, len))
+        (begin..end).get_unchecked_mut(self)
     }
 
     #[inline]
@@ -2081,7 +2428,9 @@ impl StrExt for str {
     fn is_empty(&self) -> bool { self.len() == 0 }
 
     #[inline]
-    fn parse<T: FromStr>(&self) -> Result<T, T::Err> { FromStr::from_str(self) }
+    fn parse<'a, T>(&'a self) -> Result<T, T::Error> where T: TryFrom<&'a str> {
+        T::try_from(self)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 743e3c41170..0c70524ead2 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -15,27 +15,37 @@
 //! types.
 //!
 //! This module defines atomic versions of a select number of primitive
-//! types, including `AtomicBool`, `AtomicIsize`, and `AtomicUsize`.
+//! types, including [`AtomicBool`], [`AtomicIsize`], and [`AtomicUsize`].
 //! Atomic types present operations that, when used correctly, synchronize
 //! updates between threads.
 //!
-//! Each method takes an `Ordering` which represents the strength of
+//! [`AtomicBool`]: struct.AtomicBool.html
+//! [`AtomicIsize`]: struct.AtomicIsize.html
+//! [`AtomicUsize`]: struct.AtomicUsize.html
+//!
+//! Each method takes an [`Ordering`] which represents the strength of
 //! the memory barrier for that operation. These orderings are the
 //! same as [LLVM atomic orderings][1]. For more information see the [nomicon][2].
 //!
+//! [`Ordering`]: enum.Ordering.html
+//!
 //! [1]: http://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations
 //! [2]: ../../../nomicon/atomics.html
 //!
-//! Atomic variables are safe to share between threads (they implement `Sync`)
+//! Atomic variables are safe to share between threads (they implement [`Sync`])
 //! but they do not themselves provide the mechanism for sharing and follow the
 //! [threading model](../../../std/thread/index.html#the-threading-model) of rust.
-//! The most common way to share an atomic variable is to put it into an `Arc` (an
+//! The most common way to share an atomic variable is to put it into an [`Arc`][arc] (an
 //! atomically-reference-counted shared pointer).
 //!
+//! [`Sync`]: ../../marker/trait.Sync.html
+//! [arc]: ../../../std/sync/struct.Arc.html
+//!
 //! Most atomic types may be stored in static variables, initialized using
-//! the provided static initializers like `ATOMIC_BOOL_INIT`. Atomic statics
+//! the provided static initializers like [`ATOMIC_BOOL_INIT`]. Atomic statics
 //! are often used for lazy global initialization.
 //!
+//! [`ATOMIC_BOOL_INIT`]: constant.ATOMIC_BOOL_INIT.html
 //!
 //! # Examples
 //!
@@ -143,27 +153,38 @@ unsafe impl<T> Sync for AtomicPtr<T> {}
 /// Rust's memory orderings are [the same as
 /// LLVM's](http://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations).
 ///
-/// For more information see the [nomicon][1].
-/// [1]: ../../../nomicon/atomics.html
+/// For more information see the [nomicon].
+///
+/// [nomicon]: ../../../nomicon/atomics.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Copy, Clone, Debug)]
 pub enum Ordering {
-    /// No ordering constraints, only atomic operations. Corresponds to LLVM's
-    /// `Monotonic` ordering.
+    /// No ordering constraints, only atomic operations.
+    ///
+    /// Corresponds to LLVM's [`Monotonic`] ordering.
+    ///
+    /// [`Monotonic`]: http://llvm.org/docs/Atomics.html#monotonic
     #[stable(feature = "rust1", since = "1.0.0")]
     Relaxed,
     /// When coupled with a store, all previous writes become visible
-    /// to the other threads that perform a load with `Acquire` ordering
+    /// to the other threads that perform a load with [`Acquire`] ordering
     /// on the same value.
+    ///
+    /// [`Acquire`]: http://llvm.org/docs/Atomics.html#acquire
     #[stable(feature = "rust1", since = "1.0.0")]
     Release,
     /// When coupled with a load, all subsequent loads will see data
-    /// written before a store with `Release` ordering on the same value
+    /// written before a store with [`Release`] ordering on the same value
     /// in other threads.
+    ///
+    /// [`Release`]: http://llvm.org/docs/Atomics.html#release
     #[stable(feature = "rust1", since = "1.0.0")]
     Acquire,
-    /// When coupled with a load, uses `Acquire` ordering, and with a store
-    /// `Release` ordering.
+    /// When coupled with a load, uses [`Acquire`] ordering, and with a store
+    /// [`Release`] ordering.
+    ///
+    /// [`Acquire`]: http://llvm.org/docs/Atomics.html#acquire
+    /// [`Release`]: http://llvm.org/docs/Atomics.html#release
     #[stable(feature = "rust1", since = "1.0.0")]
     AcqRel,
     /// Like `AcqRel` with the additional guarantee that all threads see all
@@ -176,7 +197,9 @@ pub enum Ordering {
     __Nonexhaustive,
 }
 
-/// An `AtomicBool` initialized to `false`.
+/// An [`AtomicBool`] initialized to `false`.
+///
+/// [`AtomicBool`]: struct.AtomicBool.html
 #[cfg(target_has_atomic = "8")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool::new(false);
@@ -250,7 +273,7 @@ impl AtomicBool {
     ///
     /// [`Ordering`]: enum.Ordering.html
     /// [`Release`]: enum.Ordering.html#variant.Release
-    /// [`AcqRel`]: enum.Ordering.html#variant.Release
+    /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
     ///
     /// # Examples
     ///
@@ -287,7 +310,10 @@ impl AtomicBool {
     ///
     /// # Panics
     ///
-    /// Panics if `order` is `Acquire` or `AcqRel`.
+    /// Panics if `order` is [`Acquire`] or [`AcqRel`].
+    ///
+    /// [`Acquire`]: enum.Ordering.html#variant.Acquire
+    /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn store(&self, val: bool, order: Ordering) {
@@ -296,7 +322,7 @@ impl AtomicBool {
         }
     }
 
-    /// Stores a value into the bool, returning the old value.
+    /// Stores a value into the bool, returning the previous value.
     ///
     /// `swap` takes an [`Ordering`] argument which describes the memory ordering
     /// of this operation.
@@ -404,7 +430,7 @@ impl AtomicBool {
 
     /// Stores a value into the `bool` if the current value is the same as the `current` value.
     ///
-    /// Unlike `compare_exchange`, this function is allowed to spuriously fail even when the
+    /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even when the
     /// comparison succeeds, which can result in more efficient code on some platforms. The
     /// return value is a result indicating whether the new value was written and containing the
     /// previous value.
@@ -415,6 +441,7 @@ impl AtomicBool {
     /// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or
     /// weaker than the success ordering.
     ///
+    /// [`compare_exchange`]: #method.compare_exchange
     /// [`Ordering`]: enum.Ordering.html
     /// [`Release`]: enum.Ordering.html#variant.Release
     /// [`AcqRel`]: enum.Ordering.html#variant.Release
@@ -512,17 +539,16 @@ impl AtomicBool {
         // We can't use atomic_nand here because it can result in a bool with
         // an invalid value. This happens because the atomic operation is done
         // with an 8-bit integer internally, which would set the upper 7 bits.
-        // So we just use a compare-exchange loop instead, which is what the
-        // intrinsic actually expands to anyways on many platforms.
-        let mut old = self.load(Relaxed);
-        loop {
-            let new = !(old && val);
-            match self.compare_exchange_weak(old, new, order, Relaxed) {
-                Ok(_) => break,
-                Err(x) => old = x,
-            }
+        // So we just use fetch_xor or swap instead.
+        if val {
+            // !(x & true) == !x
+            // We must invert the bool.
+            self.fetch_xor(true, order)
+        } else {
+            // !(x & false) == true
+            // We must set the bool to true.
+            self.swap(true, order)
         }
-        old
     }
 
     /// Logical "or" with a boolean value.
@@ -694,7 +720,10 @@ impl<T> AtomicPtr<T> {
     ///
     /// # Panics
     ///
-    /// Panics if `order` is `Acquire` or `AcqRel`.
+    /// Panics if `order` is [`Acquire`] or [`AcqRel`].
+    ///
+    /// [`Acquire`]: enum.Ordering.html#variant.Acquire
+    /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn store(&self, ptr: *mut T, order: Ordering) {
@@ -703,7 +732,7 @@ impl<T> AtomicPtr<T> {
         }
     }
 
-    /// Stores a value into the pointer, returning the old value.
+    /// Stores a value into the pointer, returning the previous value.
     ///
     /// `swap` takes an [`Ordering`] argument which describes the memory ordering
     /// of this operation.
@@ -1008,14 +1037,17 @@ macro_rules! atomic_int {
             ///
             /// # Panics
             ///
-            /// Panics if `order` is `Acquire` or `AcqRel`.
+            /// Panics if `order` is [`Acquire`] or [`AcqRel`].
+            ///
+            /// [`Acquire`]: enum.Ordering.html#variant.Acquire
+            /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
             #[inline]
             #[$stable]
             pub fn store(&self, val: $int_type, order: Ordering) {
                 unsafe { atomic_store(self.v.get(), val, order); }
             }
 
-            /// Stores a value into the atomic integer, returning the old value.
+            /// Stores a value into the atomic integer, returning the previous value.
             ///
             /// `swap` takes an [`Ordering`] argument which describes the memory ordering of this
             /// operation.
@@ -1169,7 +1201,9 @@ macro_rules! atomic_int {
                 }
             }
 
-            /// Add to the current value, returning the previous value.
+            /// Adds to the current value, returning the previous value.
+            ///
+            /// This operation wraps around on overflow.
             ///
             /// # Examples
             ///
@@ -1186,7 +1220,9 @@ macro_rules! atomic_int {
                 unsafe { atomic_add(self.v.get(), val, order) }
             }
 
-            /// Subtract from the current value, returning the previous value.
+            /// Subtracts from the current value, returning the previous value.
+            ///
+            /// This operation wraps around on overflow.
             ///
             /// # Examples
             ///
@@ -1203,7 +1239,12 @@ macro_rules! atomic_int {
                 unsafe { atomic_sub(self.v.get(), val, order) }
             }
 
-            /// Bitwise and with the current value, returning the previous value.
+            /// Bitwise "and" with the current value.
+            ///
+            /// Performs a bitwise "and" operation on the current value and the argument `val`, and
+            /// sets the new value to the result.
+            ///
+            /// Returns the previous value.
             ///
             /// # Examples
             ///
@@ -1219,7 +1260,12 @@ macro_rules! atomic_int {
                 unsafe { atomic_and(self.v.get(), val, order) }
             }
 
-            /// Bitwise or with the current value, returning the previous value.
+            /// Bitwise "or" with the current value.
+            ///
+            /// Performs a bitwise "or" operation on the current value and the argument `val`, and
+            /// sets the new value to the result.
+            ///
+            /// Returns the previous value.
             ///
             /// # Examples
             ///
@@ -1235,7 +1281,12 @@ macro_rules! atomic_int {
                 unsafe { atomic_or(self.v.get(), val, order) }
             }
 
-            /// Bitwise xor with the current value, returning the previous value.
+            /// Bitwise "xor" with the current value.
+            ///
+            /// Performs a bitwise "xor" operation on the current value and the argument `val`, and
+            /// sets the new value to the result.
+            ///
+            /// Returns the previous value.
             ///
             /// # Examples
             ///
@@ -1383,7 +1434,7 @@ unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
     }
 }
 
-/// Returns the old value (like __sync_fetch_and_add).
+/// Returns the previous value (like __sync_fetch_and_add).
 #[inline]
 unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
@@ -1396,7 +1447,7 @@ unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
     }
 }
 
-/// Returns the old value (like __sync_fetch_and_sub).
+/// Returns the previous value (like __sync_fetch_and_sub).
 #[inline]
 unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
@@ -1540,6 +1591,47 @@ pub fn fence(order: Ordering) {
 }
 
 
+/// A compiler memory barrier.
+///
+/// `compiler_barrier` does not emit any machine code, but prevents the compiler from re-ordering
+/// memory operations across this point. Which reorderings are disallowed is dictated by the given
+/// [`Ordering`]. Note that `compiler_barrier` does *not* introduce inter-thread memory
+/// synchronization; for that, a [`fence`] is needed.
+///
+/// The re-ordering prevented by the different ordering semantics are:
+///
+///  - with [`SeqCst`], no re-ordering of reads and writes across this point is allowed.
+///  - with [`Release`], preceding reads and writes cannot be moved past subsequent writes.
+///  - with [`Acquire`], subsequent reads and writes cannot be moved ahead of preceding reads.
+///  - with [`AcqRel`], both of the above rules are enforced.
+///
+/// # Panics
+///
+/// Panics if `order` is [`Relaxed`].
+///
+/// [`fence`]: fn.fence.html
+/// [`Ordering`]: enum.Ordering.html
+/// [`Acquire`]: enum.Ordering.html#variant.Acquire
+/// [`SeqCst`]: enum.Ordering.html#variant.SeqCst
+/// [`Release`]: enum.Ordering.html#variant.Release
+/// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
+/// [`Relaxed`]: enum.Ordering.html#variant.Relaxed
+#[inline]
+#[unstable(feature = "compiler_barriers", issue = "41091")]
+pub fn compiler_barrier(order: Ordering) {
+    unsafe {
+        match order {
+            Acquire => intrinsics::atomic_singlethreadfence_acq(),
+            Release => intrinsics::atomic_singlethreadfence_rel(),
+            AcqRel => intrinsics::atomic_singlethreadfence_acqrel(),
+            SeqCst => intrinsics::atomic_singlethreadfence(),
+            Relaxed => panic!("there is no such thing as a relaxed barrier"),
+            __Nonexhaustive => panic!("invalid memory ordering"),
+        }
+    }
+}
+
+
 #[cfg(target_has_atomic = "8")]
 #[stable(feature = "atomic_debug", since = "1.3.0")]
 impl fmt::Debug for AtomicBool {
diff --git a/src/libcore/tests/any.rs b/src/libcore/tests/any.rs
new file mode 100644
index 00000000000..2d3e81aa131
--- /dev/null
+++ b/src/libcore/tests/any.rs
@@ -0,0 +1,125 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::any::*;
+
+#[derive(PartialEq, Debug)]
+struct Test;
+
+static TEST: &'static str = "Test";
+
+#[test]
+fn any_referenced() {
+    let (a, b, c) = (&5 as &Any, &TEST as &Any, &Test as &Any);
+
+    assert!(a.is::<i32>());
+    assert!(!b.is::<i32>());
+    assert!(!c.is::<i32>());
+
+    assert!(!a.is::<&'static str>());
+    assert!(b.is::<&'static str>());
+    assert!(!c.is::<&'static str>());
+
+    assert!(!a.is::<Test>());
+    assert!(!b.is::<Test>());
+    assert!(c.is::<Test>());
+}
+
+#[test]
+fn any_owning() {
+    let (a, b, c) = (box 5_usize as Box<Any>, box TEST as Box<Any>, box Test as Box<Any>);
+
+    assert!(a.is::<usize>());
+    assert!(!b.is::<usize>());
+    assert!(!c.is::<usize>());
+
+    assert!(!a.is::<&'static str>());
+    assert!(b.is::<&'static str>());
+    assert!(!c.is::<&'static str>());
+
+    assert!(!a.is::<Test>());
+    assert!(!b.is::<Test>());
+    assert!(c.is::<Test>());
+}
+
+#[test]
+fn any_downcast_ref() {
+    let a = &5_usize as &Any;
+
+    match a.downcast_ref::<usize>() {
+        Some(&5) => {}
+        x => panic!("Unexpected value {:?}", x)
+    }
+
+    match a.downcast_ref::<Test>() {
+        None => {}
+        x => panic!("Unexpected value {:?}", x)
+    }
+}
+
+#[test]
+fn any_downcast_mut() {
+    let mut a = 5_usize;
+    let mut b: Box<_> = box 7_usize;
+
+    let a_r = &mut a as &mut Any;
+    let tmp: &mut usize = &mut *b;
+    let b_r = tmp as &mut Any;
+
+    match a_r.downcast_mut::<usize>() {
+        Some(x) => {
+            assert_eq!(*x, 5);
+            *x = 612;
+        }
+        x => panic!("Unexpected value {:?}", x)
+    }
+
+    match b_r.downcast_mut::<usize>() {
+        Some(x) => {
+            assert_eq!(*x, 7);
+            *x = 413;
+        }
+        x => panic!("Unexpected value {:?}", x)
+    }
+
+    match a_r.downcast_mut::<Test>() {
+        None => (),
+        x => panic!("Unexpected value {:?}", x)
+    }
+
+    match b_r.downcast_mut::<Test>() {
+        None => (),
+        x => panic!("Unexpected value {:?}", x)
+    }
+
+    match a_r.downcast_mut::<usize>() {
+        Some(&mut 612) => {}
+        x => panic!("Unexpected value {:?}", x)
+    }
+
+    match b_r.downcast_mut::<usize>() {
+        Some(&mut 413) => {}
+        x => panic!("Unexpected value {:?}", x)
+    }
+}
+
+#[test]
+fn any_fixed_vec() {
+    let test = [0_usize; 8];
+    let test = &test as &Any;
+    assert!(test.is::<[usize; 8]>());
+    assert!(!test.is::<[usize; 10]>());
+}
+
+#[test]
+fn any_unsized() {
+    fn is_any<T: Any + ?Sized>() {}
+    is_any::<[i32]>();
+}
diff --git a/src/libcore/tests/array.rs b/src/libcore/tests/array.rs
new file mode 100644
index 00000000000..6af031dee58
--- /dev/null
+++ b/src/libcore/tests/array.rs
@@ -0,0 +1,28 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+use core::array::FixedSizeArray;
+
+#[test]
+fn fixed_size_array() {
+    let mut array = [0; 64];
+    let mut zero_sized = [(); 64];
+    let mut empty_array = [0; 0];
+    let mut empty_zero_sized = [(); 0];
+
+    assert_eq!(FixedSizeArray::as_slice(&array).len(), 64);
+    assert_eq!(FixedSizeArray::as_slice(&zero_sized).len(), 64);
+    assert_eq!(FixedSizeArray::as_slice(&empty_array).len(), 0);
+    assert_eq!(FixedSizeArray::as_slice(&empty_zero_sized).len(), 0);
+
+    assert_eq!(FixedSizeArray::as_mut_slice(&mut array).len(), 64);
+    assert_eq!(FixedSizeArray::as_mut_slice(&mut zero_sized).len(), 64);
+    assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_array).len(), 0);
+    assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_zero_sized).len(), 0);
+}
diff --git a/src/libcore/tests/atomic.rs b/src/libcore/tests/atomic.rs
new file mode 100644
index 00000000000..9babe24a985
--- /dev/null
+++ b/src/libcore/tests/atomic.rs
@@ -0,0 +1,97 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::sync::atomic::*;
+use core::sync::atomic::Ordering::SeqCst;
+
+#[test]
+fn bool_() {
+    let a = AtomicBool::new(false);
+    assert_eq!(a.compare_and_swap(false, true, SeqCst), false);
+    assert_eq!(a.compare_and_swap(false, true, SeqCst), true);
+
+    a.store(false, SeqCst);
+    assert_eq!(a.compare_and_swap(false, true, SeqCst), false);
+}
+
+#[test]
+fn bool_and() {
+    let a = AtomicBool::new(true);
+    assert_eq!(a.fetch_and(false, SeqCst), true);
+    assert_eq!(a.load(SeqCst),false);
+}
+
+#[test]
+fn bool_nand() {
+    let a = AtomicBool::new(false);
+    assert_eq!(a.fetch_nand(false, SeqCst), false);
+    assert_eq!(a.load(SeqCst), true);
+    assert_eq!(a.fetch_nand(false, SeqCst), true);
+    assert_eq!(a.load(SeqCst), true);
+    assert_eq!(a.fetch_nand(true, SeqCst), true);
+    assert_eq!(a.load(SeqCst), false);
+    assert_eq!(a.fetch_nand(true, SeqCst), false);
+    assert_eq!(a.load(SeqCst), true);
+}
+
+#[test]
+fn uint_and() {
+    let x = AtomicUsize::new(0xf731);
+    assert_eq!(x.fetch_and(0x137f, SeqCst), 0xf731);
+    assert_eq!(x.load(SeqCst), 0xf731 & 0x137f);
+}
+
+#[test]
+fn uint_or() {
+    let x = AtomicUsize::new(0xf731);
+    assert_eq!(x.fetch_or(0x137f, SeqCst), 0xf731);
+    assert_eq!(x.load(SeqCst), 0xf731 | 0x137f);
+}
+
+#[test]
+fn uint_xor() {
+    let x = AtomicUsize::new(0xf731);
+    assert_eq!(x.fetch_xor(0x137f, SeqCst), 0xf731);
+    assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f);
+}
+
+#[test]
+fn int_and() {
+    let x = AtomicIsize::new(0xf731);
+    assert_eq!(x.fetch_and(0x137f, SeqCst), 0xf731);
+    assert_eq!(x.load(SeqCst), 0xf731 & 0x137f);
+}
+
+#[test]
+fn int_or() {
+    let x = AtomicIsize::new(0xf731);
+    assert_eq!(x.fetch_or(0x137f, SeqCst), 0xf731);
+    assert_eq!(x.load(SeqCst), 0xf731 | 0x137f);
+}
+
+#[test]
+fn int_xor() {
+    let x = AtomicIsize::new(0xf731);
+    assert_eq!(x.fetch_xor(0x137f, SeqCst), 0xf731);
+    assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f);
+}
+
+static S_FALSE: AtomicBool = AtomicBool::new(false);
+static S_TRUE: AtomicBool = AtomicBool::new(true);
+static S_INT: AtomicIsize  = AtomicIsize::new(0);
+static S_UINT: AtomicUsize = AtomicUsize::new(0);
+
+#[test]
+fn static_init() {
+    assert!(!S_FALSE.load(SeqCst));
+    assert!(S_TRUE.load(SeqCst));
+    assert!(S_INT.load(SeqCst) == 0);
+    assert!(S_UINT.load(SeqCst) == 0);
+}
diff --git a/src/libcore/tests/cell.rs b/src/libcore/tests/cell.rs
new file mode 100644
index 00000000000..8585f2f0871
--- /dev/null
+++ b/src/libcore/tests/cell.rs
@@ -0,0 +1,289 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::cell::*;
+use core::default::Default;
+use std::mem::drop;
+
+#[test]
+fn smoketest_cell() {
+    let x = Cell::new(10);
+    assert!(x == Cell::new(10));
+    assert!(x.get() == 10);
+    x.set(20);
+    assert!(x == Cell::new(20));
+    assert!(x.get() == 20);
+
+    let y = Cell::new((30, 40));
+    assert!(y == Cell::new((30, 40)));
+    assert!(y.get() == (30, 40));
+}
+
+#[test]
+fn cell_has_sensible_show() {
+    let x = Cell::new("foo bar");
+    assert!(format!("{:?}", x).contains(x.get()));
+
+    x.set("baz qux");
+    assert!(format!("{:?}", x).contains(x.get()));
+}
+
+#[test]
+fn ref_and_refmut_have_sensible_show() {
+    let refcell = RefCell::new("foo");
+
+    let refcell_refmut = refcell.borrow_mut();
+    assert!(format!("{:?}", refcell_refmut).contains("foo"));
+    drop(refcell_refmut);
+
+    let refcell_ref = refcell.borrow();
+    assert!(format!("{:?}", refcell_ref).contains("foo"));
+    drop(refcell_ref);
+}
+
+#[test]
+fn double_imm_borrow() {
+    let x = RefCell::new(0);
+    let _b1 = x.borrow();
+    x.borrow();
+}
+
+#[test]
+fn no_mut_then_imm_borrow() {
+    let x = RefCell::new(0);
+    let _b1 = x.borrow_mut();
+    assert!(x.try_borrow().is_err());
+}
+
+#[test]
+fn no_imm_then_borrow_mut() {
+    let x = RefCell::new(0);
+    let _b1 = x.borrow();
+    assert!(x.try_borrow_mut().is_err());
+}
+
+#[test]
+fn no_double_borrow_mut() {
+    let x = RefCell::new(0);
+    assert!(x.try_borrow().is_ok());
+    let _b1 = x.borrow_mut();
+    assert!(x.try_borrow().is_err());
+}
+
+#[test]
+fn imm_release_borrow_mut() {
+    let x = RefCell::new(0);
+    {
+        let _b1 = x.borrow();
+    }
+    x.borrow_mut();
+}
+
+#[test]
+fn mut_release_borrow_mut() {
+    let x = RefCell::new(0);
+    {
+        let _b1 = x.borrow_mut();
+    }
+    x.borrow();
+}
+
+#[test]
+fn double_borrow_single_release_no_borrow_mut() {
+    let x = RefCell::new(0);
+    let _b1 = x.borrow();
+    {
+        let _b2 = x.borrow();
+    }
+    assert!(x.try_borrow().is_ok());
+    assert!(x.try_borrow_mut().is_err());
+}
+
+#[test]
+#[should_panic]
+fn discard_doesnt_unborrow() {
+    let x = RefCell::new(0);
+    let _b = x.borrow();
+    let _ = _b;
+    let _b = x.borrow_mut();
+}
+
+#[test]
+fn ref_clone_updates_flag() {
+    let x = RefCell::new(0);
+    {
+        let b1 = x.borrow();
+        assert!(x.try_borrow().is_ok());
+        assert!(x.try_borrow_mut().is_err());
+        {
+            let _b2 = Ref::clone(&b1);
+            assert!(x.try_borrow().is_ok());
+            assert!(x.try_borrow_mut().is_err());
+        }
+        assert!(x.try_borrow().is_ok());
+        assert!(x.try_borrow_mut().is_err());
+    }
+    assert!(x.try_borrow().is_ok());
+    assert!(x.try_borrow_mut().is_ok());
+}
+
+#[test]
+fn ref_map_does_not_update_flag() {
+    let x = RefCell::new(Some(5));
+    {
+        let b1: Ref<Option<u32>> = x.borrow();
+        assert!(x.try_borrow().is_ok());
+        assert!(x.try_borrow_mut().is_err());
+        {
+            let b2: Ref<u32> = Ref::map(b1, |o| o.as_ref().unwrap());
+            assert_eq!(*b2, 5);
+            assert!(x.try_borrow().is_ok());
+            assert!(x.try_borrow_mut().is_err());
+        }
+        assert!(x.try_borrow().is_ok());
+        assert!(x.try_borrow_mut().is_ok());
+    }
+    assert!(x.try_borrow().is_ok());
+    assert!(x.try_borrow_mut().is_ok());
+}
+
+#[test]
+fn ref_map_accessor() {
+    struct X(RefCell<(u32, char)>);
+    impl X {
+        fn accessor(&self) -> Ref<u32> {
+            Ref::map(self.0.borrow(), |tuple| &tuple.0)
+        }
+    }
+    let x = X(RefCell::new((7, 'z')));
+    let d: Ref<u32> = x.accessor();
+    assert_eq!(*d, 7);
+}
+
+#[test]
+fn ref_mut_map_accessor() {
+    struct X(RefCell<(u32, char)>);
+    impl X {
+        fn accessor(&self) -> RefMut<u32> {
+            RefMut::map(self.0.borrow_mut(), |tuple| &mut tuple.0)
+        }
+    }
+    let x = X(RefCell::new((7, 'z')));
+    {
+        let mut d: RefMut<u32> = x.accessor();
+        assert_eq!(*d, 7);
+        *d += 1;
+    }
+    assert_eq!(*x.0.borrow(), (8, 'z'));
+}
+
+#[test]
+fn as_ptr() {
+    let c1: Cell<usize> = Cell::new(0);
+    c1.set(1);
+    assert_eq!(1, unsafe { *c1.as_ptr() });
+
+    let c2: Cell<usize> = Cell::new(0);
+    unsafe { *c2.as_ptr() = 1; }
+    assert_eq!(1, c2.get());
+
+    let r1: RefCell<usize> = RefCell::new(0);
+    *r1.borrow_mut() = 1;
+    assert_eq!(1, unsafe { *r1.as_ptr() });
+
+    let r2: RefCell<usize> = RefCell::new(0);
+    unsafe { *r2.as_ptr() = 1; }
+    assert_eq!(1, *r2.borrow());
+}
+
+#[test]
+fn cell_default() {
+    let cell: Cell<u32> = Default::default();
+    assert_eq!(0, cell.get());
+}
+
+#[test]
+fn cell_set() {
+    let cell = Cell::new(10);
+    cell.set(20);
+    assert_eq!(20, cell.get());
+
+    let cell = Cell::new("Hello".to_owned());
+    cell.set("World".to_owned());
+    assert_eq!("World".to_owned(), cell.into_inner());
+}
+
+#[test]
+fn cell_replace() {
+    let cell = Cell::new(10);
+    assert_eq!(10, cell.replace(20));
+    assert_eq!(20, cell.get());
+
+    let cell = Cell::new("Hello".to_owned());
+    assert_eq!("Hello".to_owned(), cell.replace("World".to_owned()));
+    assert_eq!("World".to_owned(), cell.into_inner());
+}
+
+#[test]
+fn cell_into_inner() {
+    let cell = Cell::new(10);
+    assert_eq!(10, cell.into_inner());
+
+    let cell = Cell::new("Hello world".to_owned());
+    assert_eq!("Hello world".to_owned(), cell.into_inner());
+}
+
+#[test]
+fn refcell_default() {
+    let cell: RefCell<u64> = Default::default();
+    assert_eq!(0, *cell.borrow());
+}
+
+#[test]
+fn unsafe_cell_unsized() {
+    let cell: &UnsafeCell<[i32]> = &UnsafeCell::new([1, 2, 3]);
+    {
+        let val: &mut [i32] = unsafe { &mut *cell.get() };
+        val[0] = 4;
+        val[2] = 5;
+    }
+    let comp: &mut [i32] = &mut [4, 2, 5];
+    assert_eq!(unsafe { &mut *cell.get() }, comp);
+}
+
+#[test]
+fn refcell_unsized() {
+    let cell: &RefCell<[i32]> = &RefCell::new([1, 2, 3]);
+    {
+        let b = &mut *cell.borrow_mut();
+        b[0] = 4;
+        b[2] = 5;
+    }
+    let comp: &mut [i32] = &mut [4, 2, 5];
+    assert_eq!(&*cell.borrow(), comp);
+}
+
+#[test]
+fn refcell_ref_coercion() {
+    let cell: RefCell<[i32; 3]> = RefCell::new([1, 2, 3]);
+    {
+        let mut cellref: RefMut<[i32; 3]> = cell.borrow_mut();
+        cellref[0] = 4;
+        let mut coerced: RefMut<[i32]> = cellref;
+        coerced[2] = 5;
+    }
+    {
+        let comp: &mut [i32] = &mut [4, 2, 5];
+        let cellref: Ref<[i32; 3]> = cell.borrow();
+        assert_eq!(&*cellref, comp);
+        let coerced: Ref<[i32]> = cellref;
+        assert_eq!(&*coerced, comp);
+    }
+}
diff --git a/src/libcore/tests/char.rs b/src/libcore/tests/char.rs
new file mode 100644
index 00000000000..e4012ec91e2
--- /dev/null
+++ b/src/libcore/tests/char.rs
@@ -0,0 +1,404 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::{char,str};
+use std::convert::TryFrom;
+
+#[test]
+fn test_convert() {
+    assert_eq!(u32::from('a'), 0x61);
+    assert_eq!(char::from(b'\0'), '\0');
+    assert_eq!(char::from(b'a'), 'a');
+    assert_eq!(char::from(b'\xFF'), '\u{FF}');
+    assert_eq!(char::try_from(0_u32), Ok('\0'));
+    assert_eq!(char::try_from(0x61_u32), Ok('a'));
+    assert_eq!(char::try_from(0xD7FF_u32), Ok('\u{D7FF}'));
+    assert!(char::try_from(0xD800_u32).is_err());
+    assert!(char::try_from(0xDFFF_u32).is_err());
+    assert_eq!(char::try_from(0xE000_u32), Ok('\u{E000}'));
+    assert_eq!(char::try_from(0x10FFFF_u32), Ok('\u{10FFFF}'));
+    assert!(char::try_from(0x110000_u32).is_err());
+    assert!(char::try_from(0xFFFF_FFFF_u32).is_err());
+}
+
+#[test]
+fn test_is_lowercase() {
+    assert!('a'.is_lowercase());
+    assert!('ö'.is_lowercase());
+    assert!('ß'.is_lowercase());
+    assert!(!'Ü'.is_lowercase());
+    assert!(!'P'.is_lowercase());
+}
+
+#[test]
+fn test_is_uppercase() {
+    assert!(!'h'.is_uppercase());
+    assert!(!'ä'.is_uppercase());
+    assert!(!'ß'.is_uppercase());
+    assert!('Ö'.is_uppercase());
+    assert!('T'.is_uppercase());
+}
+
+#[test]
+fn test_is_whitespace() {
+    assert!(' '.is_whitespace());
+    assert!('\u{2007}'.is_whitespace());
+    assert!('\t'.is_whitespace());
+    assert!('\n'.is_whitespace());
+    assert!(!'a'.is_whitespace());
+    assert!(!'_'.is_whitespace());
+    assert!(!'\u{0}'.is_whitespace());
+}
+
+#[test]
+fn test_to_digit() {
+    assert_eq!('0'.to_digit(10), Some(0));
+    assert_eq!('1'.to_digit(2), Some(1));
+    assert_eq!('2'.to_digit(3), Some(2));
+    assert_eq!('9'.to_digit(10), Some(9));
+    assert_eq!('a'.to_digit(16), Some(10));
+    assert_eq!('A'.to_digit(16), Some(10));
+    assert_eq!('b'.to_digit(16), Some(11));
+    assert_eq!('B'.to_digit(16), Some(11));
+    assert_eq!('z'.to_digit(36), Some(35));
+    assert_eq!('Z'.to_digit(36), Some(35));
+    assert_eq!(' '.to_digit(10), None);
+    assert_eq!('$'.to_digit(36), None);
+}
+
+#[test]
+fn test_to_lowercase() {
+    fn lower(c: char) -> String {
+        let iter: String = c.to_lowercase().collect();
+        let disp: String = c.to_lowercase().to_string();
+        assert_eq!(iter, disp);
+        iter
+    }
+    assert_eq!(lower('A'), "a");
+    assert_eq!(lower('Ö'), "ö");
+    assert_eq!(lower('ß'), "ß");
+    assert_eq!(lower('Ü'), "ü");
+    assert_eq!(lower('💩'), "💩");
+    assert_eq!(lower('Σ'), "σ");
+    assert_eq!(lower('Τ'), "τ");
+    assert_eq!(lower('Ι'), "ι");
+    assert_eq!(lower('Γ'), "γ");
+    assert_eq!(lower('Μ'), "μ");
+    assert_eq!(lower('Α'), "α");
+    assert_eq!(lower('Σ'), "σ");
+    assert_eq!(lower('Dž'), "dž");
+    assert_eq!(lower('fi'), "fi");
+    assert_eq!(lower('İ'), "i\u{307}");
+}
+
+#[test]
+fn test_to_uppercase() {
+    fn upper(c: char) -> String {
+        let iter: String = c.to_uppercase().collect();
+        let disp: String = c.to_uppercase().to_string();
+        assert_eq!(iter, disp);
+        iter
+    }
+    assert_eq!(upper('a'), "A");
+    assert_eq!(upper('ö'), "Ö");
+    assert_eq!(upper('ß'), "SS"); // not ẞ: Latin capital letter sharp s
+    assert_eq!(upper('ü'), "Ü");
+    assert_eq!(upper('💩'), "💩");
+
+    assert_eq!(upper('σ'), "Σ");
+    assert_eq!(upper('τ'), "Τ");
+    assert_eq!(upper('ι'), "Ι");
+    assert_eq!(upper('γ'), "Γ");
+    assert_eq!(upper('μ'), "Μ");
+    assert_eq!(upper('α'), "Α");
+    assert_eq!(upper('ς'), "Σ");
+    assert_eq!(upper('Dž'), "DŽ");
+    assert_eq!(upper('fi'), "FI");
+    assert_eq!(upper('ᾀ'), "ἈΙ");
+}
+
+#[test]
+fn test_is_control() {
+    assert!('\u{0}'.is_control());
+    assert!('\u{3}'.is_control());
+    assert!('\u{6}'.is_control());
+    assert!('\u{9}'.is_control());
+    assert!('\u{7f}'.is_control());
+    assert!('\u{92}'.is_control());
+    assert!(!'\u{20}'.is_control());
+    assert!(!'\u{55}'.is_control());
+    assert!(!'\u{68}'.is_control());
+}
+
+#[test]
+fn test_is_digit() {
+   assert!('2'.is_numeric());
+   assert!('7'.is_numeric());
+   assert!(!'c'.is_numeric());
+   assert!(!'i'.is_numeric());
+   assert!(!'z'.is_numeric());
+   assert!(!'Q'.is_numeric());
+}
+
+#[test]
+fn test_escape_debug() {
+    fn string(c: char) -> String {
+        let iter: String = c.escape_debug().collect();
+        let disp: String = c.escape_debug().to_string();
+        assert_eq!(iter, disp);
+        iter
+    }
+    assert_eq!(string('\n'), "\\n");
+    assert_eq!(string('\r'), "\\r");
+    assert_eq!(string('\''), "\\'");
+    assert_eq!(string('"'), "\\\"");
+    assert_eq!(string(' '), " ");
+    assert_eq!(string('a'), "a");
+    assert_eq!(string('~'), "~");
+    assert_eq!(string('é'), "é");
+    assert_eq!(string('文'), "文");
+    assert_eq!(string('\x00'), "\\u{0}");
+    assert_eq!(string('\x1f'), "\\u{1f}");
+    assert_eq!(string('\x7f'), "\\u{7f}");
+    assert_eq!(string('\u{80}'), "\\u{80}");
+    assert_eq!(string('\u{ff}'), "\u{ff}");
+    assert_eq!(string('\u{11b}'), "\u{11b}");
+    assert_eq!(string('\u{1d4b6}'), "\u{1d4b6}");
+    assert_eq!(string('\u{200b}'),"\\u{200b}");      // zero width space
+    assert_eq!(string('\u{e000}'), "\\u{e000}");     // private use 1
+    assert_eq!(string('\u{100000}'), "\\u{100000}"); // private use 2
+}
+
+#[test]
+fn test_escape_default() {
+    fn string(c: char) -> String {
+        let iter: String = c.escape_default().collect();
+        let disp: String = c.escape_default().to_string();
+        assert_eq!(iter, disp);
+        iter
+    }
+    assert_eq!(string('\n'), "\\n");
+    assert_eq!(string('\r'), "\\r");
+    assert_eq!(string('\''), "\\'");
+    assert_eq!(string('"'), "\\\"");
+    assert_eq!(string(' '), " ");
+    assert_eq!(string('a'), "a");
+    assert_eq!(string('~'), "~");
+    assert_eq!(string('é'), "\\u{e9}");
+    assert_eq!(string('\x00'), "\\u{0}");
+    assert_eq!(string('\x1f'), "\\u{1f}");
+    assert_eq!(string('\x7f'), "\\u{7f}");
+    assert_eq!(string('\u{80}'), "\\u{80}");
+    assert_eq!(string('\u{ff}'), "\\u{ff}");
+    assert_eq!(string('\u{11b}'), "\\u{11b}");
+    assert_eq!(string('\u{1d4b6}'), "\\u{1d4b6}");
+    assert_eq!(string('\u{200b}'), "\\u{200b}"); // zero width space
+    assert_eq!(string('\u{e000}'), "\\u{e000}"); // private use 1
+    assert_eq!(string('\u{100000}'), "\\u{100000}"); // private use 2
+}
+
+#[test]
+fn test_escape_unicode() {
+    fn string(c: char) -> String {
+        let iter: String = c.escape_unicode().collect();
+        let disp: String = c.escape_unicode().to_string();
+        assert_eq!(iter, disp);
+        iter
+    }
+
+    assert_eq!(string('\x00'), "\\u{0}");
+    assert_eq!(string('\n'), "\\u{a}");
+    assert_eq!(string(' '), "\\u{20}");
+    assert_eq!(string('a'), "\\u{61}");
+    assert_eq!(string('\u{11b}'), "\\u{11b}");
+    assert_eq!(string('\u{1d4b6}'), "\\u{1d4b6}");
+}
+
+#[test]
+fn test_encode_utf8() {
+    fn check(input: char, expect: &[u8]) {
+        let mut buf = [0; 4];
+        let ptr = buf.as_ptr();
+        let s = input.encode_utf8(&mut buf);
+        assert_eq!(s.as_ptr() as usize, ptr as usize);
+        assert!(str::from_utf8(s.as_bytes()).is_ok());
+        assert_eq!(s.as_bytes(), expect);
+    }
+
+    check('x', &[0x78]);
+    check('\u{e9}', &[0xc3, 0xa9]);
+    check('\u{a66e}', &[0xea, 0x99, 0xae]);
+    check('\u{1f4a9}', &[0xf0, 0x9f, 0x92, 0xa9]);
+}
+
+#[test]
+fn test_encode_utf16() {
+    fn check(input: char, expect: &[u16]) {
+        let mut buf = [0; 2];
+        let ptr = buf.as_mut_ptr();
+        let b = input.encode_utf16(&mut buf);
+        assert_eq!(b.as_mut_ptr() as usize, ptr as usize);
+        assert_eq!(b, expect);
+    }
+
+    check('x', &[0x0078]);
+    check('\u{e9}', &[0x00e9]);
+    check('\u{a66e}', &[0xa66e]);
+    check('\u{1f4a9}', &[0xd83d, 0xdca9]);
+}
+
+#[test]
+fn test_len_utf16() {
+    assert!('x'.len_utf16() == 1);
+    assert!('\u{e9}'.len_utf16() == 1);
+    assert!('\u{a66e}'.len_utf16() == 1);
+    assert!('\u{1f4a9}'.len_utf16() == 2);
+}
+
+#[test]
+fn test_decode_utf16() {
+    fn check(s: &[u16], expected: &[Result<char, u16>]) {
+        let v = char::decode_utf16(s.iter().cloned())
+                     .map(|r| r.map_err(|e| e.unpaired_surrogate()))
+                     .collect::<Vec<_>>();
+        assert_eq!(v, expected);
+    }
+    check(&[0xD800, 0x41, 0x42], &[Err(0xD800), Ok('A'), Ok('B')]);
+    check(&[0xD800, 0], &[Err(0xD800), Ok('\0')]);
+}
+
+#[test]
+fn ed_iterator_specializations() {
+    // Check counting
+    assert_eq!('\n'.escape_default().count(), 2);
+    assert_eq!('c'.escape_default().count(), 1);
+    assert_eq!(' '.escape_default().count(), 1);
+    assert_eq!('\\'.escape_default().count(), 2);
+    assert_eq!('\''.escape_default().count(), 2);
+
+    // Check nth
+
+    // Check that OoB is handled correctly
+    assert_eq!('\n'.escape_default().nth(2), None);
+    assert_eq!('c'.escape_default().nth(1), None);
+    assert_eq!(' '.escape_default().nth(1), None);
+    assert_eq!('\\'.escape_default().nth(2), None);
+    assert_eq!('\''.escape_default().nth(2), None);
+
+    // Check the first char
+    assert_eq!('\n'.escape_default().nth(0), Some('\\'));
+    assert_eq!('c'.escape_default().nth(0), Some('c'));
+    assert_eq!(' '.escape_default().nth(0), Some(' '));
+    assert_eq!('\\'.escape_default().nth(0), Some('\\'));
+    assert_eq!('\''.escape_default().nth(0), Some('\\'));
+
+    // Check the second char
+    assert_eq!('\n'.escape_default().nth(1), Some('n'));
+    assert_eq!('\\'.escape_default().nth(1), Some('\\'));
+    assert_eq!('\''.escape_default().nth(1), Some('\''));
+
+    // Check the last char
+    assert_eq!('\n'.escape_default().last(), Some('n'));
+    assert_eq!('c'.escape_default().last(), Some('c'));
+    assert_eq!(' '.escape_default().last(), Some(' '));
+    assert_eq!('\\'.escape_default().last(), Some('\\'));
+    assert_eq!('\''.escape_default().last(), Some('\''));
+}
+
+#[test]
+fn eu_iterator_specializations() {
+    fn check(c: char) {
+        let len = c.escape_unicode().count();
+
+        // Check OoB
+        assert_eq!(c.escape_unicode().nth(len), None);
+
+        // For all possible in-bound offsets
+        let mut iter = c.escape_unicode();
+        for offset in 0..len {
+            // Check last
+            assert_eq!(iter.clone().last(), Some('}'));
+
+            // Check len
+            assert_eq!(iter.len(), len - offset);
+
+            // Check size_hint (= len in ExactSizeIterator)
+            assert_eq!(iter.size_hint(), (iter.len(), Some(iter.len())));
+
+            // Check counting
+            assert_eq!(iter.clone().count(), len - offset);
+
+            // Check nth
+            assert_eq!(c.escape_unicode().nth(offset), iter.next());
+        }
+
+        // Check post-last
+        assert_eq!(iter.clone().last(), None);
+        assert_eq!(iter.clone().count(), 0);
+    }
+
+    check('\u{0}');
+    check('\u{1}');
+    check('\u{12}');
+    check('\u{123}');
+    check('\u{1234}');
+    check('\u{12340}');
+    check('\u{10FFFF}');
+}
+
+#[test]
+fn test_decode_utf8() {
+    macro_rules! assert_decode_utf8 {
+        ($input_bytes: expr, $expected_str: expr) => {
+            let input_bytes: &[u8] = &$input_bytes;
+            let s = char::decode_utf8(input_bytes.iter().cloned())
+                .map(|r_b| r_b.unwrap_or('\u{FFFD}'))
+                .collect::<String>();
+            assert_eq!(s, $expected_str,
+                       "input bytes: {:?}, expected str: {:?}, result: {:?}",
+                       input_bytes, $expected_str, s);
+            assert_eq!(String::from_utf8_lossy(&$input_bytes), $expected_str);
+        }
+    }
+
+    assert_decode_utf8!([], "");
+    assert_decode_utf8!([0x41], "A");
+    assert_decode_utf8!([0xC1, 0x81], "��");
+    assert_decode_utf8!([0xE2, 0x99, 0xA5], "♥");
+    assert_decode_utf8!([0xE2, 0x99, 0xA5, 0x41], "♥A");
+    assert_decode_utf8!([0xE2, 0x99], "�");
+    assert_decode_utf8!([0xE2, 0x99, 0x41], "�A");
+    assert_decode_utf8!([0xC0], "�");
+    assert_decode_utf8!([0xC0, 0x41], "�A");
+    assert_decode_utf8!([0x80], "�");
+    assert_decode_utf8!([0x80, 0x41], "�A");
+    assert_decode_utf8!([0xFE], "�");
+    assert_decode_utf8!([0xFE, 0x41], "�A");
+    assert_decode_utf8!([0xFF], "�");
+    assert_decode_utf8!([0xFF, 0x41], "�A");
+    assert_decode_utf8!([0xC0, 0x80], "��");
+
+    // Surrogates
+    assert_decode_utf8!([0xED, 0x9F, 0xBF], "\u{D7FF}");
+    assert_decode_utf8!([0xED, 0xA0, 0x80], "���");
+    assert_decode_utf8!([0xED, 0xBF, 0x80], "���");
+    assert_decode_utf8!([0xEE, 0x80, 0x80], "\u{E000}");
+
+    // char::MAX
+    assert_decode_utf8!([0xF4, 0x8F, 0xBF, 0xBF], "\u{10FFFF}");
+    assert_decode_utf8!([0xF4, 0x8F, 0xBF, 0x41], "�A");
+    assert_decode_utf8!([0xF4, 0x90, 0x80, 0x80], "����");
+
+    // 5 and 6 bytes sequence
+    // Part of the original design of UTF-8,
+    // but invalid now that UTF-8 is artificially restricted to match the range of UTF-16.
+    assert_decode_utf8!([0xF8, 0x80, 0x80, 0x80, 0x80], "�����");
+    assert_decode_utf8!([0xFC, 0x80, 0x80, 0x80, 0x80, 0x80], "������");
+}
diff --git a/src/libcore/tests/clone.rs b/src/libcore/tests/clone.rs
new file mode 100644
index 00000000000..91d68ba3344
--- /dev/null
+++ b/src/libcore/tests/clone.rs
@@ -0,0 +1,25 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[test]
+fn test_borrowed_clone() {
+    let x = 5;
+    let y: &i32 = &x;
+    let z: &i32 = (&y).clone();
+    assert_eq!(*z, 5);
+}
+
+#[test]
+fn test_clone_from() {
+    let a = box 5;
+    let mut b = box 10;
+    b.clone_from(&a);
+    assert_eq!(*b, 5);
+}
diff --git a/src/libcore/tests/cmp.rs b/src/libcore/tests/cmp.rs
new file mode 100644
index 00000000000..e3c65ad8b33
--- /dev/null
+++ b/src/libcore/tests/cmp.rs
@@ -0,0 +1,88 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::cmp::Ordering::{Less, Greater, Equal};
+
+#[test]
+fn test_int_totalord() {
+    assert_eq!(5.cmp(&10), Less);
+    assert_eq!(10.cmp(&5), Greater);
+    assert_eq!(5.cmp(&5), Equal);
+    assert_eq!((-5).cmp(&12), Less);
+    assert_eq!(12.cmp(&-5), Greater);
+}
+
+#[test]
+fn test_mut_int_totalord() {
+    assert_eq!((&mut 5).cmp(&&mut 10), Less);
+    assert_eq!((&mut 10).cmp(&&mut 5), Greater);
+    assert_eq!((&mut 5).cmp(&&mut 5), Equal);
+    assert_eq!((&mut -5).cmp(&&mut 12), Less);
+    assert_eq!((&mut 12).cmp(&&mut -5), Greater);
+}
+
+#[test]
+fn test_ordering_reverse() {
+    assert_eq!(Less.reverse(), Greater);
+    assert_eq!(Equal.reverse(), Equal);
+    assert_eq!(Greater.reverse(), Less);
+}
+
+#[test]
+fn test_ordering_order() {
+    assert!(Less < Equal);
+    assert_eq!(Greater.cmp(&Less), Greater);
+}
+
+#[test]
+fn test_ordering_then() {
+    assert_eq!(Equal.then(Less), Less);
+    assert_eq!(Equal.then(Equal), Equal);
+    assert_eq!(Equal.then(Greater), Greater);
+    assert_eq!(Less.then(Less), Less);
+    assert_eq!(Less.then(Equal), Less);
+    assert_eq!(Less.then(Greater), Less);
+    assert_eq!(Greater.then(Less), Greater);
+    assert_eq!(Greater.then(Equal), Greater);
+    assert_eq!(Greater.then(Greater), Greater);
+}
+
+#[test]
+fn test_ordering_then_with() {
+    assert_eq!(Equal.then_with(|| Less), Less);
+    assert_eq!(Equal.then_with(|| Equal), Equal);
+    assert_eq!(Equal.then_with(|| Greater), Greater);
+    assert_eq!(Less.then_with(|| Less), Less);
+    assert_eq!(Less.then_with(|| Equal), Less);
+    assert_eq!(Less.then_with(|| Greater), Less);
+    assert_eq!(Greater.then_with(|| Less), Greater);
+    assert_eq!(Greater.then_with(|| Equal), Greater);
+    assert_eq!(Greater.then_with(|| Greater), Greater);
+}
+
+#[test]
+fn test_user_defined_eq() {
+    // Our type.
+    struct SketchyNum {
+        num : isize
+    }
+
+    // Our implementation of `PartialEq` to support `==` and `!=`.
+    impl PartialEq for SketchyNum {
+        // Our custom eq allows numbers which are near each other to be equal! :D
+        fn eq(&self, other: &SketchyNum) -> bool {
+            (self.num - other.num).abs() < 5
+        }
+    }
+
+    // Now these binary operators will work when applied!
+    assert!(SketchyNum {num: 37} == SketchyNum {num: 34});
+    assert!(SketchyNum {num: 25} != SketchyNum {num: 57});
+}
diff --git a/src/libcore/tests/fmt/builders.rs b/src/libcore/tests/fmt/builders.rs
new file mode 100644
index 00000000000..e71e61bda5e
--- /dev/null
+++ b/src/libcore/tests/fmt/builders.rs
@@ -0,0 +1,498 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod debug_struct {
+    use std::fmt;
+
+    #[test]
+    fn test_empty() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_struct("Foo").finish()
+            }
+        }
+
+        assert_eq!("Foo", format!("{:?}", Foo));
+        assert_eq!("Foo", format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_single() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_struct("Foo")
+                    .field("bar", &true)
+                    .finish()
+            }
+        }
+
+        assert_eq!("Foo { bar: true }", format!("{:?}", Foo));
+        assert_eq!(
+"Foo {
+    bar: true
+}",
+                   format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_multiple() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_struct("Foo")
+                    .field("bar", &true)
+                    .field("baz", &format_args!("{}/{}", 10, 20))
+                    .finish()
+            }
+        }
+
+        assert_eq!("Foo { bar: true, baz: 10/20 }", format!("{:?}", Foo));
+        assert_eq!(
+"Foo {
+    bar: true,
+    baz: 10/20
+}",
+                   format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_nested() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_struct("Foo")
+                    .field("bar", &true)
+                    .field("baz", &format_args!("{}/{}", 10, 20))
+                    .finish()
+            }
+        }
+
+        struct Bar;
+
+        impl fmt::Debug for Bar {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_struct("Bar")
+                    .field("foo", &Foo)
+                    .field("hello", &"world")
+                    .finish()
+            }
+        }
+
+        assert_eq!("Bar { foo: Foo { bar: true, baz: 10/20 }, hello: \"world\" }",
+                   format!("{:?}", Bar));
+        assert_eq!(
+"Bar {
+    foo: Foo {
+        bar: true,
+        baz: 10/20
+    },
+    hello: \"world\"
+}",
+                   format!("{:#?}", Bar));
+    }
+}
+
+mod debug_tuple {
+    use std::fmt;
+
+    #[test]
+    fn test_empty() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_tuple("Foo").finish()
+            }
+        }
+
+        assert_eq!("Foo", format!("{:?}", Foo));
+        assert_eq!("Foo", format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_single() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_tuple("Foo")
+                    .field(&true)
+                    .finish()
+            }
+        }
+
+        assert_eq!("Foo(true)", format!("{:?}", Foo));
+        assert_eq!(
+"Foo(
+    true
+)",
+                   format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_multiple() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_tuple("Foo")
+                    .field(&true)
+                    .field(&format_args!("{}/{}", 10, 20))
+                    .finish()
+            }
+        }
+
+        assert_eq!("Foo(true, 10/20)", format!("{:?}", Foo));
+        assert_eq!(
+"Foo(
+    true,
+    10/20
+)",
+                   format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_nested() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_tuple("Foo")
+                    .field(&true)
+                    .field(&format_args!("{}/{}", 10, 20))
+                    .finish()
+            }
+        }
+
+        struct Bar;
+
+        impl fmt::Debug for Bar {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_tuple("Bar")
+                    .field(&Foo)
+                    .field(&"world")
+                    .finish()
+            }
+        }
+
+        assert_eq!("Bar(Foo(true, 10/20), \"world\")",
+                   format!("{:?}", Bar));
+        assert_eq!(
+"Bar(
+    Foo(
+        true,
+        10/20
+    ),
+    \"world\"
+)",
+                   format!("{:#?}", Bar));
+    }
+}
+
+mod debug_map {
+    use std::fmt;
+
+    #[test]
+    fn test_empty() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_map().finish()
+            }
+        }
+
+        assert_eq!("{}", format!("{:?}", Foo));
+        assert_eq!("{}", format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_single() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_map()
+                    .entry(&"bar", &true)
+                    .finish()
+            }
+        }
+
+        assert_eq!("{\"bar\": true}", format!("{:?}", Foo));
+        assert_eq!(
+"{
+    \"bar\": true
+}",
+                   format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_multiple() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_map()
+                    .entry(&"bar", &true)
+                    .entry(&10, &format_args!("{}/{}", 10, 20))
+                    .finish()
+            }
+        }
+
+        assert_eq!("{\"bar\": true, 10: 10/20}", format!("{:?}", Foo));
+        assert_eq!(
+"{
+    \"bar\": true,
+    10: 10/20
+}",
+                   format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_nested() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_map()
+                    .entry(&"bar", &true)
+                    .entry(&10, &format_args!("{}/{}", 10, 20))
+                    .finish()
+            }
+        }
+
+        struct Bar;
+
+        impl fmt::Debug for Bar {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_map()
+                    .entry(&"foo", &Foo)
+                    .entry(&Foo, &"world")
+                    .finish()
+            }
+        }
+
+        assert_eq!("{\"foo\": {\"bar\": true, 10: 10/20}, \
+                    {\"bar\": true, 10: 10/20}: \"world\"}",
+                   format!("{:?}", Bar));
+        assert_eq!(
+"{
+    \"foo\": {
+        \"bar\": true,
+        10: 10/20
+    },
+    {
+        \"bar\": true,
+        10: 10/20
+    }: \"world\"
+}",
+                   format!("{:#?}", Bar));
+    }
+}
+
+mod debug_set {
+    use std::fmt;
+
+    #[test]
+    fn test_empty() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_set().finish()
+            }
+        }
+
+        assert_eq!("{}", format!("{:?}", Foo));
+        assert_eq!("{}", format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_single() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_set()
+                    .entry(&true)
+                    .finish()
+            }
+        }
+
+        assert_eq!("{true}", format!("{:?}", Foo));
+        assert_eq!(
+"{
+    true
+}",
+                   format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_multiple() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_set()
+                    .entry(&true)
+                    .entry(&format_args!("{}/{}", 10, 20))
+                    .finish()
+            }
+        }
+
+        assert_eq!("{true, 10/20}", format!("{:?}", Foo));
+        assert_eq!(
+"{
+    true,
+    10/20
+}",
+                   format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_nested() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_set()
+                    .entry(&true)
+                    .entry(&format_args!("{}/{}", 10, 20))
+                    .finish()
+            }
+        }
+
+        struct Bar;
+
+        impl fmt::Debug for Bar {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_set()
+                    .entry(&Foo)
+                    .entry(&"world")
+                    .finish()
+            }
+        }
+
+        assert_eq!("{{true, 10/20}, \"world\"}",
+                   format!("{:?}", Bar));
+        assert_eq!(
+"{
+    {
+        true,
+        10/20
+    },
+    \"world\"
+}",
+                   format!("{:#?}", Bar));
+    }
+}
+
+mod debug_list {
+    use std::fmt;
+
+    #[test]
+    fn test_empty() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_list().finish()
+            }
+        }
+
+        assert_eq!("[]", format!("{:?}", Foo));
+        assert_eq!("[]", format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_single() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_list()
+                    .entry(&true)
+                    .finish()
+            }
+        }
+
+        assert_eq!("[true]", format!("{:?}", Foo));
+        assert_eq!(
+"[
+    true
+]",
+                   format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_multiple() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_list()
+                    .entry(&true)
+                    .entry(&format_args!("{}/{}", 10, 20))
+                    .finish()
+            }
+        }
+
+        assert_eq!("[true, 10/20]", format!("{:?}", Foo));
+        assert_eq!(
+"[
+    true,
+    10/20
+]",
+                   format!("{:#?}", Foo));
+    }
+
+    #[test]
+    fn test_nested() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_list()
+                    .entry(&true)
+                    .entry(&format_args!("{}/{}", 10, 20))
+                    .finish()
+            }
+        }
+
+        struct Bar;
+
+        impl fmt::Debug for Bar {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                fmt.debug_list()
+                    .entry(&Foo)
+                    .entry(&"world")
+                    .finish()
+            }
+        }
+
+        assert_eq!("[[true, 10/20], \"world\"]",
+                   format!("{:?}", Bar));
+        assert_eq!(
+"[
+    [
+        true,
+        10/20
+    ],
+    \"world\"
+]",
+                   format!("{:#?}", Bar));
+    }
+}
diff --git a/src/libcore/tests/fmt/float.rs b/src/libcore/tests/fmt/float.rs
new file mode 100644
index 00000000000..695001312e4
--- /dev/null
+++ b/src/libcore/tests/fmt/float.rs
@@ -0,0 +1,37 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[test]
+fn test_format_f64() {
+    assert_eq!("1", format!("{:.0}", 1.0f64));
+    assert_eq!("9", format!("{:.0}", 9.4f64));
+    assert_eq!("10", format!("{:.0}", 9.9f64));
+    assert_eq!("9.8", format!("{:.1}", 9.849f64));
+    assert_eq!("9.9", format!("{:.1}", 9.851f64));
+    assert_eq!("1", format!("{:.0}", 0.5f64));
+    assert_eq!("1.23456789e6", format!("{:e}", 1234567.89f64));
+    assert_eq!("1.23456789e3", format!("{:e}", 1234.56789f64));
+    assert_eq!("1.23456789E6", format!("{:E}", 1234567.89f64));
+    assert_eq!("1.23456789E3", format!("{:E}", 1234.56789f64));
+}
+
+#[test]
+fn test_format_f32() {
+    assert_eq!("1", format!("{:.0}", 1.0f32));
+    assert_eq!("9", format!("{:.0}", 9.4f32));
+    assert_eq!("10", format!("{:.0}", 9.9f32));
+    assert_eq!("9.8", format!("{:.1}", 9.849f32));
+    assert_eq!("9.9", format!("{:.1}", 9.851f32));
+    assert_eq!("1", format!("{:.0}", 0.5f32));
+    assert_eq!("1.2345679e6", format!("{:e}", 1234567.89f32));
+    assert_eq!("1.2345679e3", format!("{:e}", 1234.56789f32));
+    assert_eq!("1.2345679E6", format!("{:E}", 1234567.89f32));
+    assert_eq!("1.2345679E3", format!("{:E}", 1234.56789f32));
+}
diff --git a/src/libcore/tests/fmt/mod.rs b/src/libcore/tests/fmt/mod.rs
new file mode 100644
index 00000000000..5d204c7d523
--- /dev/null
+++ b/src/libcore/tests/fmt/mod.rs
@@ -0,0 +1,40 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod builders;
+mod float;
+mod num;
+
+#[test]
+fn test_format_flags() {
+    // No residual flags left by pointer formatting
+    let p = "".as_ptr();
+    assert_eq!(format!("{:p} {:x}", p, 16), format!("{:p} 10", p));
+
+    assert_eq!(format!("{: >3}", 'a'), "  a");
+}
+
+#[test]
+fn test_pointer_formats_data_pointer() {
+    let b: &[u8] = b"";
+    let s: &str = "";
+    assert_eq!(format!("{:p}", s), format!("{:p}", s.as_ptr()));
+    assert_eq!(format!("{:p}", b), format!("{:p}", b.as_ptr()));
+}
+
+#[test]
+fn test_estimated_capacity() {
+    assert_eq!(format_args!("").estimated_capacity(), 0);
+    assert_eq!(format_args!("{}", "").estimated_capacity(), 0);
+    assert_eq!(format_args!("Hello").estimated_capacity(), 5);
+    assert_eq!(format_args!("Hello, {}!", "").estimated_capacity(), 16);
+    assert_eq!(format_args!("{}, hello!", "World").estimated_capacity(), 0);
+    assert_eq!(format_args!("{}. 16-bytes piece", "World").estimated_capacity(), 32);
+}
diff --git a/src/libcore/tests/fmt/num.rs b/src/libcore/tests/fmt/num.rs
new file mode 100644
index 00000000000..4ddedd91004
--- /dev/null
+++ b/src/libcore/tests/fmt/num.rs
@@ -0,0 +1,152 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[test]
+fn test_format_int() {
+    // Formatting integers should select the right implementation based off
+    // the type of the argument. Also, hex/octal/binary should be defined
+    // for integers, but they shouldn't emit the negative sign.
+    assert!(format!("{}", 1isize) == "1");
+    assert!(format!("{}", 1i8) == "1");
+    assert!(format!("{}", 1i16) == "1");
+    assert!(format!("{}", 1i32) == "1");
+    assert!(format!("{}", 1i64) == "1");
+    assert!(format!("{}", -1isize) == "-1");
+    assert!(format!("{}", -1i8) == "-1");
+    assert!(format!("{}", -1i16) == "-1");
+    assert!(format!("{}", -1i32) == "-1");
+    assert!(format!("{}", -1i64) == "-1");
+    assert!(format!("{:?}", 1isize) == "1");
+    assert!(format!("{:?}", 1i8) == "1");
+    assert!(format!("{:?}", 1i16) == "1");
+    assert!(format!("{:?}", 1i32) == "1");
+    assert!(format!("{:?}", 1i64) == "1");
+    assert!(format!("{:b}", 1isize) == "1");
+    assert!(format!("{:b}", 1i8) == "1");
+    assert!(format!("{:b}", 1i16) == "1");
+    assert!(format!("{:b}", 1i32) == "1");
+    assert!(format!("{:b}", 1i64) == "1");
+    assert!(format!("{:x}", 1isize) == "1");
+    assert!(format!("{:x}", 1i8) == "1");
+    assert!(format!("{:x}", 1i16) == "1");
+    assert!(format!("{:x}", 1i32) == "1");
+    assert!(format!("{:x}", 1i64) == "1");
+    assert!(format!("{:X}", 1isize) == "1");
+    assert!(format!("{:X}", 1i8) == "1");
+    assert!(format!("{:X}", 1i16) == "1");
+    assert!(format!("{:X}", 1i32) == "1");
+    assert!(format!("{:X}", 1i64) == "1");
+    assert!(format!("{:o}", 1isize) == "1");
+    assert!(format!("{:o}", 1i8) == "1");
+    assert!(format!("{:o}", 1i16) == "1");
+    assert!(format!("{:o}", 1i32) == "1");
+    assert!(format!("{:o}", 1i64) == "1");
+
+    assert!(format!("{}", 1usize) == "1");
+    assert!(format!("{}", 1u8) == "1");
+    assert!(format!("{}", 1u16) == "1");
+    assert!(format!("{}", 1u32) == "1");
+    assert!(format!("{}", 1u64) == "1");
+    assert!(format!("{:?}", 1usize) == "1");
+    assert!(format!("{:?}", 1u8) == "1");
+    assert!(format!("{:?}", 1u16) == "1");
+    assert!(format!("{:?}", 1u32) == "1");
+    assert!(format!("{:?}", 1u64) == "1");
+    assert!(format!("{:b}", 1usize) == "1");
+    assert!(format!("{:b}", 1u8) == "1");
+    assert!(format!("{:b}", 1u16) == "1");
+    assert!(format!("{:b}", 1u32) == "1");
+    assert!(format!("{:b}", 1u64) == "1");
+    assert!(format!("{:x}", 1usize) == "1");
+    assert!(format!("{:x}", 1u8) == "1");
+    assert!(format!("{:x}", 1u16) == "1");
+    assert!(format!("{:x}", 1u32) == "1");
+    assert!(format!("{:x}", 1u64) == "1");
+    assert!(format!("{:X}", 1usize) == "1");
+    assert!(format!("{:X}", 1u8) == "1");
+    assert!(format!("{:X}", 1u16) == "1");
+    assert!(format!("{:X}", 1u32) == "1");
+    assert!(format!("{:X}", 1u64) == "1");
+    assert!(format!("{:o}", 1usize) == "1");
+    assert!(format!("{:o}", 1u8) == "1");
+    assert!(format!("{:o}", 1u16) == "1");
+    assert!(format!("{:o}", 1u32) == "1");
+    assert!(format!("{:o}", 1u64) == "1");
+
+    // Test a larger number
+    assert!(format!("{:b}", 55) == "110111");
+    assert!(format!("{:o}", 55) == "67");
+    assert!(format!("{}", 55) == "55");
+    assert!(format!("{:x}", 55) == "37");
+    assert!(format!("{:X}", 55) == "37");
+}
+
+#[test]
+fn test_format_int_zero() {
+    assert!(format!("{}", 0) == "0");
+    assert!(format!("{:?}", 0) == "0");
+    assert!(format!("{:b}", 0) == "0");
+    assert!(format!("{:o}", 0) == "0");
+    assert!(format!("{:x}", 0) == "0");
+    assert!(format!("{:X}", 0) == "0");
+
+    assert!(format!("{}", 0u32) == "0");
+    assert!(format!("{:?}", 0u32) == "0");
+    assert!(format!("{:b}", 0u32) == "0");
+    assert!(format!("{:o}", 0u32) == "0");
+    assert!(format!("{:x}", 0u32) == "0");
+    assert!(format!("{:X}", 0u32) == "0");
+}
+
+#[test]
+fn test_format_int_flags() {
+    assert!(format!("{:3}", 1) == "  1");
+    assert!(format!("{:>3}", 1) == "  1");
+    assert!(format!("{:>+3}", 1) == " +1");
+    assert!(format!("{:<3}", 1) == "1  ");
+    assert!(format!("{:#}", 1) == "1");
+    assert!(format!("{:#x}", 10) == "0xa");
+    assert!(format!("{:#X}", 10) == "0xA");
+    assert!(format!("{:#5x}", 10) == "  0xa");
+    assert!(format!("{:#o}", 10) == "0o12");
+    assert!(format!("{:08x}", 10) == "0000000a");
+    assert!(format!("{:8x}", 10) == "       a");
+    assert!(format!("{:<8x}", 10) == "a       ");
+    assert!(format!("{:>8x}", 10) == "       a");
+    assert!(format!("{:#08x}", 10) == "0x00000a");
+    assert!(format!("{:08}", -10) == "-0000010");
+    assert!(format!("{:x}", !0u8) == "ff");
+    assert!(format!("{:X}", !0u8) == "FF");
+    assert!(format!("{:b}", !0u8) == "11111111");
+    assert!(format!("{:o}", !0u8) == "377");
+    assert!(format!("{:#x}", !0u8) == "0xff");
+    assert!(format!("{:#X}", !0u8) == "0xFF");
+    assert!(format!("{:#b}", !0u8) == "0b11111111");
+    assert!(format!("{:#o}", !0u8) == "0o377");
+}
+
+#[test]
+fn test_format_int_sign_padding() {
+    assert!(format!("{:+5}", 1) == "   +1");
+    assert!(format!("{:+5}", -1) == "   -1");
+    assert!(format!("{:05}", 1) == "00001");
+    assert!(format!("{:05}", -1) == "-0001");
+    assert!(format!("{:+05}", 1) == "+0001");
+    assert!(format!("{:+05}", -1) == "-0001");
+}
+
+#[test]
+fn test_format_int_twos_complement() {
+    use core::{i8, i16, i32, i64};
+    assert!(format!("{}", i8::MIN) == "-128");
+    assert!(format!("{}", i16::MIN) == "-32768");
+    assert!(format!("{}", i32::MIN) == "-2147483648");
+    assert!(format!("{}", i64::MIN) == "-9223372036854775808");
+}
diff --git a/src/libcore/tests/hash/mod.rs b/src/libcore/tests/hash/mod.rs
new file mode 100644
index 00000000000..53ac17c052f
--- /dev/null
+++ b/src/libcore/tests/hash/mod.rs
@@ -0,0 +1,111 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod sip;
+
+use std::hash::{Hash, Hasher};
+use std::default::Default;
+
+struct MyHasher {
+    hash: u64,
+}
+
+impl Default for MyHasher {
+    fn default() -> MyHasher {
+        MyHasher { hash: 0 }
+    }
+}
+
+impl Hasher for MyHasher {
+    fn write(&mut self, buf: &[u8]) {
+        for byte in buf {
+            self.hash += *byte as u64;
+        }
+    }
+    fn finish(&self) -> u64 { self.hash }
+}
+
+
+#[test]
+fn test_writer_hasher() {
+    fn hash<T: Hash>(t: &T) -> u64 {
+        let mut s = MyHasher { hash: 0 };
+        t.hash(&mut s);
+        s.finish()
+    }
+
+    assert_eq!(hash(&()), 0);
+
+    assert_eq!(hash(&5_u8), 5);
+    assert_eq!(hash(&5_u16), 5);
+    assert_eq!(hash(&5_u32), 5);
+    assert_eq!(hash(&5_u64), 5);
+    assert_eq!(hash(&5_usize), 5);
+
+    assert_eq!(hash(&5_i8), 5);
+    assert_eq!(hash(&5_i16), 5);
+    assert_eq!(hash(&5_i32), 5);
+    assert_eq!(hash(&5_i64), 5);
+    assert_eq!(hash(&5_isize), 5);
+
+    assert_eq!(hash(&false), 0);
+    assert_eq!(hash(&true), 1);
+
+    assert_eq!(hash(&'a'), 97);
+
+    let s: &str = "a";
+    assert_eq!(hash(& s), 97 + 0xFF);
+    let s: Box<str> = String::from("a").into_boxed_str();
+    assert_eq!(hash(& s), 97 + 0xFF);
+    let cs: &[u8] = &[1, 2, 3];
+    assert_eq!(hash(& cs), 9);
+    let cs: Box<[u8]> = Box::new([1, 2, 3]);
+    assert_eq!(hash(& cs), 9);
+
+    // FIXME (#18248) Add tests for hashing Rc<str> and Rc<[T]>
+
+    let ptr = 5_usize as *const i32;
+    assert_eq!(hash(&ptr), 5);
+
+    let ptr = 5_usize as *mut i32;
+    assert_eq!(hash(&ptr), 5);
+}
+
+struct Custom { hash: u64 }
+struct CustomHasher { output: u64 }
+
+impl Hasher for CustomHasher {
+    fn finish(&self) -> u64 { self.output }
+    fn write(&mut self, _: &[u8]) { panic!() }
+    fn write_u64(&mut self, data: u64) { self.output = data; }
+}
+
+impl Default for CustomHasher {
+    fn default() -> CustomHasher {
+        CustomHasher { output: 0 }
+    }
+}
+
+impl Hash for Custom {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        state.write_u64(self.hash);
+    }
+}
+
+#[test]
+fn test_custom_state() {
+    fn hash<T: Hash>(t: &T) -> u64 {
+        let mut c = CustomHasher { output: 0 };
+        t.hash(&mut c);
+        c.finish()
+    }
+
+    assert_eq!(hash(&Custom { hash: 5 }), 5);
+}
diff --git a/src/libcore/tests/hash/sip.rs b/src/libcore/tests/hash/sip.rs
new file mode 100644
index 00000000000..4a9657e0340
--- /dev/null
+++ b/src/libcore/tests/hash/sip.rs
@@ -0,0 +1,342 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(deprecated)]
+
+use core::hash::{Hash, Hasher};
+use core::hash::{SipHasher, SipHasher13, SipHasher24};
+use core::{slice, mem};
+
+// Hash just the bytes of the slice, without length prefix
+struct Bytes<'a>(&'a [u8]);
+
+impl<'a> Hash for Bytes<'a> {
+    #[allow(unused_must_use)]
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let Bytes(v) = *self;
+        state.write(v);
+    }
+}
+
+macro_rules! u8to64_le {
+    ($buf:expr, $i:expr) =>
+    ($buf[0+$i] as u64 |
+     ($buf[1+$i] as u64) << 8 |
+     ($buf[2+$i] as u64) << 16 |
+     ($buf[3+$i] as u64) << 24 |
+     ($buf[4+$i] as u64) << 32 |
+     ($buf[5+$i] as u64) << 40 |
+     ($buf[6+$i] as u64) << 48 |
+     ($buf[7+$i] as u64) << 56);
+    ($buf:expr, $i:expr, $len:expr) =>
+    ({
+        let mut t = 0;
+        let mut out = 0;
+        while t < $len {
+            out |= ($buf[t+$i] as u64) << t*8;
+            t += 1;
+        }
+        out
+    });
+}
+
+fn hash_with<H: Hasher, T: Hash>(mut st: H, x: &T) -> u64 {
+    x.hash(&mut st);
+    st.finish()
+}
+
+fn hash<T: Hash>(x: &T) -> u64 {
+    hash_with(SipHasher::new(), x)
+}
+
+#[test]
+#[allow(unused_must_use)]
+fn test_siphash_1_3() {
+    let vecs : [[u8; 8]; 64] = [
+        [ 0xdc, 0xc4, 0x0f, 0x05, 0x58, 0x01, 0xac, 0xab ],
+        [ 0x93, 0xca, 0x57, 0x7d, 0xf3, 0x9b, 0xf4, 0xc9 ],
+        [ 0x4d, 0xd4, 0xc7, 0x4d, 0x02, 0x9b, 0xcb, 0x82 ],
+        [ 0xfb, 0xf7, 0xdd, 0xe7, 0xb8, 0x0a, 0xf8, 0x8b ],
+        [ 0x28, 0x83, 0xd3, 0x88, 0x60, 0x57, 0x75, 0xcf ],
+        [ 0x67, 0x3b, 0x53, 0x49, 0x2f, 0xd5, 0xf9, 0xde ],
+        [ 0xa7, 0x22, 0x9f, 0xc5, 0x50, 0x2b, 0x0d, 0xc5 ],
+        [ 0x40, 0x11, 0xb1, 0x9b, 0x98, 0x7d, 0x92, 0xd3 ],
+        [ 0x8e, 0x9a, 0x29, 0x8d, 0x11, 0x95, 0x90, 0x36 ],
+        [ 0xe4, 0x3d, 0x06, 0x6c, 0xb3, 0x8e, 0xa4, 0x25 ],
+        [ 0x7f, 0x09, 0xff, 0x92, 0xee, 0x85, 0xde, 0x79 ],
+        [ 0x52, 0xc3, 0x4d, 0xf9, 0xc1, 0x18, 0xc1, 0x70 ],
+        [ 0xa2, 0xd9, 0xb4, 0x57, 0xb1, 0x84, 0xa3, 0x78 ],
+        [ 0xa7, 0xff, 0x29, 0x12, 0x0c, 0x76, 0x6f, 0x30 ],
+        [ 0x34, 0x5d, 0xf9, 0xc0, 0x11, 0xa1, 0x5a, 0x60 ],
+        [ 0x56, 0x99, 0x51, 0x2a, 0x6d, 0xd8, 0x20, 0xd3 ],
+        [ 0x66, 0x8b, 0x90, 0x7d, 0x1a, 0xdd, 0x4f, 0xcc ],
+        [ 0x0c, 0xd8, 0xdb, 0x63, 0x90, 0x68, 0xf2, 0x9c ],
+        [ 0x3e, 0xe6, 0x73, 0xb4, 0x9c, 0x38, 0xfc, 0x8f ],
+        [ 0x1c, 0x7d, 0x29, 0x8d, 0xe5, 0x9d, 0x1f, 0xf2 ],
+        [ 0x40, 0xe0, 0xcc, 0xa6, 0x46, 0x2f, 0xdc, 0xc0 ],
+        [ 0x44, 0xf8, 0x45, 0x2b, 0xfe, 0xab, 0x92, 0xb9 ],
+        [ 0x2e, 0x87, 0x20, 0xa3, 0x9b, 0x7b, 0xfe, 0x7f ],
+        [ 0x23, 0xc1, 0xe6, 0xda, 0x7f, 0x0e, 0x5a, 0x52 ],
+        [ 0x8c, 0x9c, 0x34, 0x67, 0xb2, 0xae, 0x64, 0xf4 ],
+        [ 0x79, 0x09, 0x5b, 0x70, 0x28, 0x59, 0xcd, 0x45 ],
+        [ 0xa5, 0x13, 0x99, 0xca, 0xe3, 0x35, 0x3e, 0x3a ],
+        [ 0x35, 0x3b, 0xde, 0x4a, 0x4e, 0xc7, 0x1d, 0xa9 ],
+        [ 0x0d, 0xd0, 0x6c, 0xef, 0x02, 0xed, 0x0b, 0xfb ],
+        [ 0xf4, 0xe1, 0xb1, 0x4a, 0xb4, 0x3c, 0xd9, 0x88 ],
+        [ 0x63, 0xe6, 0xc5, 0x43, 0xd6, 0x11, 0x0f, 0x54 ],
+        [ 0xbc, 0xd1, 0x21, 0x8c, 0x1f, 0xdd, 0x70, 0x23 ],
+        [ 0x0d, 0xb6, 0xa7, 0x16, 0x6c, 0x7b, 0x15, 0x81 ],
+        [ 0xbf, 0xf9, 0x8f, 0x7a, 0xe5, 0xb9, 0x54, 0x4d ],
+        [ 0x3e, 0x75, 0x2a, 0x1f, 0x78, 0x12, 0x9f, 0x75 ],
+        [ 0x91, 0x6b, 0x18, 0xbf, 0xbe, 0xa3, 0xa1, 0xce ],
+        [ 0x06, 0x62, 0xa2, 0xad, 0xd3, 0x08, 0xf5, 0x2c ],
+        [ 0x57, 0x30, 0xc3, 0xa3, 0x2d, 0x1c, 0x10, 0xb6 ],
+        [ 0xa1, 0x36, 0x3a, 0xae, 0x96, 0x74, 0xf4, 0xb3 ],
+        [ 0x92, 0x83, 0x10, 0x7b, 0x54, 0x57, 0x6b, 0x62 ],
+        [ 0x31, 0x15, 0xe4, 0x99, 0x32, 0x36, 0xd2, 0xc1 ],
+        [ 0x44, 0xd9, 0x1a, 0x3f, 0x92, 0xc1, 0x7c, 0x66 ],
+        [ 0x25, 0x88, 0x13, 0xc8, 0xfe, 0x4f, 0x70, 0x65 ],
+        [ 0xa6, 0x49, 0x89, 0xc2, 0xd1, 0x80, 0xf2, 0x24 ],
+        [ 0x6b, 0x87, 0xf8, 0xfa, 0xed, 0x1c, 0xca, 0xc2 ],
+        [ 0x96, 0x21, 0x04, 0x9f, 0xfc, 0x4b, 0x16, 0xc2 ],
+        [ 0x23, 0xd6, 0xb1, 0x68, 0x93, 0x9c, 0x6e, 0xa1 ],
+        [ 0xfd, 0x14, 0x51, 0x8b, 0x9c, 0x16, 0xfb, 0x49 ],
+        [ 0x46, 0x4c, 0x07, 0xdf, 0xf8, 0x43, 0x31, 0x9f ],
+        [ 0xb3, 0x86, 0xcc, 0x12, 0x24, 0xaf, 0xfd, 0xc6 ],
+        [ 0x8f, 0x09, 0x52, 0x0a, 0xd1, 0x49, 0xaf, 0x7e ],
+        [ 0x9a, 0x2f, 0x29, 0x9d, 0x55, 0x13, 0xf3, 0x1c ],
+        [ 0x12, 0x1f, 0xf4, 0xa2, 0xdd, 0x30, 0x4a, 0xc4 ],
+        [ 0xd0, 0x1e, 0xa7, 0x43, 0x89, 0xe9, 0xfa, 0x36 ],
+        [ 0xe6, 0xbc, 0xf0, 0x73, 0x4c, 0xb3, 0x8f, 0x31 ],
+        [ 0x80, 0xe9, 0xa7, 0x70, 0x36, 0xbf, 0x7a, 0xa2 ],
+        [ 0x75, 0x6d, 0x3c, 0x24, 0xdb, 0xc0, 0xbc, 0xb4 ],
+        [ 0x13, 0x15, 0xb7, 0xfd, 0x52, 0xd8, 0xf8, 0x23 ],
+        [ 0x08, 0x8a, 0x7d, 0xa6, 0x4d, 0x5f, 0x03, 0x8f ],
+        [ 0x48, 0xf1, 0xe8, 0xb7, 0xe5, 0xd0, 0x9c, 0xd8 ],
+        [ 0xee, 0x44, 0xa6, 0xf7, 0xbc, 0xe6, 0xf4, 0xf6 ],
+        [ 0xf2, 0x37, 0x18, 0x0f, 0xd8, 0x9a, 0xc5, 0xae ],
+        [ 0xe0, 0x94, 0x66, 0x4b, 0x15, 0xf6, 0xb2, 0xc3 ],
+        [ 0xa8, 0xb3, 0xbb, 0xb7, 0x62, 0x90, 0x19, 0x9d ]
+    ];
+
+    let k0 = 0x_07_06_05_04_03_02_01_00;
+    let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08;
+    let mut buf = Vec::new();
+    let mut t = 0;
+    let mut state_inc = SipHasher13::new_with_keys(k0, k1);
+
+    while t < 64 {
+        let vec = u8to64_le!(vecs[t], 0);
+        let out = hash_with(SipHasher13::new_with_keys(k0, k1), &Bytes(&buf));
+        assert_eq!(vec, out);
+
+        let full = hash_with(SipHasher13::new_with_keys(k0, k1), &Bytes(&buf));
+        let i = state_inc.finish();
+
+        assert_eq!(full, i);
+        assert_eq!(full, vec);
+
+        buf.push(t as u8);
+        Hasher::write(&mut state_inc, &[t as u8]);
+
+        t += 1;
+    }
+}
+
+#[test]
+#[allow(unused_must_use)]
+fn test_siphash_2_4() {
+    let vecs : [[u8; 8]; 64] = [
+        [ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, ],
+        [ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, ],
+        [ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, ],
+        [ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, ],
+        [ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, ],
+        [ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, ],
+        [ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, ],
+        [ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, ],
+        [ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, ],
+        [ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, ],
+        [ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, ],
+        [ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, ],
+        [ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, ],
+        [ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, ],
+        [ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, ],
+        [ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, ],
+        [ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, ],
+        [ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, ],
+        [ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, ],
+        [ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, ],
+        [ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, ],
+        [ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, ],
+        [ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, ],
+        [ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, ],
+        [ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, ],
+        [ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, ],
+        [ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, ],
+        [ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, ],
+        [ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, ],
+        [ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, ],
+        [ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, ],
+        [ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, ],
+        [ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, ],
+        [ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, ],
+        [ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, ],
+        [ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, ],
+        [ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, ],
+        [ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, ],
+        [ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, ],
+        [ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, ],
+        [ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, ],
+        [ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, ],
+        [ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, ],
+        [ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, ],
+        [ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, ],
+        [ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, ],
+        [ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, ],
+        [ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, ],
+        [ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, ],
+        [ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, ],
+        [ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, ],
+        [ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, ],
+        [ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, ],
+        [ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, ],
+        [ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, ],
+        [ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, ],
+        [ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, ],
+        [ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, ],
+        [ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, ],
+        [ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, ],
+        [ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, ],
+        [ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, ],
+        [ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, ],
+        [ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, ]
+    ];
+
+    let k0 = 0x_07_06_05_04_03_02_01_00;
+    let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08;
+    let mut buf = Vec::new();
+    let mut t = 0;
+    let mut state_inc = SipHasher24::new_with_keys(k0, k1);
+
+    while t < 64 {
+        let vec = u8to64_le!(vecs[t], 0);
+        let out = hash_with(SipHasher24::new_with_keys(k0, k1), &Bytes(&buf));
+        assert_eq!(vec, out);
+
+        let full = hash_with(SipHasher24::new_with_keys(k0, k1), &Bytes(&buf));
+        let i = state_inc.finish();
+
+        assert_eq!(full, i);
+        assert_eq!(full, vec);
+
+        buf.push(t as u8);
+        Hasher::write(&mut state_inc, &[t as u8]);
+
+        t += 1;
+    }
+}
+#[test] #[cfg(target_arch = "arm")]
+fn test_hash_usize() {
+    let val = 0xdeadbeef_deadbeef_u64;
+    assert!(hash(&(val as u64)) != hash(&(val as usize)));
+    assert_eq!(hash(&(val as u32)), hash(&(val as usize)));
+}
+#[test] #[cfg(target_arch = "x86_64")]
+fn test_hash_usize() {
+    let val = 0xdeadbeef_deadbeef_u64;
+    assert_eq!(hash(&(val as u64)), hash(&(val as usize)));
+    assert!(hash(&(val as u32)) != hash(&(val as usize)));
+}
+#[test] #[cfg(target_arch = "x86")]
+fn test_hash_usize() {
+    let val = 0xdeadbeef_deadbeef_u64;
+    assert!(hash(&(val as u64)) != hash(&(val as usize)));
+    assert_eq!(hash(&(val as u32)), hash(&(val as usize)));
+}
+
+#[test]
+fn test_hash_idempotent() {
+    let val64 = 0xdeadbeef_deadbeef_u64;
+    assert_eq!(hash(&val64), hash(&val64));
+    let val32 = 0xdeadbeef_u32;
+    assert_eq!(hash(&val32), hash(&val32));
+}
+
+#[test]
+fn test_hash_no_bytes_dropped_64() {
+    let val = 0xdeadbeef_deadbeef_u64;
+
+    assert!(hash(&val) != hash(&zero_byte(val, 0)));
+    assert!(hash(&val) != hash(&zero_byte(val, 1)));
+    assert!(hash(&val) != hash(&zero_byte(val, 2)));
+    assert!(hash(&val) != hash(&zero_byte(val, 3)));
+    assert!(hash(&val) != hash(&zero_byte(val, 4)));
+    assert!(hash(&val) != hash(&zero_byte(val, 5)));
+    assert!(hash(&val) != hash(&zero_byte(val, 6)));
+    assert!(hash(&val) != hash(&zero_byte(val, 7)));
+
+    fn zero_byte(val: u64, byte: usize) -> u64 {
+        assert!(byte < 8);
+        val & !(0xff << (byte * 8))
+    }
+}
+
+#[test]
+fn test_hash_no_bytes_dropped_32() {
+    let val = 0xdeadbeef_u32;
+
+    assert!(hash(&val) != hash(&zero_byte(val, 0)));
+    assert!(hash(&val) != hash(&zero_byte(val, 1)));
+    assert!(hash(&val) != hash(&zero_byte(val, 2)));
+    assert!(hash(&val) != hash(&zero_byte(val, 3)));
+
+    fn zero_byte(val: u32, byte: usize) -> u32 {
+        assert!(byte < 4);
+        val & !(0xff << (byte * 8))
+    }
+}
+
+#[test]
+fn test_hash_no_concat_alias() {
+    let s = ("aa", "bb");
+    let t = ("aabb", "");
+    let u = ("a", "abb");
+
+    assert!(s != t && t != u);
+    assert!(hash(&s) != hash(&t) && hash(&s) != hash(&u));
+
+    let u = [1, 0, 0, 0];
+    let v = (&u[..1], &u[1..3], &u[3..]);
+    let w = (&u[..], &u[4..4], &u[4..4]);
+
+    assert!(v != w);
+    assert!(hash(&v) != hash(&w));
+}
+
+#[test]
+fn test_write_short_works() {
+    let test_usize = 0xd0c0b0a0usize;
+    let mut h1 = SipHasher24::new();
+    h1.write_usize(test_usize);
+    h1.write(b"bytes");
+    h1.write(b"string");
+    h1.write_u8(0xFFu8);
+    h1.write_u8(0x01u8);
+    let mut h2 = SipHasher24::new();
+    h2.write(unsafe {
+        slice::from_raw_parts(&test_usize as *const _ as *const u8,
+                              mem::size_of::<usize>())
+    });
+    h2.write(b"bytes");
+    h2.write(b"string");
+    h2.write(&[0xFFu8, 0x01u8]);
+    assert_eq!(h1.finish(), h2.finish());
+}
diff --git a/src/libcore/tests/intrinsics.rs b/src/libcore/tests/intrinsics.rs
new file mode 100644
index 00000000000..2b380abf63c
--- /dev/null
+++ b/src/libcore/tests/intrinsics.rs
@@ -0,0 +1,30 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::any::TypeId;
+
+#[test]
+fn test_typeid_sized_types() {
+    struct X; struct Y(u32);
+
+    assert_eq!(TypeId::of::<X>(), TypeId::of::<X>());
+    assert_eq!(TypeId::of::<Y>(), TypeId::of::<Y>());
+    assert!(TypeId::of::<X>() != TypeId::of::<Y>());
+}
+
+#[test]
+fn test_typeid_unsized_types() {
+    trait Z {}
+    struct X(str); struct Y(Z + 'static);
+
+    assert_eq!(TypeId::of::<X>(), TypeId::of::<X>());
+    assert_eq!(TypeId::of::<Y>(), TypeId::of::<Y>());
+    assert!(TypeId::of::<X>() != TypeId::of::<Y>());
+}
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
new file mode 100644
index 00000000000..08442f9bcbf
--- /dev/null
+++ b/src/libcore/tests/iter.rs
@@ -0,0 +1,1084 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::iter::*;
+use core::{i8, i16, isize};
+use core::usize;
+
+#[test]
+fn test_lt() {
+    let empty: [isize; 0] = [];
+    let xs = [1,2,3];
+    let ys = [1,2,0];
+
+    assert!(!xs.iter().lt(ys.iter()));
+    assert!(!xs.iter().le(ys.iter()));
+    assert!( xs.iter().gt(ys.iter()));
+    assert!( xs.iter().ge(ys.iter()));
+
+    assert!( ys.iter().lt(xs.iter()));
+    assert!( ys.iter().le(xs.iter()));
+    assert!(!ys.iter().gt(xs.iter()));
+    assert!(!ys.iter().ge(xs.iter()));
+
+    assert!( empty.iter().lt(xs.iter()));
+    assert!( empty.iter().le(xs.iter()));
+    assert!(!empty.iter().gt(xs.iter()));
+    assert!(!empty.iter().ge(xs.iter()));
+
+    // Sequence with NaN
+    let u = [1.0f64, 2.0];
+    let v = [0.0f64/0.0, 3.0];
+
+    assert!(!u.iter().lt(v.iter()));
+    assert!(!u.iter().le(v.iter()));
+    assert!(!u.iter().gt(v.iter()));
+    assert!(!u.iter().ge(v.iter()));
+
+    let a = [0.0f64/0.0];
+    let b = [1.0f64];
+    let c = [2.0f64];
+
+    assert!(a.iter().lt(b.iter()) == (a[0] <  b[0]));
+    assert!(a.iter().le(b.iter()) == (a[0] <= b[0]));
+    assert!(a.iter().gt(b.iter()) == (a[0] >  b[0]));
+    assert!(a.iter().ge(b.iter()) == (a[0] >= b[0]));
+
+    assert!(c.iter().lt(b.iter()) == (c[0] <  b[0]));
+    assert!(c.iter().le(b.iter()) == (c[0] <= b[0]));
+    assert!(c.iter().gt(b.iter()) == (c[0] >  b[0]));
+    assert!(c.iter().ge(b.iter()) == (c[0] >= b[0]));
+}
+
+#[test]
+fn test_multi_iter() {
+    let xs = [1,2,3,4];
+    let ys = [4,3,2,1];
+    assert!(xs.iter().eq(ys.iter().rev()));
+    assert!(xs.iter().lt(xs.iter().skip(2)));
+}
+
+#[test]
+fn test_counter_from_iter() {
+    let it = (0..).step_by(5).take(10);
+    let xs: Vec<isize> = FromIterator::from_iter(it);
+    assert_eq!(xs, [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
+}
+
+#[test]
+fn test_iterator_chain() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let ys = [30, 40, 50, 60];
+    let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
+    let it = xs.iter().chain(&ys);
+    let mut i = 0;
+    for &x in it {
+        assert_eq!(x, expected[i]);
+        i += 1;
+    }
+    assert_eq!(i, expected.len());
+
+    let ys = (30..).step_by(10).take(4);
+    let it = xs.iter().cloned().chain(ys);
+    let mut i = 0;
+    for x in it {
+        assert_eq!(x, expected[i]);
+        i += 1;
+    }
+    assert_eq!(i, expected.len());
+}
+
+#[test]
+fn test_iterator_chain_nth() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let ys = [30, 40, 50, 60];
+    let zs = [];
+    let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
+    for (i, x) in expected.iter().enumerate() {
+        assert_eq!(Some(x), xs.iter().chain(&ys).nth(i));
+    }
+    assert_eq!(zs.iter().chain(&xs).nth(0), Some(&0));
+
+    let mut it = xs.iter().chain(&zs);
+    assert_eq!(it.nth(5), Some(&5));
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_iterator_chain_last() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let ys = [30, 40, 50, 60];
+    let zs = [];
+    assert_eq!(xs.iter().chain(&ys).last(), Some(&60));
+    assert_eq!(zs.iter().chain(&ys).last(), Some(&60));
+    assert_eq!(ys.iter().chain(&zs).last(), Some(&60));
+    assert_eq!(zs.iter().chain(&zs).last(), None);
+}
+
+#[test]
+fn test_iterator_chain_count() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let ys = [30, 40, 50, 60];
+    let zs = [];
+    assert_eq!(xs.iter().chain(&ys).count(), 10);
+    assert_eq!(zs.iter().chain(&ys).count(), 4);
+}
+
+#[test]
+fn test_iterator_chain_find() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let ys = [30, 40, 50, 60];
+    let mut iter = xs.iter().chain(&ys);
+    assert_eq!(iter.find(|&&i| i == 4), Some(&4));
+    assert_eq!(iter.next(), Some(&5));
+    assert_eq!(iter.find(|&&i| i == 40), Some(&40));
+    assert_eq!(iter.next(), Some(&50));
+    assert_eq!(iter.find(|&&i| i == 100), None);
+    assert_eq!(iter.next(), None);
+}
+
+#[test]
+fn test_filter_map() {
+    let it = (0..).step_by(1).take(10)
+        .filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None });
+    assert_eq!(it.collect::<Vec<usize>>(), [0*0, 2*2, 4*4, 6*6, 8*8]);
+}
+
+#[test]
+fn test_iterator_enumerate() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let it = xs.iter().enumerate();
+    for (i, &x) in it {
+        assert_eq!(i, x);
+    }
+}
+
+#[test]
+fn test_iterator_enumerate_nth() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    for (i, &x) in xs.iter().enumerate() {
+        assert_eq!(i, x);
+    }
+
+    let mut it = xs.iter().enumerate();
+    while let Some((i, &x)) = it.nth(0) {
+        assert_eq!(i, x);
+    }
+
+    let mut it = xs.iter().enumerate();
+    while let Some((i, &x)) = it.nth(1) {
+        assert_eq!(i, x);
+    }
+
+    let (i, &x) = xs.iter().enumerate().nth(3).unwrap();
+    assert_eq!(i, x);
+    assert_eq!(i, 3);
+}
+
+#[test]
+fn test_iterator_enumerate_count() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    assert_eq!(xs.iter().count(), 6);
+}
+
+#[test]
+fn test_iterator_filter_count() {
+    let xs = [0, 1, 2, 3, 4, 5, 6, 7, 8];
+    assert_eq!(xs.iter().filter(|&&x| x % 2 == 0).count(), 5);
+}
+
+#[test]
+fn test_iterator_peekable() {
+    let xs = vec![0, 1, 2, 3, 4, 5];
+    let mut it = xs.iter().cloned().peekable();
+
+    assert_eq!(it.len(), 6);
+    assert_eq!(it.peek().unwrap(), &0);
+    assert_eq!(it.len(), 6);
+    assert_eq!(it.next().unwrap(), 0);
+    assert_eq!(it.len(), 5);
+    assert_eq!(it.next().unwrap(), 1);
+    assert_eq!(it.len(), 4);
+    assert_eq!(it.next().unwrap(), 2);
+    assert_eq!(it.len(), 3);
+    assert_eq!(it.peek().unwrap(), &3);
+    assert_eq!(it.len(), 3);
+    assert_eq!(it.peek().unwrap(), &3);
+    assert_eq!(it.len(), 3);
+    assert_eq!(it.next().unwrap(), 3);
+    assert_eq!(it.len(), 2);
+    assert_eq!(it.next().unwrap(), 4);
+    assert_eq!(it.len(), 1);
+    assert_eq!(it.peek().unwrap(), &5);
+    assert_eq!(it.len(), 1);
+    assert_eq!(it.next().unwrap(), 5);
+    assert_eq!(it.len(), 0);
+    assert!(it.peek().is_none());
+    assert_eq!(it.len(), 0);
+    assert!(it.next().is_none());
+    assert_eq!(it.len(), 0);
+}
+
+#[test]
+fn test_iterator_peekable_count() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let ys = [10];
+    let zs: [i32; 0] = [];
+
+    assert_eq!(xs.iter().peekable().count(), 6);
+
+    let mut it = xs.iter().peekable();
+    assert_eq!(it.peek(), Some(&&0));
+    assert_eq!(it.count(), 6);
+
+    assert_eq!(ys.iter().peekable().count(), 1);
+
+    let mut it = ys.iter().peekable();
+    assert_eq!(it.peek(), Some(&&10));
+    assert_eq!(it.count(), 1);
+
+    assert_eq!(zs.iter().peekable().count(), 0);
+
+    let mut it = zs.iter().peekable();
+    assert_eq!(it.peek(), None);
+
+}
+
+#[test]
+fn test_iterator_peekable_nth() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let mut it = xs.iter().peekable();
+
+    assert_eq!(it.peek(), Some(&&0));
+    assert_eq!(it.nth(0), Some(&0));
+    assert_eq!(it.peek(), Some(&&1));
+    assert_eq!(it.nth(1), Some(&2));
+    assert_eq!(it.peek(), Some(&&3));
+    assert_eq!(it.nth(2), Some(&5));
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_iterator_peekable_last() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let ys = [0];
+
+    let mut it = xs.iter().peekable();
+    assert_eq!(it.peek(), Some(&&0));
+    assert_eq!(it.last(), Some(&5));
+
+    let mut it = ys.iter().peekable();
+    assert_eq!(it.peek(), Some(&&0));
+    assert_eq!(it.last(), Some(&0));
+
+    let mut it = ys.iter().peekable();
+    assert_eq!(it.next(), Some(&0));
+    assert_eq!(it.peek(), None);
+    assert_eq!(it.last(), None);
+}
+
+/// This is an iterator that follows the Iterator contract,
+/// but it is not fused. After having returned None once, it will start
+/// producing elements if .next() is called again.
+pub struct CycleIter<'a, T: 'a> {
+    index: usize,
+    data: &'a [T],
+}
+
+pub fn cycle<T>(data: &[T]) -> CycleIter<T> {
+    CycleIter {
+        index: 0,
+        data: data,
+    }
+}
+
+impl<'a, T> Iterator for CycleIter<'a, T> {
+    type Item = &'a T;
+    fn next(&mut self) -> Option<Self::Item> {
+        let elt = self.data.get(self.index);
+        self.index += 1;
+        self.index %= 1 + self.data.len();
+        elt
+    }
+}
+
+#[test]
+fn test_iterator_peekable_remember_peek_none_1() {
+    // Check that the loop using .peek() terminates
+    let data = [1, 2, 3];
+    let mut iter = cycle(&data).peekable();
+
+    let mut n = 0;
+    while let Some(_) = iter.next() {
+        let is_the_last = iter.peek().is_none();
+        assert_eq!(is_the_last, n == data.len() - 1);
+        n += 1;
+        if n > data.len() { break; }
+    }
+    assert_eq!(n, data.len());
+}
+
+#[test]
+fn test_iterator_peekable_remember_peek_none_2() {
+    let data = [0];
+    let mut iter = cycle(&data).peekable();
+    iter.next();
+    assert_eq!(iter.peek(), None);
+    assert_eq!(iter.last(), None);
+}
+
+#[test]
+fn test_iterator_peekable_remember_peek_none_3() {
+    let data = [0];
+    let mut iter = cycle(&data).peekable();
+    iter.peek();
+    assert_eq!(iter.nth(0), Some(&0));
+
+    let mut iter = cycle(&data).peekable();
+    iter.next();
+    assert_eq!(iter.peek(), None);
+    assert_eq!(iter.nth(0), None);
+}
+
+#[test]
+fn test_iterator_take_while() {
+    let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19];
+    let ys = [0, 1, 2, 3, 5, 13];
+    let it = xs.iter().take_while(|&x| *x < 15);
+    let mut i = 0;
+    for x in it {
+        assert_eq!(*x, ys[i]);
+        i += 1;
+    }
+    assert_eq!(i, ys.len());
+}
+
+#[test]
+fn test_iterator_skip_while() {
+    let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19];
+    let ys = [15, 16, 17, 19];
+    let it = xs.iter().skip_while(|&x| *x < 15);
+    let mut i = 0;
+    for x in it {
+        assert_eq!(*x, ys[i]);
+        i += 1;
+    }
+    assert_eq!(i, ys.len());
+}
+
+#[test]
+fn test_iterator_skip() {
+    let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
+    let ys = [13, 15, 16, 17, 19, 20, 30];
+    let mut it = xs.iter().skip(5);
+    let mut i = 0;
+    while let Some(&x) = it.next() {
+        assert_eq!(x, ys[i]);
+        i += 1;
+        assert_eq!(it.len(), xs.len()-5-i);
+    }
+    assert_eq!(i, ys.len());
+    assert_eq!(it.len(), 0);
+}
+
+#[test]
+fn test_iterator_skip_doubleended() {
+    let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
+    let mut it = xs.iter().rev().skip(5);
+    assert_eq!(it.next(), Some(&15));
+    assert_eq!(it.by_ref().rev().next(), Some(&0));
+    assert_eq!(it.next(), Some(&13));
+    assert_eq!(it.by_ref().rev().next(), Some(&1));
+    assert_eq!(it.next(), Some(&5));
+    assert_eq!(it.by_ref().rev().next(), Some(&2));
+    assert_eq!(it.next(), Some(&3));
+    assert_eq!(it.next(), None);
+    let mut it = xs.iter().rev().skip(5).rev();
+    assert_eq!(it.next(), Some(&0));
+    assert_eq!(it.rev().next(), Some(&15));
+    let mut it_base = xs.iter();
+    {
+        let mut it = it_base.by_ref().skip(5).rev();
+        assert_eq!(it.next(), Some(&30));
+        assert_eq!(it.next(), Some(&20));
+        assert_eq!(it.next(), Some(&19));
+        assert_eq!(it.next(), Some(&17));
+        assert_eq!(it.next(), Some(&16));
+        assert_eq!(it.next(), Some(&15));
+        assert_eq!(it.next(), Some(&13));
+        assert_eq!(it.next(), None);
+    }
+    // make sure the skipped parts have not been consumed
+    assert_eq!(it_base.next(), Some(&0));
+    assert_eq!(it_base.next(), Some(&1));
+    assert_eq!(it_base.next(), Some(&2));
+    assert_eq!(it_base.next(), Some(&3));
+    assert_eq!(it_base.next(), Some(&5));
+    assert_eq!(it_base.next(), None);
+    let it = xs.iter().skip(5).rev();
+    assert_eq!(it.last(), Some(&13));
+}
+
+#[test]
+fn test_iterator_skip_nth() {
+    let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
+
+    let mut it = xs.iter().skip(0);
+    assert_eq!(it.nth(0), Some(&0));
+    assert_eq!(it.nth(1), Some(&2));
+
+    let mut it = xs.iter().skip(5);
+    assert_eq!(it.nth(0), Some(&13));
+    assert_eq!(it.nth(1), Some(&16));
+
+    let mut it = xs.iter().skip(12);
+    assert_eq!(it.nth(0), None);
+
+}
+
+#[test]
+fn test_iterator_skip_count() {
+    let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
+
+    assert_eq!(xs.iter().skip(0).count(), 12);
+    assert_eq!(xs.iter().skip(1).count(), 11);
+    assert_eq!(xs.iter().skip(11).count(), 1);
+    assert_eq!(xs.iter().skip(12).count(), 0);
+    assert_eq!(xs.iter().skip(13).count(), 0);
+}
+
+#[test]
+fn test_iterator_skip_last() {
+    let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
+
+    assert_eq!(xs.iter().skip(0).last(), Some(&30));
+    assert_eq!(xs.iter().skip(1).last(), Some(&30));
+    assert_eq!(xs.iter().skip(11).last(), Some(&30));
+    assert_eq!(xs.iter().skip(12).last(), None);
+    assert_eq!(xs.iter().skip(13).last(), None);
+
+    let mut it = xs.iter().skip(5);
+    assert_eq!(it.next(), Some(&13));
+    assert_eq!(it.last(), Some(&30));
+}
+
+#[test]
+fn test_iterator_take() {
+    let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19];
+    let ys = [0, 1, 2, 3, 5];
+    let mut it = xs.iter().take(5);
+    let mut i = 0;
+    assert_eq!(it.len(), 5);
+    while let Some(&x) = it.next() {
+        assert_eq!(x, ys[i]);
+        i += 1;
+        assert_eq!(it.len(), 5-i);
+    }
+    assert_eq!(i, ys.len());
+    assert_eq!(it.len(), 0);
+}
+
+#[test]
+fn test_iterator_take_nth() {
+    let xs = [0, 1, 2, 4, 5];
+    let mut it = xs.iter();
+    {
+        let mut take = it.by_ref().take(3);
+        let mut i = 0;
+        while let Some(&x) = take.nth(0) {
+            assert_eq!(x, i);
+            i += 1;
+        }
+    }
+    assert_eq!(it.nth(1), Some(&5));
+    assert_eq!(it.nth(0), None);
+
+    let xs = [0, 1, 2, 3, 4];
+    let mut it = xs.iter().take(7);
+    let mut i = 1;
+    while let Some(&x) = it.nth(1) {
+        assert_eq!(x, i);
+        i += 2;
+    }
+}
+
+#[test]
+fn test_iterator_take_short() {
+    let xs = [0, 1, 2, 3];
+    let ys = [0, 1, 2, 3];
+    let mut it = xs.iter().take(5);
+    let mut i = 0;
+    assert_eq!(it.len(), 4);
+    while let Some(&x) = it.next() {
+        assert_eq!(x, ys[i]);
+        i += 1;
+        assert_eq!(it.len(), 4-i);
+    }
+    assert_eq!(i, ys.len());
+    assert_eq!(it.len(), 0);
+}
+
+#[test]
+fn test_iterator_scan() {
+    // test the type inference
+    fn add(old: &mut isize, new: &usize) -> Option<f64> {
+        *old += *new as isize;
+        Some(*old as f64)
+    }
+    let xs = [0, 1, 2, 3, 4];
+    let ys = [0f64, 1.0, 3.0, 6.0, 10.0];
+
+    let it = xs.iter().scan(0, add);
+    let mut i = 0;
+    for x in it {
+        assert_eq!(x, ys[i]);
+        i += 1;
+    }
+    assert_eq!(i, ys.len());
+}
+
+#[test]
+fn test_iterator_flat_map() {
+    let xs = [0, 3, 6];
+    let ys = [0, 1, 2, 3, 4, 5, 6, 7, 8];
+    let it = xs.iter().flat_map(|&x| (x..).step_by(1).take(3));
+    let mut i = 0;
+    for x in it {
+        assert_eq!(x, ys[i]);
+        i += 1;
+    }
+    assert_eq!(i, ys.len());
+}
+
+#[test]
+fn test_inspect() {
+    let xs = [1, 2, 3, 4];
+    let mut n = 0;
+
+    let ys = xs.iter()
+               .cloned()
+               .inspect(|_| n += 1)
+               .collect::<Vec<usize>>();
+
+    assert_eq!(n, xs.len());
+    assert_eq!(&xs[..], &ys[..]);
+}
+
+#[test]
+fn test_cycle() {
+    let cycle_len = 3;
+    let it = (0..).step_by(1).take(cycle_len).cycle();
+    assert_eq!(it.size_hint(), (usize::MAX, None));
+    for (i, x) in it.take(100).enumerate() {
+        assert_eq!(i % cycle_len, x);
+    }
+
+    let mut it = (0..).step_by(1).take(0).cycle();
+    assert_eq!(it.size_hint(), (0, Some(0)));
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_iterator_nth() {
+    let v: &[_] = &[0, 1, 2, 3, 4];
+    for i in 0..v.len() {
+        assert_eq!(v.iter().nth(i).unwrap(), &v[i]);
+    }
+    assert_eq!(v.iter().nth(v.len()), None);
+}
+
+#[test]
+fn test_iterator_last() {
+    let v: &[_] = &[0, 1, 2, 3, 4];
+    assert_eq!(v.iter().last().unwrap(), &4);
+    assert_eq!(v[..1].iter().last().unwrap(), &0);
+}
+
+#[test]
+fn test_iterator_len() {
+    let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    assert_eq!(v[..4].iter().count(), 4);
+    assert_eq!(v[..10].iter().count(), 10);
+    assert_eq!(v[..0].iter().count(), 0);
+}
+
+#[test]
+fn test_iterator_sum() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    assert_eq!(v[..4].iter().cloned().sum::<i32>(), 6);
+    assert_eq!(v.iter().cloned().sum::<i32>(), 55);
+    assert_eq!(v[..0].iter().cloned().sum::<i32>(), 0);
+}
+
+#[test]
+fn test_iterator_sum_result() {
+    let v: &[Result<i32, ()>] = &[Ok(1), Ok(2), Ok(3), Ok(4)];
+    assert_eq!(v.iter().cloned().sum::<Result<i32, _>>(), Ok(10));
+    let v: &[Result<i32, ()>] = &[Ok(1), Err(()), Ok(3), Ok(4)];
+    assert_eq!(v.iter().cloned().sum::<Result<i32, _>>(), Err(()));
+}
+
+#[test]
+fn test_iterator_product() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    assert_eq!(v[..4].iter().cloned().product::<i32>(), 0);
+    assert_eq!(v[1..5].iter().cloned().product::<i32>(), 24);
+    assert_eq!(v[..0].iter().cloned().product::<i32>(), 1);
+}
+
+#[test]
+fn test_iterator_product_result() {
+    let v: &[Result<i32, ()>] = &[Ok(1), Ok(2), Ok(3), Ok(4)];
+    assert_eq!(v.iter().cloned().product::<Result<i32, _>>(), Ok(24));
+    let v: &[Result<i32, ()>] = &[Ok(1), Err(()), Ok(3), Ok(4)];
+    assert_eq!(v.iter().cloned().product::<Result<i32, _>>(), Err(()));
+}
+
+#[test]
+fn test_iterator_max() {
+    let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    assert_eq!(v[..4].iter().cloned().max(), Some(3));
+    assert_eq!(v.iter().cloned().max(), Some(10));
+    assert_eq!(v[..0].iter().cloned().max(), None);
+}
+
+#[test]
+fn test_iterator_min() {
+    let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    assert_eq!(v[..4].iter().cloned().min(), Some(0));
+    assert_eq!(v.iter().cloned().min(), Some(0));
+    assert_eq!(v[..0].iter().cloned().min(), None);
+}
+
+#[test]
+fn test_iterator_size_hint() {
+    let c = (0..).step_by(1);
+    let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+    let v2 = &[10, 11, 12];
+    let vi = v.iter();
+
+    assert_eq!(c.size_hint(), (usize::MAX, None));
+    assert_eq!(vi.clone().size_hint(), (10, Some(10)));
+
+    assert_eq!(c.clone().take(5).size_hint(), (5, Some(5)));
+    assert_eq!(c.clone().skip(5).size_hint().1, None);
+    assert_eq!(c.clone().take_while(|_| false).size_hint(), (0, None));
+    assert_eq!(c.clone().skip_while(|_| false).size_hint(), (0, None));
+    assert_eq!(c.clone().enumerate().size_hint(), (usize::MAX, None));
+    assert_eq!(c.clone().chain(vi.clone().cloned()).size_hint(), (usize::MAX, None));
+    assert_eq!(c.clone().zip(vi.clone()).size_hint(), (10, Some(10)));
+    assert_eq!(c.clone().scan(0, |_,_| Some(0)).size_hint(), (0, None));
+    assert_eq!(c.clone().filter(|_| false).size_hint(), (0, None));
+    assert_eq!(c.clone().map(|_| 0).size_hint(), (usize::MAX, None));
+    assert_eq!(c.filter_map(|_| Some(0)).size_hint(), (0, None));
+
+    assert_eq!(vi.clone().take(5).size_hint(), (5, Some(5)));
+    assert_eq!(vi.clone().take(12).size_hint(), (10, Some(10)));
+    assert_eq!(vi.clone().skip(3).size_hint(), (7, Some(7)));
+    assert_eq!(vi.clone().skip(12).size_hint(), (0, Some(0)));
+    assert_eq!(vi.clone().take_while(|_| false).size_hint(), (0, Some(10)));
+    assert_eq!(vi.clone().skip_while(|_| false).size_hint(), (0, Some(10)));
+    assert_eq!(vi.clone().enumerate().size_hint(), (10, Some(10)));
+    assert_eq!(vi.clone().chain(v2).size_hint(), (13, Some(13)));
+    assert_eq!(vi.clone().zip(v2).size_hint(), (3, Some(3)));
+    assert_eq!(vi.clone().scan(0, |_,_| Some(0)).size_hint(), (0, Some(10)));
+    assert_eq!(vi.clone().filter(|_| false).size_hint(), (0, Some(10)));
+    assert_eq!(vi.clone().map(|&i| i+1).size_hint(), (10, Some(10)));
+    assert_eq!(vi.filter_map(|_| Some(0)).size_hint(), (0, Some(10)));
+}
+
+#[test]
+fn test_collect() {
+    let a = vec![1, 2, 3, 4, 5];
+    let b: Vec<isize> = a.iter().cloned().collect();
+    assert!(a == b);
+}
+
+#[test]
+fn test_all() {
+    let v: Box<[isize]> = Box::new([1, 2, 3, 4, 5]);
+    assert!(v.iter().all(|&x| x < 10));
+    assert!(!v.iter().all(|&x| x % 2 == 0));
+    assert!(!v.iter().all(|&x| x > 100));
+    assert!(v[..0].iter().all(|_| panic!()));
+}
+
+#[test]
+fn test_any() {
+    let v: Box<[isize]> = Box::new([1, 2, 3, 4, 5]);
+    assert!(v.iter().any(|&x| x < 10));
+    assert!(v.iter().any(|&x| x % 2 == 0));
+    assert!(!v.iter().any(|&x| x > 100));
+    assert!(!v[..0].iter().any(|_| panic!()));
+}
+
+#[test]
+fn test_find() {
+    let v: &[isize] = &[1, 3, 9, 27, 103, 14, 11];
+    assert_eq!(*v.iter().find(|&&x| x & 1 == 0).unwrap(), 14);
+    assert_eq!(*v.iter().find(|&&x| x % 3 == 0).unwrap(), 3);
+    assert!(v.iter().find(|&&x| x % 12 == 0).is_none());
+}
+
+#[test]
+fn test_position() {
+    let v = &[1, 3, 9, 27, 103, 14, 11];
+    assert_eq!(v.iter().position(|x| *x & 1 == 0).unwrap(), 5);
+    assert_eq!(v.iter().position(|x| *x % 3 == 0).unwrap(), 1);
+    assert!(v.iter().position(|x| *x % 12 == 0).is_none());
+}
+
+#[test]
+fn test_count() {
+    let xs = &[1, 2, 2, 1, 5, 9, 0, 2];
+    assert_eq!(xs.iter().filter(|x| **x == 2).count(), 3);
+    assert_eq!(xs.iter().filter(|x| **x == 5).count(), 1);
+    assert_eq!(xs.iter().filter(|x| **x == 95).count(), 0);
+}
+
+#[test]
+fn test_max_by_key() {
+    let xs: &[isize] = &[-3, 0, 1, 5, -10];
+    assert_eq!(*xs.iter().max_by_key(|x| x.abs()).unwrap(), -10);
+}
+
+#[test]
+fn test_max_by() {
+    let xs: &[isize] = &[-3, 0, 1, 5, -10];
+    assert_eq!(*xs.iter().max_by(|x, y| x.abs().cmp(&y.abs())).unwrap(), -10);
+}
+
+#[test]
+fn test_min_by_key() {
+    let xs: &[isize] = &[-3, 0, 1, 5, -10];
+    assert_eq!(*xs.iter().min_by_key(|x| x.abs()).unwrap(), 0);
+}
+
+#[test]
+fn test_min_by() {
+    let xs: &[isize] = &[-3, 0, 1, 5, -10];
+    assert_eq!(*xs.iter().min_by(|x, y| x.abs().cmp(&y.abs())).unwrap(), 0);
+}
+
+#[test]
+fn test_by_ref() {
+    let mut xs = 0..10;
+    // sum the first five values
+    let partial_sum = xs.by_ref().take(5).fold(0, |a, b| a + b);
+    assert_eq!(partial_sum, 10);
+    assert_eq!(xs.next(), Some(5));
+}
+
+#[test]
+fn test_rev() {
+    let xs = [2, 4, 6, 8, 10, 12, 14, 16];
+    let mut it = xs.iter();
+    it.next();
+    it.next();
+    assert!(it.rev().cloned().collect::<Vec<isize>>() ==
+            vec![16, 14, 12, 10, 8, 6]);
+}
+
+#[test]
+fn test_cloned() {
+    let xs = [2, 4, 6, 8];
+
+    let mut it = xs.iter().cloned();
+    assert_eq!(it.len(), 4);
+    assert_eq!(it.next(), Some(2));
+    assert_eq!(it.len(), 3);
+    assert_eq!(it.next(), Some(4));
+    assert_eq!(it.len(), 2);
+    assert_eq!(it.next_back(), Some(8));
+    assert_eq!(it.len(), 1);
+    assert_eq!(it.next_back(), Some(6));
+    assert_eq!(it.len(), 0);
+    assert_eq!(it.next_back(), None);
+}
+
+#[test]
+fn test_double_ended_map() {
+    let xs = [1, 2, 3, 4, 5, 6];
+    let mut it = xs.iter().map(|&x| x * -1);
+    assert_eq!(it.next(), Some(-1));
+    assert_eq!(it.next(), Some(-2));
+    assert_eq!(it.next_back(), Some(-6));
+    assert_eq!(it.next_back(), Some(-5));
+    assert_eq!(it.next(), Some(-3));
+    assert_eq!(it.next_back(), Some(-4));
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_double_ended_enumerate() {
+    let xs = [1, 2, 3, 4, 5, 6];
+    let mut it = xs.iter().cloned().enumerate();
+    assert_eq!(it.next(), Some((0, 1)));
+    assert_eq!(it.next(), Some((1, 2)));
+    assert_eq!(it.next_back(), Some((5, 6)));
+    assert_eq!(it.next_back(), Some((4, 5)));
+    assert_eq!(it.next_back(), Some((3, 4)));
+    assert_eq!(it.next_back(), Some((2, 3)));
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_double_ended_zip() {
+    let xs = [1, 2, 3, 4, 5, 6];
+    let ys = [1, 2, 3, 7];
+    let a = xs.iter().cloned();
+    let b = ys.iter().cloned();
+    let mut it = a.zip(b);
+    assert_eq!(it.next(), Some((1, 1)));
+    assert_eq!(it.next(), Some((2, 2)));
+    assert_eq!(it.next_back(), Some((4, 7)));
+    assert_eq!(it.next_back(), Some((3, 3)));
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_double_ended_filter() {
+    let xs = [1, 2, 3, 4, 5, 6];
+    let mut it = xs.iter().filter(|&x| *x & 1 == 0);
+    assert_eq!(it.next_back().unwrap(), &6);
+    assert_eq!(it.next_back().unwrap(), &4);
+    assert_eq!(it.next().unwrap(), &2);
+    assert_eq!(it.next_back(), None);
+}
+
+#[test]
+fn test_double_ended_filter_map() {
+    let xs = [1, 2, 3, 4, 5, 6];
+    let mut it = xs.iter().filter_map(|&x| if x & 1 == 0 { Some(x * 2) } else { None });
+    assert_eq!(it.next_back().unwrap(), 12);
+    assert_eq!(it.next_back().unwrap(), 8);
+    assert_eq!(it.next().unwrap(), 4);
+    assert_eq!(it.next_back(), None);
+}
+
+#[test]
+fn test_double_ended_chain() {
+    let xs = [1, 2, 3, 4, 5];
+    let ys = [7, 9, 11];
+    let mut it = xs.iter().chain(&ys).rev();
+    assert_eq!(it.next().unwrap(), &11);
+    assert_eq!(it.next().unwrap(), &9);
+    assert_eq!(it.next_back().unwrap(), &1);
+    assert_eq!(it.next_back().unwrap(), &2);
+    assert_eq!(it.next_back().unwrap(), &3);
+    assert_eq!(it.next_back().unwrap(), &4);
+    assert_eq!(it.next_back().unwrap(), &5);
+    assert_eq!(it.next_back().unwrap(), &7);
+    assert_eq!(it.next_back(), None);
+
+
+    // test that .chain() is well behaved with an unfused iterator
+    struct CrazyIterator(bool);
+    impl CrazyIterator { fn new() -> CrazyIterator { CrazyIterator(false) } }
+    impl Iterator for CrazyIterator {
+        type Item = i32;
+        fn next(&mut self) -> Option<i32> {
+            if self.0 { Some(99) } else { self.0 = true; None }
+        }
+    }
+
+    impl DoubleEndedIterator for CrazyIterator {
+        fn next_back(&mut self) -> Option<i32> {
+            self.next()
+        }
+    }
+
+    assert_eq!(CrazyIterator::new().chain(0..10).rev().last(), Some(0));
+    assert!((0..10).chain(CrazyIterator::new()).rev().any(|i| i == 0));
+}
+
+#[test]
+fn test_rposition() {
+    fn f(xy: &(isize, char)) -> bool { let (_x, y) = *xy; y == 'b' }
+    fn g(xy: &(isize, char)) -> bool { let (_x, y) = *xy; y == 'd' }
+    let v = [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
+
+    assert_eq!(v.iter().rposition(f), Some(3));
+    assert!(v.iter().rposition(g).is_none());
+}
+
+#[test]
+#[should_panic]
+fn test_rposition_panic() {
+    let v: [(Box<_>, Box<_>); 4] =
+        [(box 0, box 0), (box 0, box 0),
+         (box 0, box 0), (box 0, box 0)];
+    let mut i = 0;
+    v.iter().rposition(|_elt| {
+        if i == 2 {
+            panic!()
+        }
+        i += 1;
+        false
+    });
+}
+
+
+#[test]
+fn test_double_ended_flat_map() {
+    let u = [0,1];
+    let v = [5,6,7,8];
+    let mut it = u.iter().flat_map(|x| &v[*x..v.len()]);
+    assert_eq!(it.next_back().unwrap(), &8);
+    assert_eq!(it.next().unwrap(),      &5);
+    assert_eq!(it.next_back().unwrap(), &7);
+    assert_eq!(it.next_back().unwrap(), &6);
+    assert_eq!(it.next_back().unwrap(), &8);
+    assert_eq!(it.next().unwrap(),      &6);
+    assert_eq!(it.next_back().unwrap(), &7);
+    assert_eq!(it.next_back(), None);
+    assert_eq!(it.next(),      None);
+    assert_eq!(it.next_back(), None);
+}
+
+#[test]
+fn test_double_ended_range() {
+    assert_eq!((11..14).rev().collect::<Vec<_>>(), [13, 12, 11]);
+    for _ in (10..0).rev() {
+        panic!("unreachable");
+    }
+
+    assert_eq!((11..14).rev().collect::<Vec<_>>(), [13, 12, 11]);
+    for _ in (10..0).rev() {
+        panic!("unreachable");
+    }
+}
+
+#[test]
+fn test_range() {
+    assert_eq!((0..5).collect::<Vec<_>>(), [0, 1, 2, 3, 4]);
+    assert_eq!((-10..-1).collect::<Vec<_>>(), [-10, -9, -8, -7, -6, -5, -4, -3, -2]);
+    assert_eq!((0..5).rev().collect::<Vec<_>>(), [4, 3, 2, 1, 0]);
+    assert_eq!((200..-5).count(), 0);
+    assert_eq!((200..-5).rev().count(), 0);
+    assert_eq!((200..200).count(), 0);
+    assert_eq!((200..200).rev().count(), 0);
+
+    assert_eq!((0..100).size_hint(), (100, Some(100)));
+    // this test is only meaningful when sizeof usize < sizeof u64
+    assert_eq!((usize::MAX - 1..usize::MAX).size_hint(), (1, Some(1)));
+    assert_eq!((-10..-1).size_hint(), (9, Some(9)));
+    assert_eq!((-1..-10).size_hint(), (0, Some(0)));
+
+    assert_eq!((-70..58).size_hint(), (128, Some(128)));
+    assert_eq!((-128..127).size_hint(), (255, Some(255)));
+    assert_eq!((-2..isize::MAX).size_hint(),
+               (isize::MAX as usize + 2, Some(isize::MAX as usize + 2)));
+}
+
+#[test]
+fn test_range_step() {
+    assert_eq!((0..20).step_by(5).collect::<Vec<isize>>(), [0, 5, 10, 15]);
+    assert_eq!((20..0).step_by(-5).collect::<Vec<isize>>(), [20, 15, 10, 5]);
+    assert_eq!((20..0).step_by(-6).collect::<Vec<isize>>(), [20, 14, 8, 2]);
+    assert_eq!((200..255).step_by(50).collect::<Vec<u8>>(), [200, 250]);
+    assert_eq!((200..-5).step_by(1).collect::<Vec<isize>>(), []);
+    assert_eq!((200..200).step_by(1).collect::<Vec<isize>>(), []);
+
+    assert_eq!((0..20).step_by(1).size_hint(), (20, Some(20)));
+    assert_eq!((0..20).step_by(21).size_hint(), (1, Some(1)));
+    assert_eq!((0..20).step_by(5).size_hint(), (4, Some(4)));
+    assert_eq!((20..0).step_by(-5).size_hint(), (4, Some(4)));
+    assert_eq!((20..0).step_by(-6).size_hint(), (4, Some(4)));
+    assert_eq!((20..-5).step_by(1).size_hint(), (0, Some(0)));
+    assert_eq!((20..20).step_by(1).size_hint(), (0, Some(0)));
+    assert_eq!((0..1).step_by(0).size_hint(), (0, None));
+    assert_eq!((i8::MAX..i8::MIN).step_by(i8::MIN).size_hint(), (2, Some(2)));
+    assert_eq!((i16::MIN..i16::MAX).step_by(i16::MAX).size_hint(), (3, Some(3)));
+    assert_eq!((isize::MIN..isize::MAX).step_by(1).size_hint(), (usize::MAX, Some(usize::MAX)));
+}
+
+#[test]
+fn test_repeat() {
+    let mut it = repeat(42);
+    assert_eq!(it.next(), Some(42));
+    assert_eq!(it.next(), Some(42));
+    assert_eq!(it.next(), Some(42));
+}
+
+#[test]
+fn test_fuse() {
+    let mut it = 0..3;
+    assert_eq!(it.len(), 3);
+    assert_eq!(it.next(), Some(0));
+    assert_eq!(it.len(), 2);
+    assert_eq!(it.next(), Some(1));
+    assert_eq!(it.len(), 1);
+    assert_eq!(it.next(), Some(2));
+    assert_eq!(it.len(), 0);
+    assert_eq!(it.next(), None);
+    assert_eq!(it.len(), 0);
+    assert_eq!(it.next(), None);
+    assert_eq!(it.len(), 0);
+    assert_eq!(it.next(), None);
+    assert_eq!(it.len(), 0);
+}
+
+#[test]
+fn test_fuse_nth() {
+    let xs = [0, 1, 2];
+    let mut it = xs.iter();
+
+    assert_eq!(it.len(), 3);
+    assert_eq!(it.nth(2), Some(&2));
+    assert_eq!(it.len(), 0);
+    assert_eq!(it.nth(2), None);
+    assert_eq!(it.len(), 0);
+}
+
+#[test]
+fn test_fuse_last() {
+    let xs = [0, 1, 2];
+    let it = xs.iter();
+
+    assert_eq!(it.len(), 3);
+    assert_eq!(it.last(), Some(&2));
+}
+
+#[test]
+fn test_fuse_count() {
+    let xs = [0, 1, 2];
+    let it = xs.iter();
+
+    assert_eq!(it.len(), 3);
+    assert_eq!(it.count(), 3);
+    // Can't check len now because count consumes.
+}
+
+#[test]
+fn test_once() {
+    let mut it = once(42);
+    assert_eq!(it.next(), Some(42));
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_empty() {
+    let mut it = empty::<i32>();
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_chain_fold() {
+    let xs = [1, 2, 3];
+    let ys = [1, 2, 0];
+
+    let mut iter = xs.iter().chain(&ys);
+    iter.next();
+    let mut result = Vec::new();
+    iter.fold((), |(), &elt| result.push(elt));
+    assert_eq!(&[2, 3, 1, 2, 0], &result[..]);
+}
+
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
new file mode 100644
index 00000000000..528ab3bc845
--- /dev/null
+++ b/src/libcore/tests/lib.rs
@@ -0,0 +1,64 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![deny(warnings)]
+
+#![feature(box_syntax)]
+#![feature(char_escape_debug)]
+#![feature(const_fn)]
+#![feature(core_private_bignum)]
+#![feature(core_private_diy_float)]
+#![feature(dec2flt)]
+#![feature(decode_utf8)]
+#![feature(fixed_size_array)]
+#![feature(flt2dec)]
+#![feature(fmt_internals)]
+#![feature(iter_rfind)]
+#![feature(libc)]
+#![feature(nonzero)]
+#![feature(rand)]
+#![feature(raw)]
+#![feature(sip_hash_13)]
+#![feature(slice_patterns)]
+#![feature(sort_internals)]
+#![feature(sort_unstable)]
+#![feature(step_by)]
+#![feature(test)]
+#![feature(try_from)]
+#![feature(unicode)]
+#![feature(unique)]
+
+extern crate core;
+extern crate test;
+extern crate libc;
+extern crate std_unicode;
+extern crate rand;
+
+mod any;
+mod array;
+mod atomic;
+mod cell;
+mod char;
+mod clone;
+mod cmp;
+mod fmt;
+mod hash;
+mod intrinsics;
+mod iter;
+mod mem;
+mod nonzero;
+mod num;
+mod ops;
+mod option;
+mod ptr;
+mod result;
+mod slice;
+mod str;
+mod tuple;
diff --git a/src/libcore/tests/mem.rs b/src/libcore/tests/mem.rs
new file mode 100644
index 00000000000..86e59c736ba
--- /dev/null
+++ b/src/libcore/tests/mem.rs
@@ -0,0 +1,123 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::mem::*;
+
+#[test]
+fn size_of_basic() {
+    assert_eq!(size_of::<u8>(), 1);
+    assert_eq!(size_of::<u16>(), 2);
+    assert_eq!(size_of::<u32>(), 4);
+    assert_eq!(size_of::<u64>(), 8);
+}
+
+#[test]
+#[cfg(target_pointer_width = "16")]
+fn size_of_16() {
+    assert_eq!(size_of::<usize>(), 2);
+    assert_eq!(size_of::<*const usize>(), 2);
+}
+
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn size_of_32() {
+    assert_eq!(size_of::<usize>(), 4);
+    assert_eq!(size_of::<*const usize>(), 4);
+}
+
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn size_of_64() {
+    assert_eq!(size_of::<usize>(), 8);
+    assert_eq!(size_of::<*const usize>(), 8);
+}
+
+#[test]
+fn size_of_val_basic() {
+    assert_eq!(size_of_val(&1u8), 1);
+    assert_eq!(size_of_val(&1u16), 2);
+    assert_eq!(size_of_val(&1u32), 4);
+    assert_eq!(size_of_val(&1u64), 8);
+}
+
+#[test]
+fn align_of_basic() {
+    assert_eq!(align_of::<u8>(), 1);
+    assert_eq!(align_of::<u16>(), 2);
+    assert_eq!(align_of::<u32>(), 4);
+}
+
+#[test]
+#[cfg(target_pointer_width = "16")]
+fn align_of_16() {
+    assert_eq!(align_of::<usize>(), 2);
+    assert_eq!(align_of::<*const usize>(), 2);
+}
+
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn align_of_32() {
+    assert_eq!(align_of::<usize>(), 4);
+    assert_eq!(align_of::<*const usize>(), 4);
+}
+
+#[test]
+#[cfg(target_pointer_width = "64")]
+fn align_of_64() {
+    assert_eq!(align_of::<usize>(), 8);
+    assert_eq!(align_of::<*const usize>(), 8);
+}
+
+#[test]
+fn align_of_val_basic() {
+    assert_eq!(align_of_val(&1u8), 1);
+    assert_eq!(align_of_val(&1u16), 2);
+    assert_eq!(align_of_val(&1u32), 4);
+}
+
+#[test]
+fn test_swap() {
+    let mut x = 31337;
+    let mut y = 42;
+    swap(&mut x, &mut y);
+    assert_eq!(x, 42);
+    assert_eq!(y, 31337);
+}
+
+#[test]
+fn test_replace() {
+    let mut x = Some("test".to_string());
+    let y = replace(&mut x, None);
+    assert!(x.is_none());
+    assert!(y.is_some());
+}
+
+#[test]
+fn test_transmute_copy() {
+    assert_eq!(1, unsafe { transmute_copy(&1) });
+}
+
+#[test]
+fn test_transmute() {
+    trait Foo { fn dummy(&self) { } }
+    impl Foo for isize {}
+
+    let a = box 100isize as Box<Foo>;
+    unsafe {
+        let x: ::core::raw::TraitObject = transmute(a);
+        assert!(*(x.data as *const isize) == 100);
+        let _x: Box<Foo> = transmute(x);
+    }
+
+    unsafe {
+        assert_eq!(transmute::<_, Vec<u8>>("L".to_string()), [76]);
+    }
+}
+
diff --git a/src/libcore/tests/nonzero.rs b/src/libcore/tests/nonzero.rs
new file mode 100644
index 00000000000..7a367ddeec8
--- /dev/null
+++ b/src/libcore/tests/nonzero.rs
@@ -0,0 +1,100 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::nonzero::NonZero;
+use core::option::Option;
+use core::option::Option::{Some, None};
+use std::mem::size_of;
+
+#[test]
+fn test_create_nonzero_instance() {
+    let _a = unsafe {
+        NonZero::new(21)
+    };
+}
+
+#[test]
+fn test_size_nonzero_in_option() {
+    assert_eq!(size_of::<NonZero<u32>>(), size_of::<Option<NonZero<u32>>>());
+}
+
+#[test]
+fn test_match_on_nonzero_option() {
+    let a = Some(unsafe {
+        NonZero::new(42)
+    });
+    match a {
+        Some(val) => assert_eq!(*val, 42),
+        None => panic!("unexpected None while matching on Some(NonZero(_))")
+    }
+
+    match unsafe { Some(NonZero::new(43)) } {
+        Some(val) => assert_eq!(*val, 43),
+        None => panic!("unexpected None while matching on Some(NonZero(_))")
+    }
+}
+
+#[test]
+fn test_match_option_empty_vec() {
+    let a: Option<Vec<isize>> = Some(vec![]);
+    match a {
+        None => panic!("unexpected None while matching on Some(vec![])"),
+        _ => {}
+    }
+}
+
+#[test]
+fn test_match_option_vec() {
+    let a = Some(vec![1, 2, 3, 4]);
+    match a {
+        Some(v) => assert_eq!(v, [1, 2, 3, 4]),
+        None => panic!("unexpected None while matching on Some(vec![1, 2, 3, 4])")
+    }
+}
+
+#[test]
+fn test_match_option_rc() {
+    use std::rc::Rc;
+
+    let five = Rc::new(5);
+    match Some(five) {
+        Some(r) => assert_eq!(*r, 5),
+        None => panic!("unexpected None while matching on Some(Rc::new(5))")
+    }
+}
+
+#[test]
+fn test_match_option_arc() {
+    use std::sync::Arc;
+
+    let five = Arc::new(5);
+    match Some(five) {
+        Some(a) => assert_eq!(*a, 5),
+        None => panic!("unexpected None while matching on Some(Arc::new(5))")
+    }
+}
+
+#[test]
+fn test_match_option_empty_string() {
+    let a = Some(String::new());
+    match a {
+        None => panic!("unexpected None while matching on Some(String::new())"),
+        _ => {}
+    }
+}
+
+#[test]
+fn test_match_option_string() {
+    let five = "Five".to_string();
+    match Some(five) {
+        Some(s) => assert_eq!(s, "Five"),
+        None => panic!("unexpected None while matching on Some(String { ... })")
+    }
+}
diff --git a/src/libcore/tests/num/bignum.rs b/src/libcore/tests/num/bignum.rs
new file mode 100644
index 00000000000..58a9dd1b128
--- /dev/null
+++ b/src/libcore/tests/num/bignum.rs
@@ -0,0 +1,249 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::prelude::v1::*;
+use core::num::bignum::tests::Big8x3 as Big;
+
+#[test]
+#[should_panic]
+fn test_from_u64_overflow() {
+    Big::from_u64(0x1000000);
+}
+
+#[test]
+fn test_add() {
+    assert_eq!(*Big::from_small(3).add(&Big::from_small(4)), Big::from_small(7));
+    assert_eq!(*Big::from_small(3).add(&Big::from_small(0)), Big::from_small(3));
+    assert_eq!(*Big::from_small(0).add(&Big::from_small(3)), Big::from_small(3));
+    assert_eq!(*Big::from_small(3).add(&Big::from_u64(0xfffe)), Big::from_u64(0x10001));
+    assert_eq!(*Big::from_u64(0xfedc).add(&Big::from_u64(0x789)), Big::from_u64(0x10665));
+    assert_eq!(*Big::from_u64(0x789).add(&Big::from_u64(0xfedc)), Big::from_u64(0x10665));
+}
+
+#[test]
+#[should_panic]
+fn test_add_overflow_1() {
+    Big::from_small(1).add(&Big::from_u64(0xffffff));
+}
+
+#[test]
+#[should_panic]
+fn test_add_overflow_2() {
+    Big::from_u64(0xffffff).add(&Big::from_small(1));
+}
+
+#[test]
+fn test_add_small() {
+    assert_eq!(*Big::from_small(3).add_small(4), Big::from_small(7));
+    assert_eq!(*Big::from_small(3).add_small(0), Big::from_small(3));
+    assert_eq!(*Big::from_small(0).add_small(3), Big::from_small(3));
+    assert_eq!(*Big::from_small(7).add_small(250), Big::from_u64(257));
+    assert_eq!(*Big::from_u64(0x7fff).add_small(1), Big::from_u64(0x8000));
+    assert_eq!(*Big::from_u64(0x2ffe).add_small(0x35), Big::from_u64(0x3033));
+    assert_eq!(*Big::from_small(0xdc).add_small(0x89), Big::from_u64(0x165));
+}
+
+#[test]
+#[should_panic]
+fn test_add_small_overflow() {
+    Big::from_u64(0xffffff).add_small(1);
+}
+
+#[test]
+fn test_sub() {
+    assert_eq!(*Big::from_small(7).sub(&Big::from_small(4)), Big::from_small(3));
+    assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x789)), Big::from_u64(0xfedc));
+    assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0xfedc)), Big::from_u64(0x789));
+    assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x10664)), Big::from_small(1));
+    assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x10665)), Big::from_small(0));
+}
+
+#[test]
+#[should_panic]
+fn test_sub_underflow_1() {
+    Big::from_u64(0x10665).sub(&Big::from_u64(0x10666));
+}
+
+#[test]
+#[should_panic]
+fn test_sub_underflow_2() {
+    Big::from_small(0).sub(&Big::from_u64(0x123456));
+}
+
+#[test]
+fn test_mul_small() {
+    assert_eq!(*Big::from_small(7).mul_small(5), Big::from_small(35));
+    assert_eq!(*Big::from_small(0xff).mul_small(0xff), Big::from_u64(0xfe01));
+    assert_eq!(*Big::from_u64(0xffffff/13).mul_small(13), Big::from_u64(0xffffff));
+}
+
+#[test]
+#[should_panic]
+fn test_mul_small_overflow() {
+    Big::from_u64(0x800000).mul_small(2);
+}
+
+#[test]
+fn test_mul_pow2() {
+    assert_eq!(*Big::from_small(0x7).mul_pow2(4), Big::from_small(0x70));
+    assert_eq!(*Big::from_small(0xff).mul_pow2(1), Big::from_u64(0x1fe));
+    assert_eq!(*Big::from_small(0xff).mul_pow2(12), Big::from_u64(0xff000));
+    assert_eq!(*Big::from_small(0x1).mul_pow2(23), Big::from_u64(0x800000));
+    assert_eq!(*Big::from_u64(0x123).mul_pow2(0), Big::from_u64(0x123));
+    assert_eq!(*Big::from_u64(0x123).mul_pow2(7), Big::from_u64(0x9180));
+    assert_eq!(*Big::from_u64(0x123).mul_pow2(15), Big::from_u64(0x918000));
+    assert_eq!(*Big::from_small(0).mul_pow2(23), Big::from_small(0));
+}
+
+#[test]
+#[should_panic]
+fn test_mul_pow2_overflow_1() {
+    Big::from_u64(0x1).mul_pow2(24);
+}
+
+#[test]
+#[should_panic]
+fn test_mul_pow2_overflow_2() {
+    Big::from_u64(0x123).mul_pow2(16);
+}
+
+#[test]
+fn test_mul_pow5() {
+    assert_eq!(*Big::from_small(42).mul_pow5(0), Big::from_small(42));
+    assert_eq!(*Big::from_small(1).mul_pow5(2), Big::from_small(25));
+    assert_eq!(*Big::from_small(1).mul_pow5(4), Big::from_u64(25 * 25));
+    assert_eq!(*Big::from_small(4).mul_pow5(3), Big::from_u64(500));
+    assert_eq!(*Big::from_small(140).mul_pow5(2), Big::from_u64(25 * 140));
+    assert_eq!(*Big::from_small(25).mul_pow5(1), Big::from_small(125));
+    assert_eq!(*Big::from_small(125).mul_pow5(7), Big::from_u64(9765625));
+    assert_eq!(*Big::from_small(0).mul_pow5(127), Big::from_small(0));
+}
+
+#[test]
+#[should_panic]
+fn test_mul_pow5_overflow_1() {
+    Big::from_small(1).mul_pow5(12);
+}
+
+#[test]
+#[should_panic]
+fn test_mul_pow5_overflow_2() {
+    Big::from_small(230).mul_pow5(8);
+}
+
+#[test]
+fn test_mul_digits() {
+    assert_eq!(*Big::from_small(3).mul_digits(&[5]), Big::from_small(15));
+    assert_eq!(*Big::from_small(0xff).mul_digits(&[0xff]), Big::from_u64(0xfe01));
+    assert_eq!(*Big::from_u64(0x123).mul_digits(&[0x56, 0x4]), Big::from_u64(0x4edc2));
+    assert_eq!(*Big::from_u64(0x12345).mul_digits(&[0x67]), Big::from_u64(0x7530c3));
+    assert_eq!(*Big::from_small(0x12).mul_digits(&[0x67, 0x45, 0x3]), Big::from_u64(0x3ae13e));
+    assert_eq!(*Big::from_u64(0xffffff/13).mul_digits(&[13]), Big::from_u64(0xffffff));
+    assert_eq!(*Big::from_small(13).mul_digits(&[0x3b, 0xb1, 0x13]), Big::from_u64(0xffffff));
+}
+
+#[test]
+#[should_panic]
+fn test_mul_digits_overflow_1() {
+    Big::from_u64(0x800000).mul_digits(&[2]);
+}
+
+#[test]
+#[should_panic]
+fn test_mul_digits_overflow_2() {
+    Big::from_u64(0x1000).mul_digits(&[0, 0x10]);
+}
+
+#[test]
+fn test_div_rem_small() {
+    let as_val = |(q, r): (&mut Big, u8)| (q.clone(), r);
+    assert_eq!(as_val(Big::from_small(0xff).div_rem_small(15)), (Big::from_small(17), 0));
+    assert_eq!(as_val(Big::from_small(0xff).div_rem_small(16)), (Big::from_small(15), 15));
+    assert_eq!(as_val(Big::from_small(3).div_rem_small(40)), (Big::from_small(0), 3));
+    assert_eq!(as_val(Big::from_u64(0xffffff).div_rem_small(123)),
+               (Big::from_u64(0xffffff / 123), (0xffffffu64 % 123) as u8));
+    assert_eq!(as_val(Big::from_u64(0x10000).div_rem_small(123)),
+               (Big::from_u64(0x10000 / 123), (0x10000u64 % 123) as u8));
+}
+
+#[test]
+fn test_div_rem() {
+    fn div_rem(n: u64, d: u64) -> (Big, Big) {
+        let mut q = Big::from_small(42);
+        let mut r = Big::from_small(42);
+        Big::from_u64(n).div_rem(&Big::from_u64(d), &mut q, &mut r);
+        (q, r)
+    }
+    assert_eq!(div_rem(1, 1), (Big::from_small(1), Big::from_small(0)));
+    assert_eq!(div_rem(4, 3), (Big::from_small(1), Big::from_small(1)));
+    assert_eq!(div_rem(1, 7), (Big::from_small(0), Big::from_small(1)));
+    assert_eq!(div_rem(45, 9), (Big::from_small(5), Big::from_small(0)));
+    assert_eq!(div_rem(103, 9), (Big::from_small(11), Big::from_small(4)));
+    assert_eq!(div_rem(123456, 77), (Big::from_u64(1603), Big::from_small(25)));
+    assert_eq!(div_rem(0xffff, 1), (Big::from_u64(0xffff), Big::from_small(0)));
+    assert_eq!(div_rem(0xeeee, 0xffff), (Big::from_small(0), Big::from_u64(0xeeee)));
+    assert_eq!(div_rem(2_000_000, 2), (Big::from_u64(1_000_000), Big::from_u64(0)));
+}
+
+#[test]
+fn test_is_zero() {
+    assert!(Big::from_small(0).is_zero());
+    assert!(!Big::from_small(3).is_zero());
+    assert!(!Big::from_u64(0x123).is_zero());
+    assert!(!Big::from_u64(0xffffff).sub(&Big::from_u64(0xfffffe)).is_zero());
+    assert!(Big::from_u64(0xffffff).sub(&Big::from_u64(0xffffff)).is_zero());
+}
+
+#[test]
+fn test_get_bit() {
+    let x = Big::from_small(0b1101);
+    assert_eq!(x.get_bit(0), 1);
+    assert_eq!(x.get_bit(1), 0);
+    assert_eq!(x.get_bit(2), 1);
+    assert_eq!(x.get_bit(3), 1);
+    let y = Big::from_u64(1 << 15);
+    assert_eq!(y.get_bit(14), 0);
+    assert_eq!(y.get_bit(15), 1);
+    assert_eq!(y.get_bit(16), 0);
+}
+
+#[test]
+#[should_panic]
+fn test_get_bit_out_of_range() {
+    Big::from_small(42).get_bit(24);
+}
+
+#[test]
+fn test_bit_length() {
+    assert_eq!(Big::from_small(0).bit_length(), 0);
+    assert_eq!(Big::from_small(1).bit_length(), 1);
+    assert_eq!(Big::from_small(5).bit_length(), 3);
+    assert_eq!(Big::from_small(0x18).bit_length(), 5);
+    assert_eq!(Big::from_u64(0x4073).bit_length(), 15);
+    assert_eq!(Big::from_u64(0xffffff).bit_length(), 24);
+}
+
+#[test]
+fn test_ord() {
+    assert!(Big::from_u64(0) < Big::from_u64(0xffffff));
+    assert!(Big::from_u64(0x102) < Big::from_u64(0x201));
+}
+
+#[test]
+fn test_fmt() {
+    assert_eq!(format!("{:?}", Big::from_u64(0)), "0x0");
+    assert_eq!(format!("{:?}", Big::from_u64(0x1)), "0x1");
+    assert_eq!(format!("{:?}", Big::from_u64(0x12)), "0x12");
+    assert_eq!(format!("{:?}", Big::from_u64(0x123)), "0x1_23");
+    assert_eq!(format!("{:?}", Big::from_u64(0x1234)), "0x12_34");
+    assert_eq!(format!("{:?}", Big::from_u64(0x12345)), "0x1_23_45");
+    assert_eq!(format!("{:?}", Big::from_u64(0x123456)), "0x12_34_56");
+}
+
diff --git a/src/libcore/tests/num/dec2flt/mod.rs b/src/libcore/tests/num/dec2flt/mod.rs
new file mode 100644
index 00000000000..5d546c643e7
--- /dev/null
+++ b/src/libcore/tests/num/dec2flt/mod.rs
@@ -0,0 +1,145 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(overflowing_literals)]
+
+use std::{i64, f32, f64};
+
+mod parse;
+mod rawfp;
+
+// Take a float literal, turn it into a string in various ways (that are all trusted
+// to be correct) and see if those strings are parsed back to the value of the literal.
+// Requires a *polymorphic literal*, i.e. one that can serve as f64 as well as f32.
+macro_rules! test_literal {
+    ($x: expr) => ({
+        let x32: f32 = $x;
+        let x64: f64 = $x;
+        let inputs = &[stringify!($x).into(), format!("{:?}", x64), format!("{:e}", x64)];
+        for input in inputs {
+            assert_eq!(input.parse(), Ok(x64));
+            assert_eq!(input.parse(), Ok(x32));
+            let neg_input = &format!("-{}", input);
+            assert_eq!(neg_input.parse(), Ok(-x64));
+            assert_eq!(neg_input.parse(), Ok(-x32));
+        }
+    })
+}
+
+#[test]
+fn ordinary() {
+    test_literal!(1.0);
+    test_literal!(3e-5);
+    test_literal!(0.1);
+    test_literal!(12345.);
+    test_literal!(0.9999999);
+    test_literal!(2.2250738585072014e-308);
+}
+
+#[test]
+fn special_code_paths() {
+    test_literal!(36893488147419103229.0); // 2^65 - 3, triggers half-to-even with even significand
+    test_literal!(101e-33); // Triggers the tricky underflow case in AlgorithmM (for f32)
+    test_literal!(1e23); // Triggers AlgorithmR
+    test_literal!(2075e23); // Triggers another path through AlgorithmR
+    test_literal!(8713e-23); // ... and yet another.
+}
+
+#[test]
+fn large() {
+    test_literal!(1e300);
+    test_literal!(123456789.34567e250);
+    test_literal!(943794359898089732078308743689303290943794359843568973207830874368930329.);
+}
+
+#[test]
+fn subnormals() {
+    test_literal!(5e-324);
+    test_literal!(91e-324);
+    test_literal!(1e-322);
+    test_literal!(13245643e-320);
+    test_literal!(2.22507385851e-308);
+    test_literal!(2.1e-308);
+    test_literal!(4.9406564584124654e-324);
+}
+
+#[test]
+fn infinity() {
+    test_literal!(1e400);
+    test_literal!(1e309);
+    test_literal!(2e308);
+    test_literal!(1.7976931348624e308);
+}
+
+#[test]
+fn zero() {
+    test_literal!(0.0);
+    test_literal!(1e-325);
+    test_literal!(1e-326);
+    test_literal!(1e-500);
+}
+
+#[test]
+fn fast_path_correct() {
+    // This number triggers the fast path and is handled incorrectly when compiling on
+    // x86 without SSE2 (i.e., using the x87 FPU stack).
+    test_literal!(1.448997445238699);
+}
+
+#[test]
+fn lonely_dot() {
+    assert!(".".parse::<f32>().is_err());
+    assert!(".".parse::<f64>().is_err());
+}
+
+#[test]
+fn lonely_sign() {
+    assert!("+".parse::<f32>().is_err());
+    assert!("-".parse::<f64>().is_err());
+}
+
+#[test]
+fn whitespace() {
+    assert!(" 1.0".parse::<f32>().is_err());
+    assert!("1.0 ".parse::<f64>().is_err());
+}
+
+#[test]
+fn nan() {
+    assert!("NaN".parse::<f32>().unwrap().is_nan());
+    assert!("NaN".parse::<f64>().unwrap().is_nan());
+}
+
+#[test]
+fn inf() {
+    assert_eq!("inf".parse(), Ok(f64::INFINITY));
+    assert_eq!("-inf".parse(), Ok(f64::NEG_INFINITY));
+    assert_eq!("inf".parse(), Ok(f32::INFINITY));
+    assert_eq!("-inf".parse(), Ok(f32::NEG_INFINITY));
+}
+
+#[test]
+fn massive_exponent() {
+    let max = i64::MAX;
+    assert_eq!(format!("1e{}000", max).parse(), Ok(f64::INFINITY));
+    assert_eq!(format!("1e-{}000", max).parse(), Ok(0.0));
+    assert_eq!(format!("1e{}000", max).parse(), Ok(f64::INFINITY));
+}
+
+#[test]
+fn borderline_overflow() {
+    let mut s = "0.".to_string();
+    for _ in 0..375 {
+        s.push('3');
+    }
+    // At the time of this writing, this returns Err(..), but this is a bug that should be fixed.
+    // It makes no sense to enshrine that in a test, the important part is that it doesn't panic.
+    let _ = s.parse::<f64>();
+}
diff --git a/src/libcore/tests/num/dec2flt/parse.rs b/src/libcore/tests/num/dec2flt/parse.rs
new file mode 100644
index 00000000000..09acf2bc517
--- /dev/null
+++ b/src/libcore/tests/num/dec2flt/parse.rs
@@ -0,0 +1,52 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::iter;
+use core::num::dec2flt::parse::{Decimal, parse_decimal};
+use core::num::dec2flt::parse::ParseResult::{Valid, Invalid};
+
+#[test]
+fn missing_pieces() {
+    let permutations = &[".e", "1e", "e4", "e", ".12e", "321.e", "32.12e+", "12.32e-"];
+    for &s in permutations {
+        assert_eq!(parse_decimal(s), Invalid);
+    }
+}
+
+#[test]
+fn invalid_chars() {
+    let invalid = "r,?<j";
+    let valid_strings = &["123", "666.", ".1", "5e1", "7e-3", "0.0e+1"];
+    for c in invalid.chars() {
+        for s in valid_strings {
+            for i in 0..s.len() {
+                let mut input = String::new();
+                input.push_str(s);
+                input.insert(i, c);
+                assert!(parse_decimal(&input) == Invalid, "did not reject invalid {:?}", input);
+            }
+        }
+    }
+}
+
+#[test]
+fn valid() {
+    assert_eq!(parse_decimal("123.456e789"), Valid(Decimal::new(b"123", b"456", 789)));
+    assert_eq!(parse_decimal("123.456e+789"), Valid(Decimal::new(b"123", b"456", 789)));
+    assert_eq!(parse_decimal("123.456e-789"), Valid(Decimal::new(b"123", b"456", -789)));
+    assert_eq!(parse_decimal(".050"), Valid(Decimal::new(b"", b"050", 0)));
+    assert_eq!(parse_decimal("999"), Valid(Decimal::new(b"999", b"", 0)));
+    assert_eq!(parse_decimal("1.e300"), Valid(Decimal::new(b"1", b"", 300)));
+    assert_eq!(parse_decimal(".1e300"), Valid(Decimal::new(b"", b"1", 300)));
+    assert_eq!(parse_decimal("101e-33"), Valid(Decimal::new(b"101", b"", -33)));
+    let zeros: String = iter::repeat('0').take(25).collect();
+    let s = format!("1.5e{}", zeros);
+    assert_eq!(parse_decimal(&s), Valid(Decimal::new(b"1", b"5", 0)));
+}
diff --git a/src/libcore/tests/num/dec2flt/rawfp.rs b/src/libcore/tests/num/dec2flt/rawfp.rs
new file mode 100644
index 00000000000..1a3533317da
--- /dev/null
+++ b/src/libcore/tests/num/dec2flt/rawfp.rs
@@ -0,0 +1,154 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::f64;
+use std::mem;
+use core::num::diy_float::Fp;
+use core::num::dec2flt::rawfp::{fp_to_float, prev_float, next_float, round_normal};
+
+fn integer_decode(f: f64) -> (u64, i16, i8) {
+    let bits: u64 = unsafe { mem::transmute(f) };
+    let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
+    let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
+    let mantissa = if exponent == 0 {
+        (bits & 0xfffffffffffff) << 1
+    } else {
+        (bits & 0xfffffffffffff) | 0x10000000000000
+    };
+    // Exponent bias + mantissa shift
+    exponent -= 1023 + 52;
+    (mantissa, exponent, sign)
+}
+
+#[test]
+fn fp_to_float_half_to_even() {
+    fn is_normalized(sig: u64) -> bool {
+        // intentionally written without {min,max}_sig() as a sanity check
+        sig >> 52 == 1 && sig >> 53 == 0
+    }
+
+    fn conv(sig: u64) -> u64 {
+        // The significands are perfectly in range, so the exponent should not matter
+        let (m1, e1, _) = integer_decode(fp_to_float::<f64>(Fp { f: sig, e: 0 }));
+        assert_eq!(e1, 0 + 64 - 53);
+        let (m2, e2, _) = integer_decode(fp_to_float::<f64>(Fp { f: sig, e: 55 }));
+        assert_eq!(e2, 55 + 64 - 53);
+        assert_eq!(m2, m1);
+        let (m3, e3, _) = integer_decode(fp_to_float::<f64>(Fp { f: sig, e: -78 }));
+        assert_eq!(e3, -78 + 64 - 53);
+        assert_eq!(m3, m2);
+        m3
+    }
+
+    let odd = 0x1F_EDCB_A012_345F;
+    let even = odd - 1;
+    assert!(is_normalized(odd));
+    assert!(is_normalized(even));
+    assert_eq!(conv(odd << 11), odd);
+    assert_eq!(conv(even << 11), even);
+    assert_eq!(conv(odd << 11 | 1 << 10), odd + 1);
+    assert_eq!(conv(even << 11 | 1 << 10), even);
+    assert_eq!(conv(even << 11 | 1 << 10 | 1), even + 1);
+    assert_eq!(conv(odd << 11 | 1 << 9), odd);
+    assert_eq!(conv(even << 11 | 1 << 9), even);
+    assert_eq!(conv(odd << 11 | 0x7FF), odd + 1);
+    assert_eq!(conv(even << 11 | 0x7FF), even + 1);
+    assert_eq!(conv(odd << 11 | 0x3FF), odd);
+    assert_eq!(conv(even << 11 | 0x3FF), even);
+}
+
+#[test]
+fn integers_to_f64() {
+    assert_eq!(fp_to_float::<f64>(Fp { f: 1, e: 0 }), 1.0);
+    assert_eq!(fp_to_float::<f64>(Fp { f: 42, e: 7 }), (42 << 7) as f64);
+    assert_eq!(fp_to_float::<f64>(Fp { f: 1 << 20, e: 30 }), (1u64 << 50) as f64);
+    assert_eq!(fp_to_float::<f64>(Fp { f: 4, e: -3 }), 0.5);
+}
+
+const SOME_FLOATS: [f64; 9] =
+    [0.1f64, 33.568, 42.1e-5, 777.0e9, 1.1111, 0.347997,
+     9843579834.35892, 12456.0e-150, 54389573.0e-150];
+
+
+#[test]
+fn human_f64_roundtrip() {
+    for &x in &SOME_FLOATS {
+        let (f, e, _) = integer_decode(x);
+        let fp = Fp { f: f, e: e};
+        assert_eq!(fp_to_float::<f64>(fp), x);
+    }
+}
+
+#[test]
+fn rounding_overflow() {
+    let x = Fp { f: 0xFF_FF_FF_FF_FF_FF_FF_00u64, e: 42 };
+    let rounded = round_normal::<f64>(x);
+    let adjusted_k = x.e + 64 - 53;
+    assert_eq!(rounded.sig, 1 << 52);
+    assert_eq!(rounded.k, adjusted_k + 1);
+}
+
+#[test]
+fn prev_float_monotonic() {
+    let mut x = 1.0;
+    for _ in 0..100 {
+        let x1 = prev_float(x);
+        assert!(x1 < x);
+        assert!(x - x1 < 1e-15);
+        x = x1;
+    }
+}
+
+const MIN_SUBNORMAL: f64 = 5e-324;
+
+#[test]
+fn next_float_zero() {
+    let tiny = next_float(0.0);
+    assert_eq!(tiny, MIN_SUBNORMAL);
+    assert!(tiny != 0.0);
+}
+
+#[test]
+fn next_float_subnormal() {
+    let second = next_float(MIN_SUBNORMAL);
+    // For subnormals, MIN_SUBNORMAL is the ULP
+    assert!(second != MIN_SUBNORMAL);
+    assert!(second > 0.0);
+    assert_eq!(second - MIN_SUBNORMAL, MIN_SUBNORMAL);
+}
+
+#[test]
+fn next_float_inf() {
+    assert_eq!(next_float(f64::MAX), f64::INFINITY);
+    assert_eq!(next_float(f64::INFINITY), f64::INFINITY);
+}
+
+#[test]
+fn next_prev_identity() {
+    for &x in &SOME_FLOATS {
+        assert_eq!(prev_float(next_float(x)), x);
+        assert_eq!(prev_float(prev_float(next_float(next_float(x)))), x);
+        assert_eq!(next_float(prev_float(x)), x);
+        assert_eq!(next_float(next_float(prev_float(prev_float(x)))), x);
+    }
+}
+
+#[test]
+fn next_float_monotonic() {
+    let mut x = 0.49999999999999;
+    assert!(x < 0.5);
+    for _ in 0..200 {
+        let x1 = next_float(x);
+        assert!(x1 > x);
+        assert!(x1 - x < 1e-15, "next_float_monotonic: delta = {:?}", x1 - x);
+        x = x1;
+    }
+    assert!(x > 0.5);
+}
diff --git a/src/libcore/tests/num/flt2dec/estimator.rs b/src/libcore/tests/num/flt2dec/estimator.rs
new file mode 100644
index 00000000000..0bca616ea9a
--- /dev/null
+++ b/src/libcore/tests/num/flt2dec/estimator.rs
@@ -0,0 +1,65 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// FIXME https://github.com/kripken/emscripten/issues/4563
+// NB we have to actually not compile this test to avoid
+// an undefined symbol error
+#![cfg(not(target_os = "emscripten"))]
+
+use core::num::flt2dec::estimator::*;
+
+#[test]
+fn test_estimate_scaling_factor() {
+    macro_rules! assert_almost_eq {
+        ($actual:expr, $expected:expr) => ({
+            let actual = $actual;
+            let expected = $expected;
+            println!("{} - {} = {} - {} = {}", stringify!($expected), stringify!($actual),
+                     expected, actual, expected - actual);
+            assert!(expected == actual || expected == actual + 1,
+                    "expected {}, actual {}", expected, actual);
+        })
+    }
+
+    assert_almost_eq!(estimate_scaling_factor(1, 0), 0);
+    assert_almost_eq!(estimate_scaling_factor(2, 0), 1);
+    assert_almost_eq!(estimate_scaling_factor(10, 0), 1);
+    assert_almost_eq!(estimate_scaling_factor(11, 0), 2);
+    assert_almost_eq!(estimate_scaling_factor(100, 0), 2);
+    assert_almost_eq!(estimate_scaling_factor(101, 0), 3);
+    assert_almost_eq!(estimate_scaling_factor(10000000000000000000, 0), 19);
+    assert_almost_eq!(estimate_scaling_factor(10000000000000000001, 0), 20);
+
+    // 1/2^20 = 0.00000095367...
+    assert_almost_eq!(estimate_scaling_factor(1 * 1048576 / 1000000, -20), -6);
+    assert_almost_eq!(estimate_scaling_factor(1 * 1048576 / 1000000 + 1, -20), -5);
+    assert_almost_eq!(estimate_scaling_factor(10 * 1048576 / 1000000, -20), -5);
+    assert_almost_eq!(estimate_scaling_factor(10 * 1048576 / 1000000 + 1, -20), -4);
+    assert_almost_eq!(estimate_scaling_factor(100 * 1048576 / 1000000, -20), -4);
+    assert_almost_eq!(estimate_scaling_factor(100 * 1048576 / 1000000 + 1, -20), -3);
+    assert_almost_eq!(estimate_scaling_factor(1048575, -20), 0);
+    assert_almost_eq!(estimate_scaling_factor(1048576, -20), 0);
+    assert_almost_eq!(estimate_scaling_factor(1048577, -20), 1);
+    assert_almost_eq!(estimate_scaling_factor(10485759999999999999, -20), 13);
+    assert_almost_eq!(estimate_scaling_factor(10485760000000000000, -20), 13);
+    assert_almost_eq!(estimate_scaling_factor(10485760000000000001, -20), 14);
+
+    // extreme values:
+    // 2^-1074 = 4.94065... * 10^-324
+    // (2^53-1) * 2^971 = 1.79763... * 10^308
+    assert_almost_eq!(estimate_scaling_factor(1, -1074), -323);
+    assert_almost_eq!(estimate_scaling_factor(0x1fffffffffffff, 971), 309);
+
+    for i in -1074..972 {
+        let expected = super::ldexp_f64(1.0, i).log10().ceil();
+        assert_almost_eq!(estimate_scaling_factor(1, i as i16), expected as i16);
+    }
+}
+
diff --git a/src/libcore/tests/num/flt2dec/mod.rs b/src/libcore/tests/num/flt2dec/mod.rs
new file mode 100644
index 00000000000..0f4d19e7092
--- /dev/null
+++ b/src/libcore/tests/num/flt2dec/mod.rs
@@ -0,0 +1,1201 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::prelude::v1::*;
+use std::{str, mem, i16, f32, f64, fmt};
+use std::__rand as rand;
+use rand::{Rand, XorShiftRng};
+use rand::distributions::{IndependentSample, Range};
+
+use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded};
+use core::num::flt2dec::{MAX_SIG_DIGITS, round_up, Part, Formatted, Sign};
+use core::num::flt2dec::{to_shortest_str, to_shortest_exp_str,
+                         to_exact_exp_str, to_exact_fixed_str};
+
+pub use test::Bencher;
+
+mod estimator;
+mod strategy {
+    mod dragon;
+    mod grisu;
+}
+
+pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
+    match decode(v).1 {
+        FullDecoded::Finite(decoded) => decoded,
+        full_decoded => panic!("expected finite, got {:?} instead", full_decoded)
+    }
+}
+
+macro_rules! check_shortest {
+    ($f:ident($v:expr) => $buf:expr, $exp:expr) => (
+        check_shortest!($f($v) => $buf, $exp;
+                        "shortest mismatch for v={v}: actual {actual:?}, expected {expected:?}",
+                        v = stringify!($v))
+    );
+
+    ($f:ident{$($k:ident: $v:expr),+} => $buf:expr, $exp:expr) => (
+        check_shortest!($f{$($k: $v),+} => $buf, $exp;
+                        "shortest mismatch for {v:?}: actual {actual:?}, expected {expected:?}",
+                        v = Decoded { $($k: $v),+ })
+    );
+
+    ($f:ident($v:expr) => $buf:expr, $exp:expr; $fmt:expr, $($key:ident = $val:expr),*) => ({
+        let mut buf = [b'_'; MAX_SIG_DIGITS];
+        let (len, k) = $f(&decode_finite($v), &mut buf);
+        assert!((&buf[..len], k) == ($buf, $exp),
+                $fmt, actual = (str::from_utf8(&buf[..len]).unwrap(), k),
+                      expected = (str::from_utf8($buf).unwrap(), $exp),
+                      $($key = $val),*);
+    });
+
+    ($f:ident{$($k:ident: $v:expr),+} => $buf:expr, $exp:expr;
+                                         $fmt:expr, $($key:ident = $val:expr),*) => ({
+        let mut buf = [b'_'; MAX_SIG_DIGITS];
+        let (len, k) = $f(&Decoded { $($k: $v),+ }, &mut buf);
+        assert!((&buf[..len], k) == ($buf, $exp),
+                $fmt, actual = (str::from_utf8(&buf[..len]).unwrap(), k),
+                      expected = (str::from_utf8($buf).unwrap(), $exp),
+                      $($key = $val),*);
+    })
+}
+
+macro_rules! try_exact {
+    ($f:ident($decoded:expr) => $buf:expr, $expected:expr, $expectedk:expr;
+                                $fmt:expr, $($key:ident = $val:expr),*) => ({
+        let (len, k) = $f($decoded, &mut $buf[..$expected.len()], i16::MIN);
+        assert!((&$buf[..len], k) == ($expected, $expectedk),
+                $fmt, actual = (str::from_utf8(&$buf[..len]).unwrap(), k),
+                      expected = (str::from_utf8($expected).unwrap(), $expectedk),
+                      $($key = $val),*);
+    })
+}
+
+macro_rules! try_fixed {
+    ($f:ident($decoded:expr) => $buf:expr, $request:expr, $expected:expr, $expectedk:expr;
+                                $fmt:expr, $($key:ident = $val:expr),*) => ({
+        let (len, k) = $f($decoded, &mut $buf[..], $request);
+        assert!((&$buf[..len], k) == ($expected, $expectedk),
+                $fmt, actual = (str::from_utf8(&$buf[..len]).unwrap(), k),
+                      expected = (str::from_utf8($expected).unwrap(), $expectedk),
+                      $($key = $val),*);
+    })
+}
+
+fn ldexp_f32(a: f32, b: i32) -> f32 {
+    ldexp_f64(a as f64, b) as f32
+}
+
+fn ldexp_f64(a: f64, b: i32) -> f64 {
+    extern {
+        fn ldexp(x: f64, n: i32) -> f64;
+    }
+    unsafe { ldexp(a, b) }
+}
+
+fn check_exact<F, T>(mut f: F, v: T, vstr: &str, expected: &[u8], expectedk: i16)
+        where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+    // use a large enough buffer
+    let mut buf = [b'_'; 1024];
+    let mut expected_ = [b'_'; 1024];
+
+    let decoded = decode_finite(v);
+    let cut = expected.iter().position(|&c| c == b' ');
+
+    // check significant digits
+    for i in 1..cut.unwrap_or(expected.len() - 1) {
+        expected_[..i].copy_from_slice(&expected[..i]);
+        let mut expectedk_ = expectedk;
+        if expected[i] >= b'5' {
+            // check if this is a rounding-to-even case.
+            // we avoid rounding ...x5000... (with infinite zeroes) to ...(x+1) when x is even.
+            if !(i+1 < expected.len() && expected[i-1] & 1 == 0 &&
+                                         expected[i] == b'5' &&
+                                         expected[i+1] == b' ') {
+                // if this returns true, expected_[..i] is all `9`s and being rounded up.
+                // we should always return `100..00` (`i` digits) instead, since that's
+                // what we can came up with `i` digits anyway. `round_up` assumes that
+                // the adjustment to the length is done by caller, which we simply ignore.
+                if let Some(_) = round_up(&mut expected_, i) { expectedk_ += 1; }
+            }
+        }
+
+        try_exact!(f(&decoded) => &mut buf, &expected_[..i], expectedk_;
+                   "exact sigdigit mismatch for v={v}, i={i}: \
+                    actual {actual:?}, expected {expected:?}",
+                   v = vstr, i = i);
+        try_fixed!(f(&decoded) => &mut buf, expectedk_ - i as i16, &expected_[..i], expectedk_;
+                   "fixed sigdigit mismatch for v={v}, i={i}: \
+                    actual {actual:?}, expected {expected:?}",
+                   v = vstr, i = i);
+    }
+
+    // check exact rounding for zero- and negative-width cases
+    let start;
+    if expected[0] >= b'5' {
+        try_fixed!(f(&decoded) => &mut buf, expectedk, b"1", expectedk + 1;
+                   "zero-width rounding-up mismatch for v={v}: \
+                    actual {actual:?}, expected {expected:?}",
+                   v = vstr);
+        start = 1;
+    } else {
+        start = 0;
+    }
+    for i in start..-10 {
+        try_fixed!(f(&decoded) => &mut buf, expectedk - i, b"", expectedk;
+                   "rounding-down mismatch for v={v}, i={i}: \
+                    actual {actual:?}, expected {expected:?}",
+                   v = vstr, i = -i);
+    }
+
+    // check infinite zero digits
+    if let Some(cut) = cut {
+        for i in cut..expected.len()-1 {
+            expected_[..cut].copy_from_slice(&expected[..cut]);
+            for c in &mut expected_[cut..i] { *c = b'0'; }
+
+            try_exact!(f(&decoded) => &mut buf, &expected_[..i], expectedk;
+                       "exact infzero mismatch for v={v}, i={i}: \
+                        actual {actual:?}, expected {expected:?}",
+                       v = vstr, i = i);
+            try_fixed!(f(&decoded) => &mut buf, expectedk - i as i16, &expected_[..i], expectedk;
+                       "fixed infzero mismatch for v={v}, i={i}: \
+                        actual {actual:?}, expected {expected:?}",
+                       v = vstr, i = i);
+        }
+    }
+}
+
+trait TestableFloat : DecodableFloat + fmt::Display {
+    /// Returns `x * 2^exp`. Almost same to `std::{f32,f64}::ldexp`.
+    /// This is used for testing.
+    fn ldexpi(f: i64, exp: isize) -> Self;
+}
+
+impl TestableFloat for f32 {
+    fn ldexpi(f: i64, exp: isize) -> Self { f as Self * (exp as Self).exp2() }
+}
+
+impl TestableFloat for f64 {
+    fn ldexpi(f: i64, exp: isize) -> Self { f as Self * (exp as Self).exp2() }
+}
+
+fn check_exact_one<F, T>(mut f: F, x: i64, e: isize, tstr: &str, expected: &[u8], expectedk: i16)
+        where T: TestableFloat,
+              F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+    // use a large enough buffer
+    let mut buf = [b'_'; 1024];
+    let v: T = TestableFloat::ldexpi(x, e);
+    let decoded = decode_finite(v);
+
+    try_exact!(f(&decoded) => &mut buf, &expected, expectedk;
+               "exact mismatch for v={x}p{e}{t}: actual {actual:?}, expected {expected:?}",
+               x = x, e = e, t = tstr);
+    try_fixed!(f(&decoded) => &mut buf, expectedk - expected.len() as i16, &expected, expectedk;
+               "fixed mismatch for v={x}p{e}{t}: actual {actual:?}, expected {expected:?}",
+               x = x, e = e, t = tstr);
+}
+
+macro_rules! check_exact {
+    ($f:ident($v:expr) => $buf:expr, $exp:expr) => (
+        check_exact(|d,b,k| $f(d,b,k), $v, stringify!($v), $buf, $exp)
+    )
+}
+
+macro_rules! check_exact_one {
+    ($f:ident($x:expr, $e:expr; $t:ty) => $buf:expr, $exp:expr) => (
+        check_exact_one::<_, $t>(|d,b,k| $f(d,b,k), $x, $e, stringify!($t), $buf, $exp)
+    )
+}
+
+// in the following comments, three numbers are spaced by 1 ulp apart,
+// and the second one is being formatted.
+//
+// some tests are derived from [1].
+//
+// [1] Vern Paxson, A Program for Testing IEEE Decimal-Binary Conversion
+//     ftp://ftp.ee.lbl.gov/testbase-report.ps.Z
+
+pub fn f32_shortest_sanity_test<F>(mut f: F) where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+    // 0.0999999940395355224609375
+    // 0.100000001490116119384765625
+    // 0.10000000894069671630859375
+    check_shortest!(f(0.1f32) => b"1", 0);
+
+    // 0.333333313465118408203125
+    // 0.3333333432674407958984375 (1/3 in the default rounding)
+    // 0.33333337306976318359375
+    check_shortest!(f(1.0f32/3.0) => b"33333334", 0);
+
+    // 10^1 * 0.31415917873382568359375
+    // 10^1 * 0.31415920257568359375
+    // 10^1 * 0.31415922641754150390625
+    check_shortest!(f(3.141592f32) => b"3141592", 1);
+
+    // 10^18 * 0.31415916243714048
+    // 10^18 * 0.314159196796878848
+    // 10^18 * 0.314159231156617216
+    check_shortest!(f(3.141592e17f32) => b"3141592", 18);
+
+    // regression test for decoders
+    // 10^8 * 0.3355443
+    // 10^8 * 0.33554432
+    // 10^8 * 0.33554436
+    check_shortest!(f(ldexp_f32(1.0, 25)) => b"33554432", 8);
+
+    // 10^39 * 0.340282326356119256160033759537265639424
+    // 10^39 * 0.34028234663852885981170418348451692544
+    // 10^39 * 0.340282366920938463463374607431768211456
+    check_shortest!(f(f32::MAX) => b"34028235", 39);
+
+    // 10^-37 * 0.1175494210692441075487029444849287348827...
+    // 10^-37 * 0.1175494350822287507968736537222245677818...
+    // 10^-37 * 0.1175494490952133940450443629595204006810...
+    check_shortest!(f(f32::MIN_POSITIVE) => b"11754944", -37);
+
+    // 10^-44 * 0
+    // 10^-44 * 0.1401298464324817070923729583289916131280...
+    // 10^-44 * 0.2802596928649634141847459166579832262560...
+    let minf32 = ldexp_f32(1.0, -149);
+    check_shortest!(f(minf32) => b"1", -44);
+}
+
+pub fn f32_exact_sanity_test<F>(mut f: F)
+        where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+    let minf32 = ldexp_f32(1.0, -149);
+
+    check_exact!(f(0.1f32)            => b"100000001490116119384765625             ", 0);
+    check_exact!(f(0.5f32)            => b"5                                       ", 0);
+    check_exact!(f(1.0f32/3.0)        => b"3333333432674407958984375               ", 0);
+    check_exact!(f(3.141592f32)       => b"31415920257568359375                    ", 1);
+    check_exact!(f(3.141592e17f32)    => b"314159196796878848                      ", 18);
+    check_exact!(f(f32::MAX)          => b"34028234663852885981170418348451692544  ", 39);
+    check_exact!(f(f32::MIN_POSITIVE) => b"1175494350822287507968736537222245677818", -37);
+    check_exact!(f(minf32)            => b"1401298464324817070923729583289916131280", -44);
+
+    // [1], Table 16: Stress Inputs for Converting 24-bit Binary to Decimal, < 1/2 ULP
+    check_exact_one!(f(12676506, -102; f32) => b"2",            -23);
+    check_exact_one!(f(12676506, -103; f32) => b"12",           -23);
+    check_exact_one!(f(15445013,   86; f32) => b"119",           34);
+    check_exact_one!(f(13734123, -138; f32) => b"3941",         -34);
+    check_exact_one!(f(12428269, -130; f32) => b"91308",        -32);
+    check_exact_one!(f(15334037, -146; f32) => b"171900",       -36);
+    check_exact_one!(f(11518287,  -41; f32) => b"5237910",       -5);
+    check_exact_one!(f(12584953, -145; f32) => b"28216440",     -36);
+    check_exact_one!(f(15961084, -125; f32) => b"375243281",    -30);
+    check_exact_one!(f(14915817, -146; f32) => b"1672120916",   -36);
+    check_exact_one!(f(10845484, -102; f32) => b"21388945814",  -23);
+    check_exact_one!(f(16431059,  -61; f32) => b"712583594561", -11);
+
+    // [1], Table 17: Stress Inputs for Converting 24-bit Binary to Decimal, > 1/2 ULP
+    check_exact_one!(f(16093626,   69; f32) => b"1",             29);
+    check_exact_one!(f( 9983778,   25; f32) => b"34",            15);
+    check_exact_one!(f(12745034,  104; f32) => b"259",           39);
+    check_exact_one!(f(12706553,   72; f32) => b"6001",          29);
+    check_exact_one!(f(11005028,   45; f32) => b"38721",         21);
+    check_exact_one!(f(15059547,   71; f32) => b"355584",        29);
+    check_exact_one!(f(16015691,  -99; f32) => b"2526831",      -22);
+    check_exact_one!(f( 8667859,   56; f32) => b"62458507",      24);
+    check_exact_one!(f(14855922,  -82; f32) => b"307213267",    -17);
+    check_exact_one!(f(14855922,  -83; f32) => b"1536066333",   -17);
+    check_exact_one!(f(10144164, -110; f32) => b"78147796834",  -26);
+    check_exact_one!(f(13248074,   95; f32) => b"524810279937",  36);
+}
+
+pub fn f64_shortest_sanity_test<F>(mut f: F) where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+    // 0.0999999999999999777955395074968691915273...
+    // 0.1000000000000000055511151231257827021181...
+    // 0.1000000000000000333066907387546962127089...
+    check_shortest!(f(0.1f64) => b"1", 0);
+
+    // this example is explicitly mentioned in the paper.
+    // 10^3 * 0.0999999999999999857891452847979962825775...
+    // 10^3 * 0.1 (exact)
+    // 10^3 * 0.1000000000000000142108547152020037174224...
+    check_shortest!(f(100.0f64) => b"1", 3);
+
+    // 0.3333333333333332593184650249895639717578...
+    // 0.3333333333333333148296162562473909929394... (1/3 in the default rounding)
+    // 0.3333333333333333703407674875052180141210...
+    check_shortest!(f(1.0f64/3.0) => b"3333333333333333", 0);
+
+    // explicit test case for equally closest representations.
+    // Dragon has its own tie-breaking rule; Grisu should fall back.
+    // 10^1 * 0.1000007629394531027955395074968691915273...
+    // 10^1 * 0.100000762939453125 (exact)
+    // 10^1 * 0.1000007629394531472044604925031308084726...
+    check_shortest!(f(1.00000762939453125f64) => b"10000076293945313", 1);
+
+    // 10^1 * 0.3141591999999999718085064159822650253772...
+    // 10^1 * 0.3141592000000000162174274009885266423225...
+    // 10^1 * 0.3141592000000000606263483859947882592678...
+    check_shortest!(f(3.141592f64) => b"3141592", 1);
+
+    // 10^18 * 0.314159199999999936
+    // 10^18 * 0.3141592 (exact)
+    // 10^18 * 0.314159200000000064
+    check_shortest!(f(3.141592e17f64) => b"3141592", 18);
+
+    // regression test for decoders
+    // 10^20 * 0.18446744073709549568
+    // 10^20 * 0.18446744073709551616
+    // 10^20 * 0.18446744073709555712
+    check_shortest!(f(ldexp_f64(1.0, 64)) => b"18446744073709552", 20);
+
+    // pathological case: high = 10^23 (exact). tie breaking should always prefer that.
+    // 10^24 * 0.099999999999999974834176
+    // 10^24 * 0.099999999999999991611392
+    // 10^24 * 0.100000000000000008388608
+    check_shortest!(f(1.0e23f64) => b"1", 24);
+
+    // 10^309 * 0.1797693134862315508561243283845062402343...
+    // 10^309 * 0.1797693134862315708145274237317043567980...
+    // 10^309 * 0.1797693134862315907729305190789024733617...
+    check_shortest!(f(f64::MAX) => b"17976931348623157", 309);
+
+    // 10^-307 * 0.2225073858507200889024586876085859887650...
+    // 10^-307 * 0.2225073858507201383090232717332404064219...
+    // 10^-307 * 0.2225073858507201877155878558578948240788...
+    check_shortest!(f(f64::MIN_POSITIVE) => b"22250738585072014", -307);
+
+    // 10^-323 * 0
+    // 10^-323 * 0.4940656458412465441765687928682213723650...
+    // 10^-323 * 0.9881312916824930883531375857364427447301...
+    let minf64 = ldexp_f64(1.0, -1074);
+    check_shortest!(f(minf64) => b"5", -323);
+}
+
+pub fn f64_exact_sanity_test<F>(mut f: F)
+        where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+    let minf64 = ldexp_f64(1.0, -1074);
+
+    check_exact!(f(0.1f64)            => b"1000000000000000055511151231257827021181", 0);
+    check_exact!(f(0.45f64)           => b"4500000000000000111022302462515654042363", 0);
+    check_exact!(f(0.5f64)            => b"5                                       ", 0);
+    check_exact!(f(0.95f64)           => b"9499999999999999555910790149937383830547", 0);
+    check_exact!(f(100.0f64)          => b"1                                       ", 3);
+    check_exact!(f(999.5f64)          => b"9995000000000000000000000000000000000000", 3);
+    check_exact!(f(1.0f64/3.0)        => b"3333333333333333148296162562473909929394", 0);
+    check_exact!(f(3.141592f64)       => b"3141592000000000162174274009885266423225", 1);
+    check_exact!(f(3.141592e17f64)    => b"3141592                                 ", 18);
+    check_exact!(f(1.0e23f64)         => b"99999999999999991611392                 ", 23);
+    check_exact!(f(f64::MAX)          => b"1797693134862315708145274237317043567980", 309);
+    check_exact!(f(f64::MIN_POSITIVE) => b"2225073858507201383090232717332404064219", -307);
+    check_exact!(f(minf64)            => b"4940656458412465441765687928682213723650\
+                                           5980261432476442558568250067550727020875\
+                                           1865299836361635992379796564695445717730\
+                                           9266567103559397963987747960107818781263\
+                                           0071319031140452784581716784898210368871\
+                                           8636056998730723050006387409153564984387\
+                                           3124733972731696151400317153853980741262\
+                                           3856559117102665855668676818703956031062\
+                                           4931945271591492455329305456544401127480\
+                                           1297099995419319894090804165633245247571\
+                                           4786901472678015935523861155013480352649\
+                                           3472019379026810710749170333222684475333\
+                                           5720832431936092382893458368060106011506\
+                                           1698097530783422773183292479049825247307\
+                                           7637592724787465608477820373446969953364\
+                                           7017972677717585125660551199131504891101\
+                                           4510378627381672509558373897335989936648\
+                                           0994116420570263709027924276754456522908\
+                                           7538682506419718265533447265625         ", -323);
+
+    // [1], Table 3: Stress Inputs for Converting 53-bit Binary to Decimal, < 1/2 ULP
+    check_exact_one!(f(8511030020275656,  -342; f64) => b"9",                       -87);
+    check_exact_one!(f(5201988407066741,  -824; f64) => b"46",                     -232);
+    check_exact_one!(f(6406892948269899,   237; f64) => b"141",                      88);
+    check_exact_one!(f(8431154198732492,    72; f64) => b"3981",                     38);
+    check_exact_one!(f(6475049196144587,    99; f64) => b"41040",                    46);
+    check_exact_one!(f(8274307542972842,   726; f64) => b"292084",                  235);
+    check_exact_one!(f(5381065484265332,  -456; f64) => b"2891946",                -121);
+    check_exact_one!(f(6761728585499734, -1057; f64) => b"43787718",               -302);
+    check_exact_one!(f(7976538478610756,   376; f64) => b"122770163",               130);
+    check_exact_one!(f(5982403858958067,   377; f64) => b"1841552452",              130);
+    check_exact_one!(f(5536995190630837,    93; f64) => b"54835744350",              44);
+    check_exact_one!(f(7225450889282194,   710; f64) => b"389190181146",            230);
+    check_exact_one!(f(7225450889282194,   709; f64) => b"1945950905732",           230);
+    check_exact_one!(f(8703372741147379,   117; f64) => b"14460958381605",           52);
+    check_exact_one!(f(8944262675275217, -1001; f64) => b"417367747458531",        -285);
+    check_exact_one!(f(7459803696087692,  -707; f64) => b"1107950772878888",       -196);
+    check_exact_one!(f(6080469016670379,  -381; f64) => b"12345501366327440",       -98);
+    check_exact_one!(f(8385515147034757,   721; f64) => b"925031711960365024",      233);
+    check_exact_one!(f(7514216811389786,  -828; f64) => b"4198047150284889840",    -233);
+    check_exact_one!(f(8397297803260511,  -345; f64) => b"11716315319786511046",    -87);
+    check_exact_one!(f(6733459239310543,   202; f64) => b"432810072844612493629",    77);
+    check_exact_one!(f(8091450587292794,  -473; f64) => b"3317710118160031081518", -126);
+
+    // [1], Table 4: Stress Inputs for Converting 53-bit Binary to Decimal, > 1/2 ULP
+    check_exact_one!(f(6567258882077402,   952; f64) => b"3",                       303);
+    check_exact_one!(f(6712731423444934,   535; f64) => b"76",                      177);
+    check_exact_one!(f(6712731423444934,   534; f64) => b"378",                     177);
+    check_exact_one!(f(5298405411573037,  -957; f64) => b"4350",                   -272);
+    check_exact_one!(f(5137311167659507,  -144; f64) => b"23037",                   -27);
+    check_exact_one!(f(6722280709661868,   363; f64) => b"126301",                  126);
+    check_exact_one!(f(5344436398034927,  -169; f64) => b"7142211",                 -35);
+    check_exact_one!(f(8369123604277281,  -853; f64) => b"13934574",               -240);
+    check_exact_one!(f(8995822108487663,  -780; f64) => b"141463449",              -218);
+    check_exact_one!(f(8942832835564782,  -383; f64) => b"4539277920",              -99);
+    check_exact_one!(f(8942832835564782,  -384; f64) => b"22696389598",             -99);
+    check_exact_one!(f(8942832835564782,  -385; f64) => b"113481947988",            -99);
+    check_exact_one!(f(6965949469487146,  -249; f64) => b"7700366561890",           -59);
+    check_exact_one!(f(6965949469487146,  -250; f64) => b"38501832809448",          -59);
+    check_exact_one!(f(6965949469487146,  -251; f64) => b"192509164047238",         -59);
+    check_exact_one!(f(7487252720986826,   548; f64) => b"6898586531774201",        181);
+    check_exact_one!(f(5592117679628511,   164; f64) => b"13076622631878654",        66);
+    check_exact_one!(f(8887055249355788,   665; f64) => b"136052020756121240",      217);
+    check_exact_one!(f(6994187472632449,   690; f64) => b"3592810217475959676",     224);
+    check_exact_one!(f(8797576579012143,   588; f64) => b"89125197712484551899",    193);
+    check_exact_one!(f(7363326733505337,   272; f64) => b"558769757362301140950",    98);
+    check_exact_one!(f(8549497411294502,  -448; f64) => b"1176257830728540379990", -118);
+}
+
+pub fn more_shortest_sanity_test<F>(mut f: F) where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+    check_shortest!(f{mant: 99_999_999_999_999_999, minus: 1, plus: 1,
+                      exp: 0, inclusive: true} => b"1", 18);
+    check_shortest!(f{mant: 99_999_999_999_999_999, minus: 1, plus: 1,
+                      exp: 0, inclusive: false} => b"99999999999999999", 17);
+}
+
+fn iterate<F, G, V>(func: &str, k: usize, n: usize, mut f: F, mut g: G, mut v: V) -> (usize, usize)
+        where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
+              G: FnMut(&Decoded, &mut [u8]) -> (usize, i16),
+              V: FnMut(usize) -> Decoded {
+    assert!(k <= 1024);
+
+    let mut npassed = 0; // f(x) = Some(g(x))
+    let mut nignored = 0; // f(x) = None
+
+    for i in 0..n {
+        if (i & 0xfffff) == 0 {
+            println!("in progress, {:x}/{:x} (ignored={} passed={} failed={})",
+                     i, n, nignored, npassed, i - nignored - npassed);
+        }
+
+        let decoded = v(i);
+        let mut buf1 = [0; 1024];
+        if let Some((len1, e1)) = f(&decoded, &mut buf1[..k]) {
+            let mut buf2 = [0; 1024];
+            let (len2, e2) = g(&decoded, &mut buf2[..k]);
+            if e1 == e2 && &buf1[..len1] == &buf2[..len2] {
+                npassed += 1;
+            } else {
+                println!("equivalence test failed, {:x}/{:x}: {:?} f(i)={}e{} g(i)={}e{}",
+                         i, n, decoded, str::from_utf8(&buf1[..len1]).unwrap(), e1,
+                                        str::from_utf8(&buf2[..len2]).unwrap(), e2);
+            }
+        } else {
+            nignored += 1;
+        }
+    }
+    println!("{}({}): done, ignored={} passed={} failed={}",
+             func, k, nignored, npassed, n - nignored - npassed);
+    assert!(nignored + npassed == n,
+            "{}({}): {} out of {} values returns an incorrect value!",
+            func, k, n - nignored - npassed, n);
+    (npassed, nignored)
+}
+
+pub fn f32_random_equivalence_test<F, G>(f: F, g: G, k: usize, n: usize)
+        where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
+              G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+    let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng());
+    let f32_range = Range::new(0x0000_0001u32, 0x7f80_0000);
+    iterate("f32_random_equivalence_test", k, n, f, g, |_| {
+        let i: u32 = f32_range.ind_sample(&mut rng);
+        let x: f32 = unsafe {mem::transmute(i)};
+        decode_finite(x)
+    });
+}
+
+pub fn f64_random_equivalence_test<F, G>(f: F, g: G, k: usize, n: usize)
+        where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
+              G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+    let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng());
+    let f64_range = Range::new(0x0000_0000_0000_0001u64, 0x7ff0_0000_0000_0000);
+    iterate("f64_random_equivalence_test", k, n, f, g, |_| {
+        let i: u64 = f64_range.ind_sample(&mut rng);
+        let x: f64 = unsafe {mem::transmute(i)};
+        decode_finite(x)
+    });
+}
+
+pub fn f32_exhaustive_equivalence_test<F, G>(f: F, g: G, k: usize)
+        where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
+              G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+    // we have only 2^23 * (2^8 - 1) - 1 = 2,139,095,039 positive finite f32 values,
+    // so why not simply testing all of them?
+    //
+    // this is of course very stressful (and thus should be behind an `#[ignore]` attribute),
+    // but with `-C opt-level=3 -C lto` this only takes about an hour or so.
+
+    // iterate from 0x0000_0001 to 0x7f7f_ffff, i.e. all finite ranges
+    let (npassed, nignored) = iterate("f32_exhaustive_equivalence_test",
+                                      k, 0x7f7f_ffff, f, g, |i: usize| {
+        let x: f32 = unsafe {mem::transmute(i as u32 + 1)};
+        decode_finite(x)
+    });
+    assert_eq!((npassed, nignored), (2121451881, 17643158));
+}
+
+fn to_string_with_parts<F>(mut f: F) -> String
+        where F: for<'a> FnMut(&'a mut [u8], &'a mut [Part<'a>]) -> Formatted<'a> {
+    let mut buf = [0; 1024];
+    let mut parts = [Part::Zero(0); 16];
+    let formatted = f(&mut buf, &mut parts);
+    let mut ret = vec![0; formatted.len()];
+    assert_eq!(formatted.write(&mut ret), Some(ret.len()));
+    String::from_utf8(ret).unwrap()
+}
+
+pub fn to_shortest_str_test<F>(mut f_: F)
+        where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+    use core::num::flt2dec::Sign::*;
+
+    fn to_string<T, F>(f: &mut F, v: T, sign: Sign, frac_digits: usize, upper: bool) -> String
+            where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+        to_string_with_parts(|buf, parts| to_shortest_str(|d,b| f(d,b), v, sign,
+                                                          frac_digits, upper, buf, parts))
+    }
+
+    let f = &mut f_;
+
+    assert_eq!(to_string(f,  0.0, Minus,        0, false), "0");
+    assert_eq!(to_string(f,  0.0, MinusRaw,     0, false), "0");
+    assert_eq!(to_string(f,  0.0, MinusPlus,    0, false), "+0");
+    assert_eq!(to_string(f,  0.0, MinusPlusRaw, 0, false), "+0");
+    assert_eq!(to_string(f, -0.0, Minus,        0, false), "0");
+    assert_eq!(to_string(f, -0.0, MinusRaw,     0, false), "-0");
+    assert_eq!(to_string(f, -0.0, MinusPlus,    0, false), "+0");
+    assert_eq!(to_string(f, -0.0, MinusPlusRaw, 0, false), "-0");
+    assert_eq!(to_string(f,  0.0, Minus,        1,  true), "0.0");
+    assert_eq!(to_string(f,  0.0, MinusRaw,     1,  true), "0.0");
+    assert_eq!(to_string(f,  0.0, MinusPlus,    1,  true), "+0.0");
+    assert_eq!(to_string(f,  0.0, MinusPlusRaw, 1,  true), "+0.0");
+    assert_eq!(to_string(f, -0.0, Minus,        8,  true), "0.00000000");
+    assert_eq!(to_string(f, -0.0, MinusRaw,     8,  true), "-0.00000000");
+    assert_eq!(to_string(f, -0.0, MinusPlus,    8,  true), "+0.00000000");
+    assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8,  true), "-0.00000000");
+
+    assert_eq!(to_string(f,  1.0/0.0, Minus,         0, false), "inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusRaw,      0,  true), "inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusPlus,     0, false), "+inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusPlusRaw,  0,  true), "+inf");
+    assert_eq!(to_string(f,  0.0/0.0, Minus,         0, false), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusRaw,      1,  true), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusPlus,     8, false), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusPlusRaw, 64,  true), "NaN");
+    assert_eq!(to_string(f, -1.0/0.0, Minus,         0, false), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusRaw,      1,  true), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusPlus,     8, false), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusPlusRaw, 64,  true), "-inf");
+
+    assert_eq!(to_string(f,  3.14, Minus,        0, false), "3.14");
+    assert_eq!(to_string(f,  3.14, MinusRaw,     0, false), "3.14");
+    assert_eq!(to_string(f,  3.14, MinusPlus,    0, false), "+3.14");
+    assert_eq!(to_string(f,  3.14, MinusPlusRaw, 0, false), "+3.14");
+    assert_eq!(to_string(f, -3.14, Minus,        0, false), "-3.14");
+    assert_eq!(to_string(f, -3.14, MinusRaw,     0, false), "-3.14");
+    assert_eq!(to_string(f, -3.14, MinusPlus,    0, false), "-3.14");
+    assert_eq!(to_string(f, -3.14, MinusPlusRaw, 0, false), "-3.14");
+    assert_eq!(to_string(f,  3.14, Minus,        1,  true), "3.14");
+    assert_eq!(to_string(f,  3.14, MinusRaw,     2,  true), "3.14");
+    assert_eq!(to_string(f,  3.14, MinusPlus,    3,  true), "+3.140");
+    assert_eq!(to_string(f,  3.14, MinusPlusRaw, 4,  true), "+3.1400");
+    assert_eq!(to_string(f, -3.14, Minus,        8,  true), "-3.14000000");
+    assert_eq!(to_string(f, -3.14, MinusRaw,     8,  true), "-3.14000000");
+    assert_eq!(to_string(f, -3.14, MinusPlus,    8,  true), "-3.14000000");
+    assert_eq!(to_string(f, -3.14, MinusPlusRaw, 8,  true), "-3.14000000");
+
+    assert_eq!(to_string(f, 7.5e-11, Minus,  0, false), "0.000000000075");
+    assert_eq!(to_string(f, 7.5e-11, Minus,  3, false), "0.000000000075");
+    assert_eq!(to_string(f, 7.5e-11, Minus, 12, false), "0.000000000075");
+    assert_eq!(to_string(f, 7.5e-11, Minus, 13, false), "0.0000000000750");
+
+    assert_eq!(to_string(f, 1.9971e20, Minus, 0, false), "199710000000000000000");
+    assert_eq!(to_string(f, 1.9971e20, Minus, 1, false), "199710000000000000000.0");
+    assert_eq!(to_string(f, 1.9971e20, Minus, 8, false), "199710000000000000000.00000000");
+
+    assert_eq!(to_string(f, f32::MAX, Minus, 0, false), format!("34028235{:0>31}", ""));
+    assert_eq!(to_string(f, f32::MAX, Minus, 1, false), format!("34028235{:0>31}.0", ""));
+    assert_eq!(to_string(f, f32::MAX, Minus, 8, false), format!("34028235{:0>31}.00000000", ""));
+
+    let minf32 = ldexp_f32(1.0, -149);
+    assert_eq!(to_string(f, minf32, Minus,  0, false), format!("0.{:0>44}1", ""));
+    assert_eq!(to_string(f, minf32, Minus, 45, false), format!("0.{:0>44}1", ""));
+    assert_eq!(to_string(f, minf32, Minus, 46, false), format!("0.{:0>44}10", ""));
+
+    assert_eq!(to_string(f, f64::MAX, Minus, 0, false),
+               format!("17976931348623157{:0>292}", ""));
+    assert_eq!(to_string(f, f64::MAX, Minus, 1, false),
+               format!("17976931348623157{:0>292}.0", ""));
+    assert_eq!(to_string(f, f64::MAX, Minus, 8, false),
+               format!("17976931348623157{:0>292}.00000000", ""));
+
+    let minf64 = ldexp_f64(1.0, -1074);
+    assert_eq!(to_string(f, minf64, Minus,   0, false), format!("0.{:0>323}5", ""));
+    assert_eq!(to_string(f, minf64, Minus, 324, false), format!("0.{:0>323}5", ""));
+    assert_eq!(to_string(f, minf64, Minus, 325, false), format!("0.{:0>323}50", ""));
+
+    // very large output
+    assert_eq!(to_string(f, 1.1, Minus, 80000, false), format!("1.1{:0>79999}", ""));
+}
+
+pub fn to_shortest_exp_str_test<F>(mut f_: F)
+        where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+    use core::num::flt2dec::Sign::*;
+
+    fn to_string<T, F>(f: &mut F, v: T, sign: Sign, exp_bounds: (i16, i16), upper: bool) -> String
+            where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+        to_string_with_parts(|buf, parts| to_shortest_exp_str(|d,b| f(d,b), v, sign,
+                                                              exp_bounds, upper, buf, parts))
+    }
+
+    let f = &mut f_;
+
+    assert_eq!(to_string(f,  0.0, Minus,        (-4, 16), false), "0");
+    assert_eq!(to_string(f,  0.0, MinusRaw,     (-4, 16), false), "0");
+    assert_eq!(to_string(f,  0.0, MinusPlus,    (-4, 16), false), "+0");
+    assert_eq!(to_string(f,  0.0, MinusPlusRaw, (-4, 16), false), "+0");
+    assert_eq!(to_string(f, -0.0, Minus,        (-4, 16), false), "0");
+    assert_eq!(to_string(f, -0.0, MinusRaw,     (-4, 16), false), "-0");
+    assert_eq!(to_string(f, -0.0, MinusPlus,    (-4, 16), false), "+0");
+    assert_eq!(to_string(f, -0.0, MinusPlusRaw, (-4, 16), false), "-0");
+    assert_eq!(to_string(f,  0.0, Minus,        ( 0,  0),  true), "0E0");
+    assert_eq!(to_string(f,  0.0, MinusRaw,     ( 0,  0), false), "0e0");
+    assert_eq!(to_string(f,  0.0, MinusPlus,    (-9, -5),  true), "+0E0");
+    assert_eq!(to_string(f,  0.0, MinusPlusRaw, ( 5,  9), false), "+0e0");
+    assert_eq!(to_string(f, -0.0, Minus,        ( 0,  0),  true), "0E0");
+    assert_eq!(to_string(f, -0.0, MinusRaw,     ( 0,  0), false), "-0e0");
+    assert_eq!(to_string(f, -0.0, MinusPlus,    (-9, -5),  true), "+0E0");
+    assert_eq!(to_string(f, -0.0, MinusPlusRaw, ( 5,  9), false), "-0e0");
+
+    assert_eq!(to_string(f,  1.0/0.0, Minus,        (-4, 16), false), "inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusRaw,     (-4, 16),  true), "inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusPlus,    (-4, 16), false), "+inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusPlusRaw, (-4, 16),  true), "+inf");
+    assert_eq!(to_string(f,  0.0/0.0, Minus,        ( 0,  0), false), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusRaw,     ( 0,  0),  true), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusPlus,    (-9, -5), false), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusPlusRaw, ( 5,  9),  true), "NaN");
+    assert_eq!(to_string(f, -1.0/0.0, Minus,        ( 0,  0), false), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusRaw,     ( 0,  0),  true), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusPlus,    (-9, -5), false), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusPlusRaw, ( 5,  9),  true), "-inf");
+
+    assert_eq!(to_string(f,  3.14, Minus,        (-4, 16), false), "3.14");
+    assert_eq!(to_string(f,  3.14, MinusRaw,     (-4, 16), false), "3.14");
+    assert_eq!(to_string(f,  3.14, MinusPlus,    (-4, 16), false), "+3.14");
+    assert_eq!(to_string(f,  3.14, MinusPlusRaw, (-4, 16), false), "+3.14");
+    assert_eq!(to_string(f, -3.14, Minus,        (-4, 16), false), "-3.14");
+    assert_eq!(to_string(f, -3.14, MinusRaw,     (-4, 16), false), "-3.14");
+    assert_eq!(to_string(f, -3.14, MinusPlus,    (-4, 16), false), "-3.14");
+    assert_eq!(to_string(f, -3.14, MinusPlusRaw, (-4, 16), false), "-3.14");
+    assert_eq!(to_string(f,  3.14, Minus,        ( 0,  0),  true), "3.14E0");
+    assert_eq!(to_string(f,  3.14, MinusRaw,     ( 0,  0), false), "3.14e0");
+    assert_eq!(to_string(f,  3.14, MinusPlus,    (-9, -5),  true), "+3.14E0");
+    assert_eq!(to_string(f,  3.14, MinusPlusRaw, ( 5,  9), false), "+3.14e0");
+    assert_eq!(to_string(f, -3.14, Minus,        ( 0,  0),  true), "-3.14E0");
+    assert_eq!(to_string(f, -3.14, MinusRaw,     ( 0,  0), false), "-3.14e0");
+    assert_eq!(to_string(f, -3.14, MinusPlus,    (-9, -5),  true), "-3.14E0");
+    assert_eq!(to_string(f, -3.14, MinusPlusRaw, ( 5,  9), false), "-3.14e0");
+
+    assert_eq!(to_string(f,  0.1, Minus,        (-4, 16), false), "0.1");
+    assert_eq!(to_string(f,  0.1, MinusRaw,     (-4, 16), false), "0.1");
+    assert_eq!(to_string(f,  0.1, MinusPlus,    (-4, 16), false), "+0.1");
+    assert_eq!(to_string(f,  0.1, MinusPlusRaw, (-4, 16), false), "+0.1");
+    assert_eq!(to_string(f, -0.1, Minus,        (-4, 16), false), "-0.1");
+    assert_eq!(to_string(f, -0.1, MinusRaw,     (-4, 16), false), "-0.1");
+    assert_eq!(to_string(f, -0.1, MinusPlus,    (-4, 16), false), "-0.1");
+    assert_eq!(to_string(f, -0.1, MinusPlusRaw, (-4, 16), false), "-0.1");
+    assert_eq!(to_string(f,  0.1, Minus,        ( 0,  0),  true), "1E-1");
+    assert_eq!(to_string(f,  0.1, MinusRaw,     ( 0,  0), false), "1e-1");
+    assert_eq!(to_string(f,  0.1, MinusPlus,    (-9, -5),  true), "+1E-1");
+    assert_eq!(to_string(f,  0.1, MinusPlusRaw, ( 5,  9), false), "+1e-1");
+    assert_eq!(to_string(f, -0.1, Minus,        ( 0,  0),  true), "-1E-1");
+    assert_eq!(to_string(f, -0.1, MinusRaw,     ( 0,  0), false), "-1e-1");
+    assert_eq!(to_string(f, -0.1, MinusPlus,    (-9, -5),  true), "-1E-1");
+    assert_eq!(to_string(f, -0.1, MinusPlusRaw, ( 5,  9), false), "-1e-1");
+
+    assert_eq!(to_string(f, 7.5e-11, Minus, ( -4, 16), false), "7.5e-11");
+    assert_eq!(to_string(f, 7.5e-11, Minus, (-11, 10), false), "0.000000000075");
+    assert_eq!(to_string(f, 7.5e-11, Minus, (-10, 11), false), "7.5e-11");
+
+    assert_eq!(to_string(f, 1.9971e20, Minus, ( -4, 16), false), "1.9971e20");
+    assert_eq!(to_string(f, 1.9971e20, Minus, (-20, 21), false), "199710000000000000000");
+    assert_eq!(to_string(f, 1.9971e20, Minus, (-21, 20), false), "1.9971e20");
+
+    // the true value of 1.0e23f64 is less than 10^23, but that shouldn't matter here
+    assert_eq!(to_string(f, 1.0e23, Minus, (22, 23), false), "1e23");
+    assert_eq!(to_string(f, 1.0e23, Minus, (23, 24), false), "100000000000000000000000");
+    assert_eq!(to_string(f, 1.0e23, Minus, (24, 25), false), "1e23");
+
+    assert_eq!(to_string(f, f32::MAX, Minus, ( -4, 16), false), "3.4028235e38");
+    assert_eq!(to_string(f, f32::MAX, Minus, (-39, 38), false), "3.4028235e38");
+    assert_eq!(to_string(f, f32::MAX, Minus, (-38, 39), false), format!("34028235{:0>31}", ""));
+
+    let minf32 = ldexp_f32(1.0, -149);
+    assert_eq!(to_string(f, minf32, Minus, ( -4, 16), false), "1e-45");
+    assert_eq!(to_string(f, minf32, Minus, (-44, 45), false), "1e-45");
+    assert_eq!(to_string(f, minf32, Minus, (-45, 44), false), format!("0.{:0>44}1", ""));
+
+    assert_eq!(to_string(f, f64::MAX, Minus, (  -4,  16), false),
+               "1.7976931348623157e308");
+    assert_eq!(to_string(f, f64::MAX, Minus, (-308, 309), false),
+               format!("17976931348623157{:0>292}", ""));
+    assert_eq!(to_string(f, f64::MAX, Minus, (-309, 308), false),
+               "1.7976931348623157e308");
+
+    let minf64 = ldexp_f64(1.0, -1074);
+    assert_eq!(to_string(f, minf64, Minus, (  -4,  16), false), "5e-324");
+    assert_eq!(to_string(f, minf64, Minus, (-324, 323), false), format!("0.{:0>323}5", ""));
+    assert_eq!(to_string(f, minf64, Minus, (-323, 324), false), "5e-324");
+
+    assert_eq!(to_string(f, 1.1, Minus, (i16::MIN, i16::MAX), false), "1.1");
+}
+
+pub fn to_exact_exp_str_test<F>(mut f_: F)
+        where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+    use core::num::flt2dec::Sign::*;
+
+    fn to_string<T, F>(f: &mut F, v: T, sign: Sign, ndigits: usize, upper: bool) -> String
+            where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+        to_string_with_parts(|buf, parts| to_exact_exp_str(|d,b,l| f(d,b,l), v, sign,
+                                                           ndigits, upper, buf, parts))
+    }
+
+    let f = &mut f_;
+
+    assert_eq!(to_string(f,  0.0, Minus,        1,  true), "0E0");
+    assert_eq!(to_string(f,  0.0, MinusRaw,     1, false), "0e0");
+    assert_eq!(to_string(f,  0.0, MinusPlus,    1,  true), "+0E0");
+    assert_eq!(to_string(f,  0.0, MinusPlusRaw, 1, false), "+0e0");
+    assert_eq!(to_string(f, -0.0, Minus,        1,  true), "0E0");
+    assert_eq!(to_string(f, -0.0, MinusRaw,     1, false), "-0e0");
+    assert_eq!(to_string(f, -0.0, MinusPlus,    1,  true), "+0E0");
+    assert_eq!(to_string(f, -0.0, MinusPlusRaw, 1, false), "-0e0");
+    assert_eq!(to_string(f,  0.0, Minus,        2,  true), "0.0E0");
+    assert_eq!(to_string(f,  0.0, MinusRaw,     2, false), "0.0e0");
+    assert_eq!(to_string(f,  0.0, MinusPlus,    2,  true), "+0.0E0");
+    assert_eq!(to_string(f,  0.0, MinusPlusRaw, 2, false), "+0.0e0");
+    assert_eq!(to_string(f, -0.0, Minus,        8,  true), "0.0000000E0");
+    assert_eq!(to_string(f, -0.0, MinusRaw,     8, false), "-0.0000000e0");
+    assert_eq!(to_string(f, -0.0, MinusPlus,    8,  true), "+0.0000000E0");
+    assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8, false), "-0.0000000e0");
+
+    assert_eq!(to_string(f,  1.0/0.0, Minus,         1, false), "inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusRaw,      1,  true), "inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusPlus,     1, false), "+inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusPlusRaw,  1,  true), "+inf");
+    assert_eq!(to_string(f,  0.0/0.0, Minus,         8, false), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusRaw,      8,  true), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusPlus,     8, false), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusPlusRaw,  8,  true), "NaN");
+    assert_eq!(to_string(f, -1.0/0.0, Minus,        64, false), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusRaw,     64,  true), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusPlus,    64, false), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusPlusRaw, 64,  true), "-inf");
+
+    assert_eq!(to_string(f,  3.14, Minus,        1,  true), "3E0");
+    assert_eq!(to_string(f,  3.14, MinusRaw,     1, false), "3e0");
+    assert_eq!(to_string(f,  3.14, MinusPlus,    1,  true), "+3E0");
+    assert_eq!(to_string(f,  3.14, MinusPlusRaw, 1, false), "+3e0");
+    assert_eq!(to_string(f, -3.14, Minus,        2,  true), "-3.1E0");
+    assert_eq!(to_string(f, -3.14, MinusRaw,     2, false), "-3.1e0");
+    assert_eq!(to_string(f, -3.14, MinusPlus,    2,  true), "-3.1E0");
+    assert_eq!(to_string(f, -3.14, MinusPlusRaw, 2, false), "-3.1e0");
+    assert_eq!(to_string(f,  3.14, Minus,        3,  true), "3.14E0");
+    assert_eq!(to_string(f,  3.14, MinusRaw,     3, false), "3.14e0");
+    assert_eq!(to_string(f,  3.14, MinusPlus,    3,  true), "+3.14E0");
+    assert_eq!(to_string(f,  3.14, MinusPlusRaw, 3, false), "+3.14e0");
+    assert_eq!(to_string(f, -3.14, Minus,        4,  true), "-3.140E0");
+    assert_eq!(to_string(f, -3.14, MinusRaw,     4, false), "-3.140e0");
+    assert_eq!(to_string(f, -3.14, MinusPlus,    4,  true), "-3.140E0");
+    assert_eq!(to_string(f, -3.14, MinusPlusRaw, 4, false), "-3.140e0");
+
+    assert_eq!(to_string(f,  0.195, Minus,        1, false), "2e-1");
+    assert_eq!(to_string(f,  0.195, MinusRaw,     1,  true), "2E-1");
+    assert_eq!(to_string(f,  0.195, MinusPlus,    1, false), "+2e-1");
+    assert_eq!(to_string(f,  0.195, MinusPlusRaw, 1,  true), "+2E-1");
+    assert_eq!(to_string(f, -0.195, Minus,        2, false), "-2.0e-1");
+    assert_eq!(to_string(f, -0.195, MinusRaw,     2,  true), "-2.0E-1");
+    assert_eq!(to_string(f, -0.195, MinusPlus,    2, false), "-2.0e-1");
+    assert_eq!(to_string(f, -0.195, MinusPlusRaw, 2,  true), "-2.0E-1");
+    assert_eq!(to_string(f,  0.195, Minus,        3, false), "1.95e-1");
+    assert_eq!(to_string(f,  0.195, MinusRaw,     3,  true), "1.95E-1");
+    assert_eq!(to_string(f,  0.195, MinusPlus,    3, false), "+1.95e-1");
+    assert_eq!(to_string(f,  0.195, MinusPlusRaw, 3,  true), "+1.95E-1");
+    assert_eq!(to_string(f, -0.195, Minus,        4, false), "-1.950e-1");
+    assert_eq!(to_string(f, -0.195, MinusRaw,     4,  true), "-1.950E-1");
+    assert_eq!(to_string(f, -0.195, MinusPlus,    4, false), "-1.950e-1");
+    assert_eq!(to_string(f, -0.195, MinusPlusRaw, 4,  true), "-1.950E-1");
+
+    assert_eq!(to_string(f, 9.5, Minus,  1, false), "1e1");
+    assert_eq!(to_string(f, 9.5, Minus,  2, false), "9.5e0");
+    assert_eq!(to_string(f, 9.5, Minus,  3, false), "9.50e0");
+    assert_eq!(to_string(f, 9.5, Minus, 30, false), "9.50000000000000000000000000000e0");
+
+    assert_eq!(to_string(f, 1.0e25, Minus,  1, false), "1e25");
+    assert_eq!(to_string(f, 1.0e25, Minus,  2, false), "1.0e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 15, false), "1.00000000000000e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 16, false), "1.000000000000000e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 17, false), "1.0000000000000001e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 18, false), "1.00000000000000009e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 19, false), "1.000000000000000091e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 20, false), "1.0000000000000000906e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 21, false), "1.00000000000000009060e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 22, false), "1.000000000000000090597e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 23, false), "1.0000000000000000905970e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 24, false), "1.00000000000000009059697e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 25, false), "1.000000000000000090596966e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 26, false), "1.0000000000000000905969664e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 27, false), "1.00000000000000009059696640e25");
+    assert_eq!(to_string(f, 1.0e25, Minus, 30, false), "1.00000000000000009059696640000e25");
+
+    assert_eq!(to_string(f, 1.0e-6, Minus,  1, false), "1e-6");
+    assert_eq!(to_string(f, 1.0e-6, Minus,  2, false), "1.0e-6");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 16, false), "1.000000000000000e-6");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 17, false), "9.9999999999999995e-7");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 18, false), "9.99999999999999955e-7");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 19, false), "9.999999999999999547e-7");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 20, false), "9.9999999999999995475e-7");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 30, false), "9.99999999999999954748111825886e-7");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 40, false),
+               "9.999999999999999547481118258862586856139e-7");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 50, false),
+               "9.9999999999999995474811182588625868561393872369081e-7");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 60, false),
+               "9.99999999999999954748111825886258685613938723690807819366455e-7");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 70, false),
+               "9.999999999999999547481118258862586856139387236908078193664550781250000e-7");
+
+    assert_eq!(to_string(f, f32::MAX, Minus,  1, false), "3e38");
+    assert_eq!(to_string(f, f32::MAX, Minus,  2, false), "3.4e38");
+    assert_eq!(to_string(f, f32::MAX, Minus,  4, false), "3.403e38");
+    assert_eq!(to_string(f, f32::MAX, Minus,  8, false), "3.4028235e38");
+    assert_eq!(to_string(f, f32::MAX, Minus, 16, false), "3.402823466385289e38");
+    assert_eq!(to_string(f, f32::MAX, Minus, 32, false), "3.4028234663852885981170418348452e38");
+    assert_eq!(to_string(f, f32::MAX, Minus, 64, false),
+               "3.402823466385288598117041834845169254400000000000000000000000000e38");
+
+    let minf32 = ldexp_f32(1.0, -149);
+    assert_eq!(to_string(f, minf32, Minus,   1, false), "1e-45");
+    assert_eq!(to_string(f, minf32, Minus,   2, false), "1.4e-45");
+    assert_eq!(to_string(f, minf32, Minus,   4, false), "1.401e-45");
+    assert_eq!(to_string(f, minf32, Minus,   8, false), "1.4012985e-45");
+    assert_eq!(to_string(f, minf32, Minus,  16, false), "1.401298464324817e-45");
+    assert_eq!(to_string(f, minf32, Minus,  32, false), "1.4012984643248170709237295832899e-45");
+    assert_eq!(to_string(f, minf32, Minus,  64, false),
+               "1.401298464324817070923729583289916131280261941876515771757068284e-45");
+    assert_eq!(to_string(f, minf32, Minus, 128, false),
+               "1.401298464324817070923729583289916131280261941876515771757068283\
+                 8897910826858606014866381883621215820312500000000000000000000000e-45");
+
+    assert_eq!(to_string(f, f64::MAX, Minus,   1, false), "2e308");
+    assert_eq!(to_string(f, f64::MAX, Minus,   2, false), "1.8e308");
+    assert_eq!(to_string(f, f64::MAX, Minus,   4, false), "1.798e308");
+    assert_eq!(to_string(f, f64::MAX, Minus,   8, false), "1.7976931e308");
+    assert_eq!(to_string(f, f64::MAX, Minus,  16, false), "1.797693134862316e308");
+    assert_eq!(to_string(f, f64::MAX, Minus,  32, false), "1.7976931348623157081452742373170e308");
+    assert_eq!(to_string(f, f64::MAX, Minus,  64, false),
+               "1.797693134862315708145274237317043567980705675258449965989174768e308");
+    assert_eq!(to_string(f, f64::MAX, Minus, 128, false),
+               "1.797693134862315708145274237317043567980705675258449965989174768\
+                 0315726078002853876058955863276687817154045895351438246423432133e308");
+    assert_eq!(to_string(f, f64::MAX, Minus, 256, false),
+               "1.797693134862315708145274237317043567980705675258449965989174768\
+                 0315726078002853876058955863276687817154045895351438246423432132\
+                 6889464182768467546703537516986049910576551282076245490090389328\
+                 9440758685084551339423045832369032229481658085593321233482747978e308");
+    assert_eq!(to_string(f, f64::MAX, Minus, 512, false),
+               "1.797693134862315708145274237317043567980705675258449965989174768\
+                 0315726078002853876058955863276687817154045895351438246423432132\
+                 6889464182768467546703537516986049910576551282076245490090389328\
+                 9440758685084551339423045832369032229481658085593321233482747978\
+                 2620414472316873817718091929988125040402618412485836800000000000\
+                 0000000000000000000000000000000000000000000000000000000000000000\
+                 0000000000000000000000000000000000000000000000000000000000000000\
+                 0000000000000000000000000000000000000000000000000000000000000000e308");
+
+    // okay, this is becoming tough. fortunately for us, this is almost the worst case.
+    let minf64 = ldexp_f64(1.0, -1074);
+    assert_eq!(to_string(f, minf64, Minus,    1, false), "5e-324");
+    assert_eq!(to_string(f, minf64, Minus,    2, false), "4.9e-324");
+    assert_eq!(to_string(f, minf64, Minus,    4, false), "4.941e-324");
+    assert_eq!(to_string(f, minf64, Minus,    8, false), "4.9406565e-324");
+    assert_eq!(to_string(f, minf64, Minus,   16, false), "4.940656458412465e-324");
+    assert_eq!(to_string(f, minf64, Minus,   32, false), "4.9406564584124654417656879286822e-324");
+    assert_eq!(to_string(f, minf64, Minus,   64, false),
+               "4.940656458412465441765687928682213723650598026143247644255856825e-324");
+    assert_eq!(to_string(f, minf64, Minus,  128, false),
+               "4.940656458412465441765687928682213723650598026143247644255856825\
+                 0067550727020875186529983636163599237979656469544571773092665671e-324");
+    assert_eq!(to_string(f, minf64, Minus,  256, false),
+               "4.940656458412465441765687928682213723650598026143247644255856825\
+                 0067550727020875186529983636163599237979656469544571773092665671\
+                 0355939796398774796010781878126300713190311404527845817167848982\
+                 1036887186360569987307230500063874091535649843873124733972731696e-324");
+    assert_eq!(to_string(f, minf64, Minus,  512, false),
+               "4.940656458412465441765687928682213723650598026143247644255856825\
+                 0067550727020875186529983636163599237979656469544571773092665671\
+                 0355939796398774796010781878126300713190311404527845817167848982\
+                 1036887186360569987307230500063874091535649843873124733972731696\
+                 1514003171538539807412623856559117102665855668676818703956031062\
+                 4931945271591492455329305456544401127480129709999541931989409080\
+                 4165633245247571478690147267801593552386115501348035264934720193\
+                 7902681071074917033322268447533357208324319360923828934583680601e-324");
+    assert_eq!(to_string(f, minf64, Minus, 1024, false),
+               "4.940656458412465441765687928682213723650598026143247644255856825\
+                 0067550727020875186529983636163599237979656469544571773092665671\
+                 0355939796398774796010781878126300713190311404527845817167848982\
+                 1036887186360569987307230500063874091535649843873124733972731696\
+                 1514003171538539807412623856559117102665855668676818703956031062\
+                 4931945271591492455329305456544401127480129709999541931989409080\
+                 4165633245247571478690147267801593552386115501348035264934720193\
+                 7902681071074917033322268447533357208324319360923828934583680601\
+                 0601150616980975307834227731832924790498252473077637592724787465\
+                 6084778203734469699533647017972677717585125660551199131504891101\
+                 4510378627381672509558373897335989936648099411642057026370902792\
+                 4276754456522908753868250641971826553344726562500000000000000000\
+                 0000000000000000000000000000000000000000000000000000000000000000\
+                 0000000000000000000000000000000000000000000000000000000000000000\
+                 0000000000000000000000000000000000000000000000000000000000000000\
+                 0000000000000000000000000000000000000000000000000000000000000000e-324");
+
+    // very large output
+    assert_eq!(to_string(f, 0.0,     Minus, 80000, false), format!("0.{:0>79999}e0", ""));
+    assert_eq!(to_string(f, 1.0e1,   Minus, 80000, false), format!("1.{:0>79999}e1", ""));
+    assert_eq!(to_string(f, 1.0e0,   Minus, 80000, false), format!("1.{:0>79999}e0", ""));
+    assert_eq!(to_string(f, 1.0e-1,  Minus, 80000, false),
+               format!("1.000000000000000055511151231257827021181583404541015625{:0>79945}\
+                        e-1", ""));
+    assert_eq!(to_string(f, 1.0e-20, Minus, 80000, false),
+               format!("9.999999999999999451532714542095716517295037027873924471077157760\
+                         66783064379706047475337982177734375{:0>79901}e-21", ""));
+}
+
+pub fn to_exact_fixed_str_test<F>(mut f_: F)
+        where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+    use core::num::flt2dec::Sign::*;
+
+    fn to_string<T, F>(f: &mut F, v: T, sign: Sign, frac_digits: usize, upper: bool) -> String
+            where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+        to_string_with_parts(|buf, parts| to_exact_fixed_str(|d,b,l| f(d,b,l), v, sign,
+                                                             frac_digits, upper, buf, parts))
+    }
+
+    let f = &mut f_;
+
+    assert_eq!(to_string(f,  0.0, Minus,        0, false), "0");
+    assert_eq!(to_string(f,  0.0, MinusRaw,     0, false), "0");
+    assert_eq!(to_string(f,  0.0, MinusPlus,    0, false), "+0");
+    assert_eq!(to_string(f,  0.0, MinusPlusRaw, 0, false), "+0");
+    assert_eq!(to_string(f, -0.0, Minus,        0, false), "0");
+    assert_eq!(to_string(f, -0.0, MinusRaw,     0, false), "-0");
+    assert_eq!(to_string(f, -0.0, MinusPlus,    0, false), "+0");
+    assert_eq!(to_string(f, -0.0, MinusPlusRaw, 0, false), "-0");
+    assert_eq!(to_string(f,  0.0, Minus,        1,  true), "0.0");
+    assert_eq!(to_string(f,  0.0, MinusRaw,     1,  true), "0.0");
+    assert_eq!(to_string(f,  0.0, MinusPlus,    1,  true), "+0.0");
+    assert_eq!(to_string(f,  0.0, MinusPlusRaw, 1,  true), "+0.0");
+    assert_eq!(to_string(f, -0.0, Minus,        8,  true), "0.00000000");
+    assert_eq!(to_string(f, -0.0, MinusRaw,     8,  true), "-0.00000000");
+    assert_eq!(to_string(f, -0.0, MinusPlus,    8,  true), "+0.00000000");
+    assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8,  true), "-0.00000000");
+
+    assert_eq!(to_string(f,  1.0/0.0, Minus,         0, false), "inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusRaw,      1,  true), "inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusPlus,     8, false), "+inf");
+    assert_eq!(to_string(f,  1.0/0.0, MinusPlusRaw, 64,  true), "+inf");
+    assert_eq!(to_string(f,  0.0/0.0, Minus,         0, false), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusRaw,      1,  true), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusPlus,     8, false), "NaN");
+    assert_eq!(to_string(f,  0.0/0.0, MinusPlusRaw, 64,  true), "NaN");
+    assert_eq!(to_string(f, -1.0/0.0, Minus,         0, false), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusRaw,      1,  true), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusPlus,     8, false), "-inf");
+    assert_eq!(to_string(f, -1.0/0.0, MinusPlusRaw, 64,  true), "-inf");
+
+    assert_eq!(to_string(f,  3.14, Minus,        0, false), "3");
+    assert_eq!(to_string(f,  3.14, MinusRaw,     0, false), "3");
+    assert_eq!(to_string(f,  3.14, MinusPlus,    0, false), "+3");
+    assert_eq!(to_string(f,  3.14, MinusPlusRaw, 0, false), "+3");
+    assert_eq!(to_string(f, -3.14, Minus,        0, false), "-3");
+    assert_eq!(to_string(f, -3.14, MinusRaw,     0, false), "-3");
+    assert_eq!(to_string(f, -3.14, MinusPlus,    0, false), "-3");
+    assert_eq!(to_string(f, -3.14, MinusPlusRaw, 0, false), "-3");
+    assert_eq!(to_string(f,  3.14, Minus,        1,  true), "3.1");
+    assert_eq!(to_string(f,  3.14, MinusRaw,     2,  true), "3.14");
+    assert_eq!(to_string(f,  3.14, MinusPlus,    3,  true), "+3.140");
+    assert_eq!(to_string(f,  3.14, MinusPlusRaw, 4,  true), "+3.1400");
+    assert_eq!(to_string(f, -3.14, Minus,        8,  true), "-3.14000000");
+    assert_eq!(to_string(f, -3.14, MinusRaw,     8,  true), "-3.14000000");
+    assert_eq!(to_string(f, -3.14, MinusPlus,    8,  true), "-3.14000000");
+    assert_eq!(to_string(f, -3.14, MinusPlusRaw, 8,  true), "-3.14000000");
+
+    assert_eq!(to_string(f,  0.195, Minus,        0, false), "0");
+    assert_eq!(to_string(f,  0.195, MinusRaw,     0, false), "0");
+    assert_eq!(to_string(f,  0.195, MinusPlus,    0, false), "+0");
+    assert_eq!(to_string(f,  0.195, MinusPlusRaw, 0, false), "+0");
+    assert_eq!(to_string(f, -0.195, Minus,        0, false), "-0");
+    assert_eq!(to_string(f, -0.195, MinusRaw,     0, false), "-0");
+    assert_eq!(to_string(f, -0.195, MinusPlus,    0, false), "-0");
+    assert_eq!(to_string(f, -0.195, MinusPlusRaw, 0, false), "-0");
+    assert_eq!(to_string(f,  0.195, Minus,        1,  true), "0.2");
+    assert_eq!(to_string(f,  0.195, MinusRaw,     2,  true), "0.20");
+    assert_eq!(to_string(f,  0.195, MinusPlus,    3,  true), "+0.195");
+    assert_eq!(to_string(f,  0.195, MinusPlusRaw, 4,  true), "+0.1950");
+    assert_eq!(to_string(f, -0.195, Minus,        5,  true), "-0.19500");
+    assert_eq!(to_string(f, -0.195, MinusRaw,     6,  true), "-0.195000");
+    assert_eq!(to_string(f, -0.195, MinusPlus,    7,  true), "-0.1950000");
+    assert_eq!(to_string(f, -0.195, MinusPlusRaw, 8,  true), "-0.19500000");
+
+    assert_eq!(to_string(f, 999.5, Minus,  0, false), "1000");
+    assert_eq!(to_string(f, 999.5, Minus,  1, false), "999.5");
+    assert_eq!(to_string(f, 999.5, Minus,  2, false), "999.50");
+    assert_eq!(to_string(f, 999.5, Minus,  3, false), "999.500");
+    assert_eq!(to_string(f, 999.5, Minus, 30, false), "999.500000000000000000000000000000");
+
+    assert_eq!(to_string(f, 0.5, Minus, 0, false), "1");
+    assert_eq!(to_string(f, 0.5, Minus, 1, false), "0.5");
+    assert_eq!(to_string(f, 0.5, Minus, 2, false), "0.50");
+    assert_eq!(to_string(f, 0.5, Minus, 3, false), "0.500");
+
+    assert_eq!(to_string(f, 0.95, Minus,  0, false), "1");
+    assert_eq!(to_string(f, 0.95, Minus,  1, false), "0.9"); // because it really is less than 0.95
+    assert_eq!(to_string(f, 0.95, Minus,  2, false), "0.95");
+    assert_eq!(to_string(f, 0.95, Minus,  3, false), "0.950");
+    assert_eq!(to_string(f, 0.95, Minus, 10, false), "0.9500000000");
+    assert_eq!(to_string(f, 0.95, Minus, 30, false), "0.949999999999999955591079014994");
+
+    assert_eq!(to_string(f, 0.095, Minus,  0, false), "0");
+    assert_eq!(to_string(f, 0.095, Minus,  1, false), "0.1");
+    assert_eq!(to_string(f, 0.095, Minus,  2, false), "0.10");
+    assert_eq!(to_string(f, 0.095, Minus,  3, false), "0.095");
+    assert_eq!(to_string(f, 0.095, Minus,  4, false), "0.0950");
+    assert_eq!(to_string(f, 0.095, Minus, 10, false), "0.0950000000");
+    assert_eq!(to_string(f, 0.095, Minus, 30, false), "0.095000000000000001110223024625");
+
+    assert_eq!(to_string(f, 0.0095, Minus,  0, false), "0");
+    assert_eq!(to_string(f, 0.0095, Minus,  1, false), "0.0");
+    assert_eq!(to_string(f, 0.0095, Minus,  2, false), "0.01");
+    assert_eq!(to_string(f, 0.0095, Minus,  3, false), "0.009"); // really is less than 0.0095
+    assert_eq!(to_string(f, 0.0095, Minus,  4, false), "0.0095");
+    assert_eq!(to_string(f, 0.0095, Minus,  5, false), "0.00950");
+    assert_eq!(to_string(f, 0.0095, Minus, 10, false), "0.0095000000");
+    assert_eq!(to_string(f, 0.0095, Minus, 30, false), "0.009499999999999999764077607267");
+
+    assert_eq!(to_string(f, 7.5e-11, Minus,  0, false), "0");
+    assert_eq!(to_string(f, 7.5e-11, Minus,  3, false), "0.000");
+    assert_eq!(to_string(f, 7.5e-11, Minus, 10, false), "0.0000000001");
+    assert_eq!(to_string(f, 7.5e-11, Minus, 11, false), "0.00000000007"); // ditto
+    assert_eq!(to_string(f, 7.5e-11, Minus, 12, false), "0.000000000075");
+    assert_eq!(to_string(f, 7.5e-11, Minus, 13, false), "0.0000000000750");
+    assert_eq!(to_string(f, 7.5e-11, Minus, 20, false), "0.00000000007500000000");
+    assert_eq!(to_string(f, 7.5e-11, Minus, 30, false), "0.000000000074999999999999999501");
+
+    assert_eq!(to_string(f, 1.0e25, Minus, 0, false), "10000000000000000905969664");
+    assert_eq!(to_string(f, 1.0e25, Minus, 1, false), "10000000000000000905969664.0");
+    assert_eq!(to_string(f, 1.0e25, Minus, 3, false), "10000000000000000905969664.000");
+
+    assert_eq!(to_string(f, 1.0e-6, Minus,  0, false), "0");
+    assert_eq!(to_string(f, 1.0e-6, Minus,  3, false), "0.000");
+    assert_eq!(to_string(f, 1.0e-6, Minus,  6, false), "0.000001");
+    assert_eq!(to_string(f, 1.0e-6, Minus,  9, false), "0.000001000");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 12, false), "0.000001000000");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 22, false), "0.0000010000000000000000");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 23, false), "0.00000099999999999999995");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 24, false), "0.000000999999999999999955");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 25, false), "0.0000009999999999999999547");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 35, false), "0.00000099999999999999995474811182589");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 45, false),
+               "0.000000999999999999999954748111825886258685614");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 55, false),
+               "0.0000009999999999999999547481118258862586856139387236908");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 65, false),
+               "0.00000099999999999999995474811182588625868561393872369080781936646");
+    assert_eq!(to_string(f, 1.0e-6, Minus, 75, false),
+               "0.000000999999999999999954748111825886258685613938723690807819366455078125000");
+
+    assert_eq!(to_string(f, f32::MAX, Minus, 0, false),
+               "340282346638528859811704183484516925440");
+    assert_eq!(to_string(f, f32::MAX, Minus, 1, false),
+               "340282346638528859811704183484516925440.0");
+    assert_eq!(to_string(f, f32::MAX, Minus, 2, false),
+               "340282346638528859811704183484516925440.00");
+
+    let minf32 = ldexp_f32(1.0, -149);
+    assert_eq!(to_string(f, minf32, Minus,   0, false), "0");
+    assert_eq!(to_string(f, minf32, Minus,   1, false), "0.0");
+    assert_eq!(to_string(f, minf32, Minus,   2, false), "0.00");
+    assert_eq!(to_string(f, minf32, Minus,   4, false), "0.0000");
+    assert_eq!(to_string(f, minf32, Minus,   8, false), "0.00000000");
+    assert_eq!(to_string(f, minf32, Minus,  16, false), "0.0000000000000000");
+    assert_eq!(to_string(f, minf32, Minus,  32, false), "0.00000000000000000000000000000000");
+    assert_eq!(to_string(f, minf32, Minus,  64, false),
+               "0.0000000000000000000000000000000000000000000014012984643248170709");
+    assert_eq!(to_string(f, minf32, Minus, 128, false),
+               "0.0000000000000000000000000000000000000000000014012984643248170709\
+                  2372958328991613128026194187651577175706828388979108268586060149");
+    assert_eq!(to_string(f, minf32, Minus, 256, false),
+               "0.0000000000000000000000000000000000000000000014012984643248170709\
+                  2372958328991613128026194187651577175706828388979108268586060148\
+                  6638188362121582031250000000000000000000000000000000000000000000\
+                  0000000000000000000000000000000000000000000000000000000000000000");
+
+    assert_eq!(to_string(f, f64::MAX, Minus, 0, false),
+               "1797693134862315708145274237317043567980705675258449965989174768\
+                0315726078002853876058955863276687817154045895351438246423432132\
+                6889464182768467546703537516986049910576551282076245490090389328\
+                9440758685084551339423045832369032229481658085593321233482747978\
+                26204144723168738177180919299881250404026184124858368");
+    assert_eq!(to_string(f, f64::MAX, Minus, 10, false),
+               "1797693134862315708145274237317043567980705675258449965989174768\
+                0315726078002853876058955863276687817154045895351438246423432132\
+                6889464182768467546703537516986049910576551282076245490090389328\
+                9440758685084551339423045832369032229481658085593321233482747978\
+                26204144723168738177180919299881250404026184124858368.0000000000");
+
+    let minf64 = ldexp_f64(1.0, -1074);
+    assert_eq!(to_string(f, minf64, Minus, 0, false), "0");
+    assert_eq!(to_string(f, minf64, Minus, 1, false), "0.0");
+    assert_eq!(to_string(f, minf64, Minus, 10, false), "0.0000000000");
+    assert_eq!(to_string(f, minf64, Minus, 100, false),
+               "0.0000000000000000000000000000000000000000000000000000000000000000\
+                  000000000000000000000000000000000000");
+    assert_eq!(to_string(f, minf64, Minus, 1000, false),
+               "0.0000000000000000000000000000000000000000000000000000000000000000\
+                  0000000000000000000000000000000000000000000000000000000000000000\
+                  0000000000000000000000000000000000000000000000000000000000000000\
+                  0000000000000000000000000000000000000000000000000000000000000000\
+                  0000000000000000000000000000000000000000000000000000000000000000\
+                  0004940656458412465441765687928682213723650598026143247644255856\
+                  8250067550727020875186529983636163599237979656469544571773092665\
+                  6710355939796398774796010781878126300713190311404527845817167848\
+                  9821036887186360569987307230500063874091535649843873124733972731\
+                  6961514003171538539807412623856559117102665855668676818703956031\
+                  0624931945271591492455329305456544401127480129709999541931989409\
+                  0804165633245247571478690147267801593552386115501348035264934720\
+                  1937902681071074917033322268447533357208324319360923828934583680\
+                  6010601150616980975307834227731832924790498252473077637592724787\
+                  4656084778203734469699533647017972677717585125660551199131504891\
+                  1014510378627381672509558373897335989937");
+
+    // very large output
+    assert_eq!(to_string(f, 0.0,     Minus, 80000, false), format!("0.{:0>80000}", ""));
+    assert_eq!(to_string(f, 1.0e1,   Minus, 80000, false), format!("10.{:0>80000}", ""));
+    assert_eq!(to_string(f, 1.0e0,   Minus, 80000, false), format!("1.{:0>80000}", ""));
+    assert_eq!(to_string(f, 1.0e-1,  Minus, 80000, false),
+               format!("0.1000000000000000055511151231257827021181583404541015625{:0>79945}", ""));
+    assert_eq!(to_string(f, 1.0e-20, Minus, 80000, false),
+               format!("0.0000000000000000000099999999999999994515327145420957165172950370\
+                          2787392447107715776066783064379706047475337982177734375{:0>79881}", ""));
+}
+
diff --git a/src/libcore/tests/num/flt2dec/strategy/dragon.rs b/src/libcore/tests/num/flt2dec/strategy/dragon.rs
new file mode 100644
index 00000000000..4edb0f3df60
--- /dev/null
+++ b/src/libcore/tests/num/flt2dec/strategy/dragon.rs
@@ -0,0 +1,74 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::prelude::v1::*;
+use super::super::*;
+use core::num::bignum::Big32x40 as Big;
+use core::num::flt2dec::strategy::dragon::*;
+
+#[test]
+fn test_mul_pow10() {
+    let mut prevpow10 = Big::from_small(1);
+    for i in 1..340 {
+        let mut curpow10 = Big::from_small(1);
+        mul_pow10(&mut curpow10, i);
+        assert_eq!(curpow10, *prevpow10.clone().mul_small(10));
+        prevpow10 = curpow10;
+    }
+}
+
+#[test]
+fn shortest_sanity_test() {
+    f64_shortest_sanity_test(format_shortest);
+    f32_shortest_sanity_test(format_shortest);
+    more_shortest_sanity_test(format_shortest);
+}
+
+#[test]
+fn exact_sanity_test() {
+    // This test ends up running what I can only assume is some corner-ish case
+    // of the `exp2` library function, defined in whatever C runtime we're
+    // using. In VS 2013 this function apparently had a bug as this test fails
+    // when linked, but with VS 2015 the bug appears fixed as the test runs just
+    // fine.
+    //
+    // The bug seems to be a difference in return value of `exp2(-1057)`, where
+    // in VS 2013 it returns a double with the bit pattern 0x2 and in VS 2015 it
+    // returns 0x20000.
+    //
+    // For now just ignore this test entirely on MSVC as it's tested elsewhere
+    // anyway and we're not super interested in testing each platform's exp2
+    // implementation.
+    if !cfg!(target_env = "msvc") {
+        f64_exact_sanity_test(format_exact);
+    }
+    f32_exact_sanity_test(format_exact);
+}
+
+#[test]
+fn test_to_shortest_str() {
+    to_shortest_str_test(format_shortest);
+}
+
+#[test]
+fn test_to_shortest_exp_str() {
+    to_shortest_exp_str_test(format_shortest);
+}
+
+#[test]
+fn test_to_exact_exp_str() {
+    to_exact_exp_str_test(format_exact);
+}
+
+#[test]
+fn test_to_exact_fixed_str() {
+    to_exact_fixed_str_test(format_exact);
+}
+
diff --git a/src/libcore/tests/num/flt2dec/strategy/grisu.rs b/src/libcore/tests/num/flt2dec/strategy/grisu.rs
new file mode 100644
index 00000000000..79e66ee669e
--- /dev/null
+++ b/src/libcore/tests/num/flt2dec/strategy/grisu.rs
@@ -0,0 +1,124 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::i16;
+use super::super::*;
+use core::num::flt2dec::strategy::grisu::*;
+
+#[test]
+fn test_cached_power() {
+    assert_eq!(CACHED_POW10.first().unwrap().1, CACHED_POW10_FIRST_E);
+    assert_eq!(CACHED_POW10.last().unwrap().1, CACHED_POW10_LAST_E);
+
+    for e in -1137..961 { // full range for f64
+        let low = ALPHA - e - 64;
+        let high = GAMMA - e - 64;
+        let (_k, cached) = cached_power(low, high);
+        assert!(low <= cached.e && cached.e <= high,
+                "cached_power({}, {}) = {:?} is incorrect", low, high, cached);
+    }
+}
+
+#[test]
+fn test_max_pow10_no_more_than() {
+    let mut prevtenk = 1;
+    for k in 1..10 {
+        let tenk = prevtenk * 10;
+        assert_eq!(max_pow10_no_more_than(tenk - 1), (k - 1, prevtenk));
+        assert_eq!(max_pow10_no_more_than(tenk), (k, tenk));
+        prevtenk = tenk;
+    }
+}
+
+
+#[test]
+fn shortest_sanity_test() {
+    f64_shortest_sanity_test(format_shortest);
+    f32_shortest_sanity_test(format_shortest);
+    more_shortest_sanity_test(format_shortest);
+}
+
+#[test]
+fn shortest_random_equivalence_test() {
+    use core::num::flt2dec::strategy::dragon::format_shortest as fallback;
+    f64_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, 10_000);
+    f32_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, 10_000);
+}
+
+#[test] #[ignore] // it is too expensive
+fn shortest_f32_exhaustive_equivalence_test() {
+    // it is hard to directly test the optimality of the output, but we can at least test if
+    // two different algorithms agree to each other.
+    //
+    // this reports the progress and the number of f32 values returned `None`.
+    // with `--nocapture` (and plenty of time and appropriate rustc flags), this should print:
+    // `done, ignored=17643158 passed=2121451881 failed=0`.
+
+    use core::num::flt2dec::strategy::dragon::format_shortest as fallback;
+    f32_exhaustive_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS);
+}
+
+#[test] #[ignore] // it is too expensive
+fn shortest_f64_hard_random_equivalence_test() {
+    // this again probably has to use appropriate rustc flags.
+
+    use core::num::flt2dec::strategy::dragon::format_shortest as fallback;
+    f64_random_equivalence_test(format_shortest_opt, fallback,
+                                         MAX_SIG_DIGITS, 100_000_000);
+}
+
+#[test]
+fn exact_sanity_test() {
+    // See comments in dragon.rs's exact_sanity_test for why this test is
+    // ignored on MSVC
+    if !cfg!(target_env = "msvc") {
+        f64_exact_sanity_test(format_exact);
+    }
+    f32_exact_sanity_test(format_exact);
+}
+
+#[test]
+fn exact_f32_random_equivalence_test() {
+    use core::num::flt2dec::strategy::dragon::format_exact as fallback;
+    for k in 1..21 {
+        f32_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN),
+                                             |d, buf| fallback(d, buf, i16::MIN), k, 1_000);
+    }
+}
+
+#[test]
+fn exact_f64_random_equivalence_test() {
+    use core::num::flt2dec::strategy::dragon::format_exact as fallback;
+    for k in 1..21 {
+        f64_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN),
+                                             |d, buf| fallback(d, buf, i16::MIN), k, 1_000);
+    }
+}
+
+#[test]
+fn test_to_shortest_str() {
+    to_shortest_str_test(format_shortest);
+}
+
+#[test]
+fn test_to_shortest_exp_str() {
+    to_shortest_exp_str_test(format_shortest);
+}
+
+#[test]
+fn test_to_exact_exp_str() {
+    to_exact_exp_str_test(format_exact);
+}
+
+#[test]
+fn test_to_exact_fixed_str() {
+    to_exact_fixed_str_test(format_exact);
+}
+
diff --git a/src/libcore/tests/num/i16.rs b/src/libcore/tests/num/i16.rs
new file mode 100644
index 00000000000..7435831ac6d
--- /dev/null
+++ b/src/libcore/tests/num/i16.rs
@@ -0,0 +1,11 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+int_module!(i16, i16);
diff --git a/src/libcore/tests/num/i32.rs b/src/libcore/tests/num/i32.rs
new file mode 100644
index 00000000000..3b3407e1ada
--- /dev/null
+++ b/src/libcore/tests/num/i32.rs
@@ -0,0 +1,11 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+int_module!(i32, i32);
diff --git a/src/libcore/tests/num/i64.rs b/src/libcore/tests/num/i64.rs
new file mode 100644
index 00000000000..9e1aec256ee
--- /dev/null
+++ b/src/libcore/tests/num/i64.rs
@@ -0,0 +1,11 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+int_module!(i64, i64);
diff --git a/src/libcore/tests/num/i8.rs b/src/libcore/tests/num/i8.rs
new file mode 100644
index 00000000000..f72244239b2
--- /dev/null
+++ b/src/libcore/tests/num/i8.rs
@@ -0,0 +1,11 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+int_module!(i8, i8);
diff --git a/src/libcore/tests/num/int_macros.rs b/src/libcore/tests/num/int_macros.rs
new file mode 100644
index 00000000000..8d791283ab8
--- /dev/null
+++ b/src/libcore/tests/num/int_macros.rs
@@ -0,0 +1,219 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! int_module { ($T:ident, $T_i:ident) => (
+#[cfg(test)]
+mod tests {
+    use core::$T_i::*;
+    use core::isize;
+    use core::ops::{Shl, Shr, Not, BitXor, BitAnd, BitOr};
+    use core::mem;
+
+    use num;
+
+    #[test]
+    fn test_overflows() {
+        assert!(MAX > 0);
+        assert!(MIN <= 0);
+        assert!(MIN + MAX + 1 == 0);
+    }
+
+    #[test]
+    fn test_num() {
+        num::test_num(10 as $T, 2 as $T);
+    }
+
+    #[test]
+    pub fn test_abs() {
+        assert!((1 as $T).abs() == 1 as $T);
+        assert!((0 as $T).abs() == 0 as $T);
+        assert!((-1 as $T).abs() == 1 as $T);
+    }
+
+    #[test]
+    fn test_signum() {
+        assert!((1 as $T).signum() == 1 as $T);
+        assert!((0 as $T).signum() == 0 as $T);
+        assert!((-0 as $T).signum() == 0 as $T);
+        assert!((-1 as $T).signum() == -1 as $T);
+    }
+
+    #[test]
+    fn test_is_positive() {
+        assert!((1 as $T).is_positive());
+        assert!(!(0 as $T).is_positive());
+        assert!(!(-0 as $T).is_positive());
+        assert!(!(-1 as $T).is_positive());
+    }
+
+    #[test]
+    fn test_is_negative() {
+        assert!(!(1 as $T).is_negative());
+        assert!(!(0 as $T).is_negative());
+        assert!(!(-0 as $T).is_negative());
+        assert!((-1 as $T).is_negative());
+    }
+
+    #[test]
+    fn test_bitwise_operators() {
+        assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T));
+        assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T));
+        assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T));
+        assert!(0b1110 as $T == (0b0111 as $T).shl(1));
+        assert!(0b0111 as $T == (0b1110 as $T).shr(1));
+        assert!(-(0b11 as $T) - (1 as $T) == (0b11 as $T).not());
+    }
+
+    const A: $T = 0b0101100;
+    const B: $T = 0b0100001;
+    const C: $T = 0b1111001;
+
+    const _0: $T = 0;
+    const _1: $T = !0;
+
+    #[test]
+    fn test_count_ones() {
+        assert!(A.count_ones() == 3);
+        assert!(B.count_ones() == 2);
+        assert!(C.count_ones() == 5);
+    }
+
+    #[test]
+    fn test_count_zeros() {
+        let bits = mem::size_of::<$T>() * 8;
+        assert!(A.count_zeros() == bits as u32 - 3);
+        assert!(B.count_zeros() == bits as u32 - 2);
+        assert!(C.count_zeros() == bits as u32 - 5);
+    }
+
+    #[test]
+    fn test_rotate() {
+        assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
+        assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B);
+        assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C);
+
+        // Rotating these should make no difference
+        //
+        // We test using 124 bits because to ensure that overlong bit shifts do
+        // not cause undefined behaviour. See #10183.
+        assert_eq!(_0.rotate_left(124), _0);
+        assert_eq!(_1.rotate_left(124), _1);
+        assert_eq!(_0.rotate_right(124), _0);
+        assert_eq!(_1.rotate_right(124), _1);
+
+        // Rotating by 0 should have no effect
+        assert_eq!(A.rotate_left(0), A);
+        assert_eq!(B.rotate_left(0), B);
+        assert_eq!(C.rotate_left(0), C);
+        // Rotating by a multiple of word size should also have no effect
+        assert_eq!(A.rotate_left(64), A);
+        assert_eq!(B.rotate_left(64), B);
+        assert_eq!(C.rotate_left(64), C);
+    }
+
+    #[test]
+    fn test_swap_bytes() {
+        assert_eq!(A.swap_bytes().swap_bytes(), A);
+        assert_eq!(B.swap_bytes().swap_bytes(), B);
+        assert_eq!(C.swap_bytes().swap_bytes(), C);
+
+        // Swapping these should make no difference
+        assert_eq!(_0.swap_bytes(), _0);
+        assert_eq!(_1.swap_bytes(), _1);
+    }
+
+    #[test]
+    fn test_le() {
+        assert_eq!($T::from_le(A.to_le()), A);
+        assert_eq!($T::from_le(B.to_le()), B);
+        assert_eq!($T::from_le(C.to_le()), C);
+        assert_eq!($T::from_le(_0), _0);
+        assert_eq!($T::from_le(_1), _1);
+        assert_eq!(_0.to_le(), _0);
+        assert_eq!(_1.to_le(), _1);
+    }
+
+    #[test]
+    fn test_be() {
+        assert_eq!($T::from_be(A.to_be()), A);
+        assert_eq!($T::from_be(B.to_be()), B);
+        assert_eq!($T::from_be(C.to_be()), C);
+        assert_eq!($T::from_be(_0), _0);
+        assert_eq!($T::from_be(_1), _1);
+        assert_eq!(_0.to_be(), _0);
+        assert_eq!(_1.to_be(), _1);
+    }
+
+    #[test]
+    fn test_signed_checked_div() {
+        assert!((10 as $T).checked_div(2) == Some(5));
+        assert!((5 as $T).checked_div(0) == None);
+        assert!(isize::MIN.checked_div(-1) == None);
+    }
+
+    #[test]
+    fn test_from_str() {
+        fn from_str<T: ::std::str::FromStr>(t: &str) -> Option<T> {
+            ::std::str::FromStr::from_str(t).ok()
+        }
+        assert_eq!(from_str::<$T>("0"), Some(0 as $T));
+        assert_eq!(from_str::<$T>("3"), Some(3 as $T));
+        assert_eq!(from_str::<$T>("10"), Some(10 as $T));
+        assert_eq!(from_str::<i32>("123456789"), Some(123456789 as i32));
+        assert_eq!(from_str::<$T>("00100"), Some(100 as $T));
+
+        assert_eq!(from_str::<$T>("-1"), Some(-1 as $T));
+        assert_eq!(from_str::<$T>("-3"), Some(-3 as $T));
+        assert_eq!(from_str::<$T>("-10"), Some(-10 as $T));
+        assert_eq!(from_str::<i32>("-123456789"), Some(-123456789 as i32));
+        assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T));
+
+        assert_eq!(from_str::<$T>(""), None);
+        assert_eq!(from_str::<$T>(" "), None);
+        assert_eq!(from_str::<$T>("x"), None);
+    }
+
+    #[test]
+    fn test_from_str_radix() {
+        assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T));
+        assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T));
+        assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T));
+        assert_eq!(i32::from_str_radix("123", 16), Ok(291 as i32));
+        assert_eq!(i32::from_str_radix("ffff", 16), Ok(65535 as i32));
+        assert_eq!(i32::from_str_radix("FFFF", 16), Ok(65535 as i32));
+        assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T));
+        assert_eq!($T::from_str_radix("Z", 36), Ok(35 as $T));
+
+        assert_eq!($T::from_str_radix("-123", 10), Ok(-123 as $T));
+        assert_eq!($T::from_str_radix("-1001", 2), Ok(-9 as $T));
+        assert_eq!($T::from_str_radix("-123", 8), Ok(-83 as $T));
+        assert_eq!(i32::from_str_radix("-123", 16), Ok(-291 as i32));
+        assert_eq!(i32::from_str_radix("-ffff", 16), Ok(-65535 as i32));
+        assert_eq!(i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32));
+        assert_eq!($T::from_str_radix("-z", 36), Ok(-35 as $T));
+        assert_eq!($T::from_str_radix("-Z", 36), Ok(-35 as $T));
+
+        assert_eq!($T::from_str_radix("Z", 35).ok(), None::<$T>);
+        assert_eq!($T::from_str_radix("-9", 2).ok(), None::<$T>);
+    }
+
+    #[test]
+    fn test_pow() {
+        let mut r = 2 as $T;
+
+        assert_eq!(r.pow(2), 4 as $T);
+        assert_eq!(r.pow(0), 1 as $T);
+        r = -2 as $T;
+        assert_eq!(r.pow(2), 4 as $T);
+        assert_eq!(r.pow(3), -8 as $T);
+    }
+}
+
+)}
diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs
new file mode 100644
index 00000000000..51737c9c3b4
--- /dev/null
+++ b/src/libcore/tests/num/mod.rs
@@ -0,0 +1,400 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::convert::TryFrom;
+use core::cmp::PartialEq;
+use core::fmt::Debug;
+use core::marker::Copy;
+use core::ops::{Add, Sub, Mul, Div, Rem};
+use core::option::Option;
+use core::option::Option::{Some, None};
+
+#[macro_use]
+mod int_macros;
+
+mod i8;
+mod i16;
+mod i32;
+mod i64;
+
+#[macro_use]
+mod uint_macros;
+
+mod u8;
+mod u16;
+mod u32;
+mod u64;
+
+mod flt2dec;
+mod dec2flt;
+mod bignum;
+
+/// Helper function for testing numeric operations
+pub fn test_num<T>(ten: T, two: T) where
+    T: PartialEq
+     + Add<Output=T> + Sub<Output=T>
+     + Mul<Output=T> + Div<Output=T>
+     + Rem<Output=T> + Debug
+     + Copy
+{
+    assert_eq!(ten.add(two),  ten + two);
+    assert_eq!(ten.sub(two),  ten - two);
+    assert_eq!(ten.mul(two),  ten * two);
+    assert_eq!(ten.div(two),  ten / two);
+    assert_eq!(ten.rem(two),  ten % two);
+}
+
+#[test]
+fn from_str_issue7588() {
+    let u : Option<u8> = u8::from_str_radix("1000", 10).ok();
+    assert_eq!(u, None);
+    let s : Option<i16> = i16::from_str_radix("80000", 10).ok();
+    assert_eq!(s, None);
+}
+
+#[test]
+fn test_int_from_str_overflow() {
+    let mut i8_val: i8 = 127;
+    assert_eq!("127".parse::<i8>().ok(), Some(i8_val));
+    assert_eq!("128".parse::<i8>().ok(), None);
+
+    i8_val = i8_val.wrapping_add(1);
+    assert_eq!("-128".parse::<i8>().ok(), Some(i8_val));
+    assert_eq!("-129".parse::<i8>().ok(), None);
+
+    let mut i16_val: i16 = 32_767;
+    assert_eq!("32767".parse::<i16>().ok(), Some(i16_val));
+    assert_eq!("32768".parse::<i16>().ok(), None);
+
+    i16_val = i16_val.wrapping_add(1);
+    assert_eq!("-32768".parse::<i16>().ok(), Some(i16_val));
+    assert_eq!("-32769".parse::<i16>().ok(), None);
+
+    let mut i32_val: i32 = 2_147_483_647;
+    assert_eq!("2147483647".parse::<i32>().ok(), Some(i32_val));
+    assert_eq!("2147483648".parse::<i32>().ok(), None);
+
+    i32_val = i32_val.wrapping_add(1);
+    assert_eq!("-2147483648".parse::<i32>().ok(), Some(i32_val));
+    assert_eq!("-2147483649".parse::<i32>().ok(), None);
+
+    let mut i64_val: i64 = 9_223_372_036_854_775_807;
+    assert_eq!("9223372036854775807".parse::<i64>().ok(), Some(i64_val));
+    assert_eq!("9223372036854775808".parse::<i64>().ok(), None);
+
+    i64_val = i64_val.wrapping_add(1);
+    assert_eq!("-9223372036854775808".parse::<i64>().ok(), Some(i64_val));
+    assert_eq!("-9223372036854775809".parse::<i64>().ok(), None);
+}
+
+#[test]
+fn test_leading_plus() {
+    assert_eq!("+127".parse::<u8>().ok(), Some(127));
+    assert_eq!("+9223372036854775807".parse::<i64>().ok(), Some(9223372036854775807));
+}
+
+#[test]
+fn test_invalid() {
+    assert_eq!("--129".parse::<i8>().ok(), None);
+    assert_eq!("++129".parse::<i8>().ok(), None);
+    assert_eq!("Съешь".parse::<u8>().ok(), None);
+}
+
+#[test]
+fn test_empty() {
+    assert_eq!("-".parse::<i8>().ok(), None);
+    assert_eq!("+".parse::<i8>().ok(), None);
+    assert_eq!("".parse::<u8>().ok(), None);
+}
+
+macro_rules! test_impl_from {
+    ($fn_name: ident, $Small: ty, $Large: ty) => {
+        #[test]
+        fn $fn_name() {
+            let small_max = <$Small>::max_value();
+            let small_min = <$Small>::min_value();
+            let large_max: $Large = small_max.into();
+            let large_min: $Large = small_min.into();
+            assert_eq!(large_max as $Small, small_max);
+            assert_eq!(large_min as $Small, small_min);
+        }
+    }
+}
+
+// Unsigned -> Unsigned
+test_impl_from! { test_u8u16, u8, u16 }
+test_impl_from! { test_u8u32, u8, u32 }
+test_impl_from! { test_u8u64, u8, u64 }
+test_impl_from! { test_u8usize, u8, usize }
+test_impl_from! { test_u16u32, u16, u32 }
+test_impl_from! { test_u16u64, u16, u64 }
+test_impl_from! { test_u32u64, u32, u64 }
+
+// Signed -> Signed
+test_impl_from! { test_i8i16, i8, i16 }
+test_impl_from! { test_i8i32, i8, i32 }
+test_impl_from! { test_i8i64, i8, i64 }
+test_impl_from! { test_i8isize, i8, isize }
+test_impl_from! { test_i16i32, i16, i32 }
+test_impl_from! { test_i16i64, i16, i64 }
+test_impl_from! { test_i32i64, i32, i64 }
+
+// Unsigned -> Signed
+test_impl_from! { test_u8i16, u8, i16 }
+test_impl_from! { test_u8i32, u8, i32 }
+test_impl_from! { test_u8i64, u8, i64 }
+test_impl_from! { test_u16i32, u16, i32 }
+test_impl_from! { test_u16i64, u16, i64 }
+test_impl_from! { test_u32i64, u32, i64 }
+
+// Signed -> Float
+test_impl_from! { test_i8f32, i8, f32 }
+test_impl_from! { test_i8f64, i8, f64 }
+test_impl_from! { test_i16f32, i16, f32 }
+test_impl_from! { test_i16f64, i16, f64 }
+test_impl_from! { test_i32f64, i32, f64 }
+
+// Unsigned -> Float
+test_impl_from! { test_u8f32, u8, f32 }
+test_impl_from! { test_u8f64, u8, f64 }
+test_impl_from! { test_u16f32, u16, f32 }
+test_impl_from! { test_u16f64, u16, f64 }
+test_impl_from! { test_u32f64, u32, f64 }
+
+// Float -> Float
+#[test]
+fn test_f32f64() {
+    use core::f32;
+
+    let max: f64 = f32::MAX.into();
+    assert_eq!(max as f32, f32::MAX);
+    assert!(max.is_normal());
+
+    let min: f64 = f32::MIN.into();
+    assert_eq!(min as f32, f32::MIN);
+    assert!(min.is_normal());
+
+    let min_positive: f64 = f32::MIN_POSITIVE.into();
+    assert_eq!(min_positive as f32, f32::MIN_POSITIVE);
+    assert!(min_positive.is_normal());
+
+    let epsilon: f64 = f32::EPSILON.into();
+    assert_eq!(epsilon as f32, f32::EPSILON);
+    assert!(epsilon.is_normal());
+
+    let zero: f64 = (0.0f32).into();
+    assert_eq!(zero as f32, 0.0f32);
+    assert!(zero.is_sign_positive());
+
+    let neg_zero: f64 = (-0.0f32).into();
+    assert_eq!(neg_zero as f32, -0.0f32);
+    assert!(neg_zero.is_sign_negative());
+
+    let infinity: f64 = f32::INFINITY.into();
+    assert_eq!(infinity as f32, f32::INFINITY);
+    assert!(infinity.is_infinite());
+    assert!(infinity.is_sign_positive());
+
+    let neg_infinity: f64 = f32::NEG_INFINITY.into();
+    assert_eq!(neg_infinity as f32, f32::NEG_INFINITY);
+    assert!(neg_infinity.is_infinite());
+    assert!(neg_infinity.is_sign_negative());
+
+    let nan: f64 = f32::NAN.into();
+    assert!(nan.is_nan());
+}
+
+macro_rules! test_impl_try_from_always_ok {
+    ($fn_name:ident, $source:ty, $target: ty) => {
+        #[test]
+        fn $fn_name() {
+            let max = <$source>::max_value();
+            let min = <$source>::min_value();
+            let zero: $source = 0;
+            assert_eq!(<$target as TryFrom<$source>>::try_from(max).unwrap(),
+                       max as $target);
+            assert_eq!(<$target as TryFrom<$source>>::try_from(min).unwrap(),
+                       min as $target);
+            assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(),
+                       zero as $target);
+        }
+    }
+}
+
+test_impl_try_from_always_ok! { test_try_u8u8, u8, u8 }
+test_impl_try_from_always_ok! { test_try_u8u16, u8, u16 }
+test_impl_try_from_always_ok! { test_try_u8u32, u8, u32 }
+test_impl_try_from_always_ok! { test_try_u8u64, u8, u64 }
+test_impl_try_from_always_ok! { test_try_u8i16, u8, i16 }
+test_impl_try_from_always_ok! { test_try_u8i32, u8, i32 }
+test_impl_try_from_always_ok! { test_try_u8i64, u8, i64 }
+
+test_impl_try_from_always_ok! { test_try_u16u16, u16, u16 }
+test_impl_try_from_always_ok! { test_try_u16u32, u16, u32 }
+test_impl_try_from_always_ok! { test_try_u16u64, u16, u64 }
+test_impl_try_from_always_ok! { test_try_u16i32, u16, i32 }
+test_impl_try_from_always_ok! { test_try_u16i64, u16, i64 }
+
+test_impl_try_from_always_ok! { test_try_u32u32, u32, u32 }
+test_impl_try_from_always_ok! { test_try_u32u64, u32, u64 }
+test_impl_try_from_always_ok! { test_try_u32i64, u32, i64 }
+
+test_impl_try_from_always_ok! { test_try_u64u64, u64, u64 }
+
+test_impl_try_from_always_ok! { test_try_i8i8, i8, i8 }
+test_impl_try_from_always_ok! { test_try_i8i16, i8, i16 }
+test_impl_try_from_always_ok! { test_try_i8i32, i8, i32 }
+test_impl_try_from_always_ok! { test_try_i8i64, i8, i64 }
+
+test_impl_try_from_always_ok! { test_try_i16i16, i16, i16 }
+test_impl_try_from_always_ok! { test_try_i16i32, i16, i32 }
+test_impl_try_from_always_ok! { test_try_i16i64, i16, i64 }
+
+test_impl_try_from_always_ok! { test_try_i32i32, i32, i32 }
+test_impl_try_from_always_ok! { test_try_i32i64, i32, i64 }
+
+test_impl_try_from_always_ok! { test_try_i64i64, i64, i64 }
+
+macro_rules! test_impl_try_from_signed_to_unsigned_upper_ok {
+    ($fn_name:ident, $source:ty, $target:ty) => {
+        #[test]
+        fn $fn_name() {
+            let max = <$source>::max_value();
+            let min = <$source>::min_value();
+            let zero: $source = 0;
+            let neg_one: $source = -1;
+            assert_eq!(<$target as TryFrom<$source>>::try_from(max).unwrap(),
+                       max as $target);
+            assert!(<$target as TryFrom<$source>>::try_from(min).is_err());
+            assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(),
+                       zero as $target);
+            assert!(<$target as TryFrom<$source>>::try_from(neg_one).is_err());
+        }
+    }
+}
+
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u8, i8, u8 }
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u16, i8, u16 }
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u32, i8, u32 }
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u64, i8, u64 }
+
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i16u16, i16, u16 }
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i16u32, i16, u32 }
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i16u64, i16, u64 }
+
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i32u32, i32, u32 }
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i32u64, i32, u64 }
+
+test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i64u64, i64, u64 }
+
+macro_rules! test_impl_try_from_unsigned_to_signed_upper_err {
+    ($fn_name:ident, $source:ty, $target:ty) => {
+        #[test]
+        fn $fn_name() {
+            let max = <$source>::max_value();
+            let min = <$source>::min_value();
+            let zero: $source = 0;
+            assert!(<$target as TryFrom<$source>>::try_from(max).is_err());
+            assert_eq!(<$target as TryFrom<$source>>::try_from(min).unwrap(),
+                       min as $target);
+            assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(),
+                       zero as $target);
+        }
+    }
+}
+
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u8i8, u8, i8 }
+
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u16i8, u16, i8 }
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u16i16, u16, i16 }
+
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32i8, u32, i8 }
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32i16, u32, i16 }
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32i32, u32, i32 }
+
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i8, u64, i8 }
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i16, u64, i16 }
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i32, u64, i32 }
+test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i64, u64, i64 }
+
+macro_rules! test_impl_try_from_same_sign_err {
+    ($fn_name:ident, $source:ty, $target:ty) => {
+        #[test]
+        fn $fn_name() {
+            let max = <$source>::max_value();
+            let min = <$source>::min_value();
+            let zero: $source = 0;
+            let t_max = <$target>::max_value();
+            let t_min = <$target>::min_value();
+            assert!(<$target as TryFrom<$source>>::try_from(max).is_err());
+            if min != 0 {
+                assert!(<$target as TryFrom<$source>>::try_from(min).is_err());
+            }
+            assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(),
+                       zero as $target);
+            assert_eq!(<$target as TryFrom<$source>>::try_from(t_max as $source)
+                            .unwrap(),
+                       t_max as $target);
+            assert_eq!(<$target as TryFrom<$source>>::try_from(t_min as $source)
+                            .unwrap(),
+                       t_min as $target);
+        }
+    }
+}
+
+test_impl_try_from_same_sign_err! { test_try_u16u8, u16, u8 }
+
+test_impl_try_from_same_sign_err! { test_try_u32u8, u32, u8 }
+test_impl_try_from_same_sign_err! { test_try_u32u16, u32, u16 }
+
+test_impl_try_from_same_sign_err! { test_try_u64u8, u64, u8 }
+test_impl_try_from_same_sign_err! { test_try_u64u16, u64, u16 }
+test_impl_try_from_same_sign_err! { test_try_u64u32, u64, u32 }
+
+test_impl_try_from_same_sign_err! { test_try_i16i8, i16, i8 }
+
+test_impl_try_from_same_sign_err! { test_try_i32i8, i32, i8 }
+test_impl_try_from_same_sign_err! { test_try_i32i16, i32, i16 }
+
+test_impl_try_from_same_sign_err! { test_try_i64i8, i64, i8 }
+test_impl_try_from_same_sign_err! { test_try_i64i16, i64, i16 }
+test_impl_try_from_same_sign_err! { test_try_i64i32, i64, i32 }
+
+macro_rules! test_impl_try_from_signed_to_unsigned_err {
+    ($fn_name:ident, $source:ty, $target:ty) => {
+        #[test]
+        fn $fn_name() {
+            let max = <$source>::max_value();
+            let min = <$source>::min_value();
+            let zero: $source = 0;
+            let t_max = <$target>::max_value();
+            let t_min = <$target>::min_value();
+            assert!(<$target as TryFrom<$source>>::try_from(max).is_err());
+            assert!(<$target as TryFrom<$source>>::try_from(min).is_err());
+            assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(),
+                       zero as $target);
+            assert_eq!(<$target as TryFrom<$source>>::try_from(t_max as $source)
+                            .unwrap(),
+                       t_max as $target);
+            assert_eq!(<$target as TryFrom<$source>>::try_from(t_min as $source)
+                            .unwrap(),
+                       t_min as $target);
+        }
+    }
+}
+
+test_impl_try_from_signed_to_unsigned_err! { test_try_i16u8, i16, u8 }
+
+test_impl_try_from_signed_to_unsigned_err! { test_try_i32u8, i32, u8 }
+test_impl_try_from_signed_to_unsigned_err! { test_try_i32u16, i32, u16 }
+
+test_impl_try_from_signed_to_unsigned_err! { test_try_i64u8, i64, u8 }
+test_impl_try_from_signed_to_unsigned_err! { test_try_i64u16, i64, u16 }
+test_impl_try_from_signed_to_unsigned_err! { test_try_i64u32, i64, u32 }
diff --git a/src/libcore/tests/num/u16.rs b/src/libcore/tests/num/u16.rs
new file mode 100644
index 00000000000..8455207583c
--- /dev/null
+++ b/src/libcore/tests/num/u16.rs
@@ -0,0 +1,11 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+uint_module!(u16, u16);
diff --git a/src/libcore/tests/num/u32.rs b/src/libcore/tests/num/u32.rs
new file mode 100644
index 00000000000..b44e60f6529
--- /dev/null
+++ b/src/libcore/tests/num/u32.rs
@@ -0,0 +1,11 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+uint_module!(u32, u32);
diff --git a/src/libcore/tests/num/u64.rs b/src/libcore/tests/num/u64.rs
new file mode 100644
index 00000000000..ffcd1015d58
--- /dev/null
+++ b/src/libcore/tests/num/u64.rs
@@ -0,0 +1,11 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+uint_module!(u64, u64);
diff --git a/src/libcore/tests/num/u8.rs b/src/libcore/tests/num/u8.rs
new file mode 100644
index 00000000000..4ee14e22f2d
--- /dev/null
+++ b/src/libcore/tests/num/u8.rs
@@ -0,0 +1,11 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+uint_module!(u8, u8);
diff --git a/src/libcore/tests/num/uint_macros.rs b/src/libcore/tests/num/uint_macros.rs
new file mode 100644
index 00000000000..daa1cc3a7f4
--- /dev/null
+++ b/src/libcore/tests/num/uint_macros.rs
@@ -0,0 +1,158 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! uint_module { ($T:ident, $T_i:ident) => (
+#[cfg(test)]
+mod tests {
+    use core::$T_i::*;
+    use num;
+    use core::ops::{BitOr, BitAnd, BitXor, Shl, Shr, Not};
+    use std::str::FromStr;
+    use std::mem;
+
+    #[test]
+    fn test_overflows() {
+        assert!(MAX > 0);
+        assert!(MIN <= 0);
+        assert!((MIN + MAX).wrapping_add(1) == 0);
+    }
+
+    #[test]
+    fn test_num() {
+        num::test_num(10 as $T, 2 as $T);
+    }
+
+    #[test]
+    fn test_bitwise_operators() {
+        assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T));
+        assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T));
+        assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T));
+        assert!(0b1110 as $T == (0b0111 as $T).shl(1));
+        assert!(0b0111 as $T == (0b1110 as $T).shr(1));
+        assert!(MAX - (0b1011 as $T) == (0b1011 as $T).not());
+    }
+
+    const A: $T = 0b0101100;
+    const B: $T = 0b0100001;
+    const C: $T = 0b1111001;
+
+    const _0: $T = 0;
+    const _1: $T = !0;
+
+    #[test]
+    fn test_count_ones() {
+        assert!(A.count_ones() == 3);
+        assert!(B.count_ones() == 2);
+        assert!(C.count_ones() == 5);
+    }
+
+    #[test]
+    fn test_count_zeros() {
+        let bits = mem::size_of::<$T>() * 8;
+        assert!(A.count_zeros() == bits as u32 - 3);
+        assert!(B.count_zeros() == bits as u32 - 2);
+        assert!(C.count_zeros() == bits as u32 - 5);
+    }
+
+    #[test]
+    fn test_rotate() {
+        assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
+        assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B);
+        assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C);
+
+        // Rotating these should make no difference
+        //
+        // We test using 124 bits because to ensure that overlong bit shifts do
+        // not cause undefined behaviour. See #10183.
+        assert_eq!(_0.rotate_left(124), _0);
+        assert_eq!(_1.rotate_left(124), _1);
+        assert_eq!(_0.rotate_right(124), _0);
+        assert_eq!(_1.rotate_right(124), _1);
+
+        // Rotating by 0 should have no effect
+        assert_eq!(A.rotate_left(0), A);
+        assert_eq!(B.rotate_left(0), B);
+        assert_eq!(C.rotate_left(0), C);
+        // Rotating by a multiple of word size should also have no effect
+        assert_eq!(A.rotate_left(64), A);
+        assert_eq!(B.rotate_left(64), B);
+        assert_eq!(C.rotate_left(64), C);
+    }
+
+    #[test]
+    fn test_swap_bytes() {
+        assert_eq!(A.swap_bytes().swap_bytes(), A);
+        assert_eq!(B.swap_bytes().swap_bytes(), B);
+        assert_eq!(C.swap_bytes().swap_bytes(), C);
+
+        // Swapping these should make no difference
+        assert_eq!(_0.swap_bytes(), _0);
+        assert_eq!(_1.swap_bytes(), _1);
+    }
+
+    #[test]
+    fn test_le() {
+        assert_eq!($T::from_le(A.to_le()), A);
+        assert_eq!($T::from_le(B.to_le()), B);
+        assert_eq!($T::from_le(C.to_le()), C);
+        assert_eq!($T::from_le(_0), _0);
+        assert_eq!($T::from_le(_1), _1);
+        assert_eq!(_0.to_le(), _0);
+        assert_eq!(_1.to_le(), _1);
+    }
+
+    #[test]
+    fn test_be() {
+        assert_eq!($T::from_be(A.to_be()), A);
+        assert_eq!($T::from_be(B.to_be()), B);
+        assert_eq!($T::from_be(C.to_be()), C);
+        assert_eq!($T::from_be(_0), _0);
+        assert_eq!($T::from_be(_1), _1);
+        assert_eq!(_0.to_be(), _0);
+        assert_eq!(_1.to_be(), _1);
+    }
+
+    #[test]
+    fn test_unsigned_checked_div() {
+        assert!((10 as $T).checked_div(2) == Some(5));
+        assert!((5 as $T).checked_div(0) == None);
+    }
+
+    fn from_str<T: FromStr>(t: &str) -> Option<T> {
+        FromStr::from_str(t).ok()
+    }
+
+    #[test]
+    pub fn test_from_str() {
+        assert_eq!(from_str::<$T>("0"), Some(0 as $T));
+        assert_eq!(from_str::<$T>("3"), Some(3 as $T));
+        assert_eq!(from_str::<$T>("10"), Some(10 as $T));
+        assert_eq!(from_str::<u32>("123456789"), Some(123456789 as u32));
+        assert_eq!(from_str::<$T>("00100"), Some(100 as $T));
+
+        assert_eq!(from_str::<$T>(""), None);
+        assert_eq!(from_str::<$T>(" "), None);
+        assert_eq!(from_str::<$T>("x"), None);
+    }
+
+    #[test]
+    pub fn test_parse_bytes() {
+        assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T));
+        assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T));
+        assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T));
+        assert_eq!(u16::from_str_radix("123", 16), Ok(291 as u16));
+        assert_eq!(u16::from_str_radix("ffff", 16), Ok(65535 as u16));
+        assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T));
+
+        assert_eq!($T::from_str_radix("Z", 10).ok(), None::<$T>);
+        assert_eq!($T::from_str_radix("_", 2).ok(), None::<$T>);
+    }
+}
+)}
diff --git a/src/libcore/tests/ops.rs b/src/libcore/tests/ops.rs
new file mode 100644
index 00000000000..1c6c13b0d02
--- /dev/null
+++ b/src/libcore/tests/ops.rs
@@ -0,0 +1,49 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::ops::{Range, RangeFull, RangeFrom, RangeTo};
+
+// Test the Range structs without the syntactic sugar.
+
+#[test]
+fn test_range() {
+    let r = Range { start: 2, end: 10 };
+    let mut count = 0;
+    for (i, ri) in r.enumerate() {
+        assert!(ri == i + 2);
+        assert!(ri >= 2 && ri < 10);
+        count += 1;
+    }
+    assert!(count == 8);
+}
+
+#[test]
+fn test_range_from() {
+    let r = RangeFrom { start: 2 };
+    let mut count = 0;
+    for (i, ri) in r.take(10).enumerate() {
+        assert!(ri == i + 2);
+        assert!(ri >= 2 && ri < 12);
+        count += 1;
+    }
+    assert!(count == 10);
+}
+
+#[test]
+fn test_range_to() {
+    // Not much to test.
+    let _ = RangeTo { end: 42 };
+}
+
+#[test]
+fn test_full_range() {
+    // Not much to test.
+    let _ = RangeFull;
+}
diff --git a/src/libcore/tests/option.rs b/src/libcore/tests/option.rs
new file mode 100644
index 00000000000..51b0655f680
--- /dev/null
+++ b/src/libcore/tests/option.rs
@@ -0,0 +1,272 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::option::*;
+use core::mem;
+use core::clone::Clone;
+
+#[test]
+fn test_get_ptr() {
+    unsafe {
+        let x: Box<_> = box 0;
+        let addr_x: *const isize = mem::transmute(&*x);
+        let opt = Some(x);
+        let y = opt.unwrap();
+        let addr_y: *const isize = mem::transmute(&*y);
+        assert_eq!(addr_x, addr_y);
+    }
+}
+
+#[test]
+fn test_get_str() {
+    let x = "test".to_string();
+    let addr_x = x.as_ptr();
+    let opt = Some(x);
+    let y = opt.unwrap();
+    let addr_y = y.as_ptr();
+    assert_eq!(addr_x, addr_y);
+}
+
+#[test]
+fn test_get_resource() {
+    use std::rc::Rc;
+    use core::cell::RefCell;
+
+    struct R {
+       i: Rc<RefCell<isize>>,
+    }
+
+        impl Drop for R {
+       fn drop(&mut self) {
+            let ii = &*self.i;
+            let i = *ii.borrow();
+            *ii.borrow_mut() = i + 1;
+        }
+    }
+
+    fn r(i: Rc<RefCell<isize>>) -> R {
+        R {
+            i: i
+        }
+    }
+
+    let i = Rc::new(RefCell::new(0));
+    {
+        let x = r(i.clone());
+        let opt = Some(x);
+        let _y = opt.unwrap();
+    }
+    assert_eq!(*i.borrow(), 1);
+}
+
+#[test]
+fn test_option_dance() {
+    let x = Some(());
+    let mut y = Some(5);
+    let mut y2 = 0;
+    for _x in x {
+        y2 = y.take().unwrap();
+    }
+    assert_eq!(y2, 5);
+    assert!(y.is_none());
+}
+
+#[test] #[should_panic]
+fn test_option_too_much_dance() {
+    struct A;
+    let mut y = Some(A);
+    let _y2 = y.take().unwrap();
+    let _y3 = y.take().unwrap();
+}
+
+#[test]
+fn test_and() {
+    let x: Option<isize> = Some(1);
+    assert_eq!(x.and(Some(2)), Some(2));
+    assert_eq!(x.and(None::<isize>), None);
+
+    let x: Option<isize> = None;
+    assert_eq!(x.and(Some(2)), None);
+    assert_eq!(x.and(None::<isize>), None);
+}
+
+#[test]
+fn test_and_then() {
+    let x: Option<isize> = Some(1);
+    assert_eq!(x.and_then(|x| Some(x + 1)), Some(2));
+    assert_eq!(x.and_then(|_| None::<isize>), None);
+
+    let x: Option<isize> = None;
+    assert_eq!(x.and_then(|x| Some(x + 1)), None);
+    assert_eq!(x.and_then(|_| None::<isize>), None);
+}
+
+#[test]
+fn test_or() {
+    let x: Option<isize> = Some(1);
+    assert_eq!(x.or(Some(2)), Some(1));
+    assert_eq!(x.or(None), Some(1));
+
+    let x: Option<isize> = None;
+    assert_eq!(x.or(Some(2)), Some(2));
+    assert_eq!(x.or(None), None);
+}
+
+#[test]
+fn test_or_else() {
+    let x: Option<isize> = Some(1);
+    assert_eq!(x.or_else(|| Some(2)), Some(1));
+    assert_eq!(x.or_else(|| None), Some(1));
+
+    let x: Option<isize> = None;
+    assert_eq!(x.or_else(|| Some(2)), Some(2));
+    assert_eq!(x.or_else(|| None), None);
+}
+
+#[test]
+fn test_unwrap() {
+    assert_eq!(Some(1).unwrap(), 1);
+    let s = Some("hello".to_string()).unwrap();
+    assert_eq!(s, "hello");
+}
+
+#[test]
+#[should_panic]
+fn test_unwrap_panic1() {
+    let x: Option<isize> = None;
+    x.unwrap();
+}
+
+#[test]
+#[should_panic]
+fn test_unwrap_panic2() {
+    let x: Option<String> = None;
+    x.unwrap();
+}
+
+#[test]
+fn test_unwrap_or() {
+    let x: Option<isize> = Some(1);
+    assert_eq!(x.unwrap_or(2), 1);
+
+    let x: Option<isize> = None;
+    assert_eq!(x.unwrap_or(2), 2);
+}
+
+#[test]
+fn test_unwrap_or_else() {
+    let x: Option<isize> = Some(1);
+    assert_eq!(x.unwrap_or_else(|| 2), 1);
+
+    let x: Option<isize> = None;
+    assert_eq!(x.unwrap_or_else(|| 2), 2);
+}
+
+#[test]
+fn test_iter() {
+    let val = 5;
+
+    let x = Some(val);
+    let mut it = x.iter();
+
+    assert_eq!(it.size_hint(), (1, Some(1)));
+    assert_eq!(it.next(), Some(&val));
+    assert_eq!(it.size_hint(), (0, Some(0)));
+    assert!(it.next().is_none());
+
+    let mut it = (&x).into_iter();
+    assert_eq!(it.next(), Some(&val));
+}
+
+#[test]
+fn test_mut_iter() {
+    let mut val = 5;
+    let new_val = 11;
+
+    let mut x = Some(val);
+    {
+        let mut it = x.iter_mut();
+
+        assert_eq!(it.size_hint(), (1, Some(1)));
+
+        match it.next() {
+            Some(interior) => {
+                assert_eq!(*interior, val);
+                *interior = new_val;
+            }
+            None => assert!(false),
+        }
+
+        assert_eq!(it.size_hint(), (0, Some(0)));
+        assert!(it.next().is_none());
+    }
+    assert_eq!(x, Some(new_val));
+
+    let mut y = Some(val);
+    let mut it = (&mut y).into_iter();
+    assert_eq!(it.next(), Some(&mut val));
+}
+
+#[test]
+fn test_ord() {
+    let small = Some(1.0f64);
+    let big = Some(5.0f64);
+    let nan = Some(0.0f64/0.0);
+    assert!(!(nan < big));
+    assert!(!(nan > big));
+    assert!(small < big);
+    assert!(None < big);
+    assert!(big > None);
+}
+
+#[test]
+fn test_collect() {
+    let v: Option<Vec<isize>> = (0..0).map(|_| Some(0)).collect();
+    assert!(v == Some(vec![]));
+
+    let v: Option<Vec<isize>> = (0..3).map(|x| Some(x)).collect();
+    assert!(v == Some(vec![0, 1, 2]));
+
+    let v: Option<Vec<isize>> = (0..3).map(|x| {
+        if x > 1 { None } else { Some(x) }
+    }).collect();
+    assert!(v == None);
+
+    // test that it does not take more elements than it needs
+    let mut functions: [Box<Fn() -> Option<()>>; 3] =
+        [box || Some(()), box || None, box || panic!()];
+
+    let v: Option<Vec<()>> = functions.iter_mut().map(|f| (*f)()).collect();
+
+    assert!(v == None);
+}
+
+
+#[test]
+fn test_cloned() {
+    let val = 1;
+    let val_ref = &val;
+    let opt_none: Option<&'static u32> = None;
+    let opt_ref = Some(&val);
+    let opt_ref_ref = Some(&val_ref);
+
+    // None works
+    assert_eq!(opt_none.clone(), None);
+    assert_eq!(opt_none.cloned(), None);
+
+    // Immutable ref works
+    assert_eq!(opt_ref.clone(), Some(&val));
+    assert_eq!(opt_ref.cloned(), Some(1));
+
+    // Double Immutable ref works
+    assert_eq!(opt_ref_ref.clone(), Some(&val_ref));
+    assert_eq!(opt_ref_ref.clone().cloned(), Some(&val));
+    assert_eq!(opt_ref_ref.cloned().cloned(), Some(1));
+}
diff --git a/src/libcore/tests/ptr.rs b/src/libcore/tests/ptr.rs
new file mode 100644
index 00000000000..7f6f472bfbb
--- /dev/null
+++ b/src/libcore/tests/ptr.rs
@@ -0,0 +1,214 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::ptr::*;
+use core::cell::RefCell;
+
+#[test]
+fn test() {
+    unsafe {
+        struct Pair {
+            fst: isize,
+            snd: isize
+        };
+        let mut p = Pair {fst: 10, snd: 20};
+        let pptr: *mut Pair = &mut p;
+        let iptr: *mut isize = pptr as *mut isize;
+        assert_eq!(*iptr, 10);
+        *iptr = 30;
+        assert_eq!(*iptr, 30);
+        assert_eq!(p.fst, 30);
+
+        *pptr = Pair {fst: 50, snd: 60};
+        assert_eq!(*iptr, 50);
+        assert_eq!(p.fst, 50);
+        assert_eq!(p.snd, 60);
+
+        let v0 = vec![32000u16, 32001u16, 32002u16];
+        let mut v1 = vec![0u16, 0u16, 0u16];
+
+        copy(v0.as_ptr().offset(1), v1.as_mut_ptr().offset(1), 1);
+        assert!((v1[0] == 0u16 &&
+                 v1[1] == 32001u16 &&
+                 v1[2] == 0u16));
+        copy(v0.as_ptr().offset(2), v1.as_mut_ptr(), 1);
+        assert!((v1[0] == 32002u16 &&
+                 v1[1] == 32001u16 &&
+                 v1[2] == 0u16));
+        copy(v0.as_ptr(), v1.as_mut_ptr().offset(2), 1);
+        assert!((v1[0] == 32002u16 &&
+                 v1[1] == 32001u16 &&
+                 v1[2] == 32000u16));
+    }
+}
+
+#[test]
+fn test_is_null() {
+    let p: *const isize = null();
+    assert!(p.is_null());
+
+    let q = unsafe { p.offset(1) };
+    assert!(!q.is_null());
+
+    let mp: *mut isize = null_mut();
+    assert!(mp.is_null());
+
+    let mq = unsafe { mp.offset(1) };
+    assert!(!mq.is_null());
+}
+
+#[test]
+fn test_as_ref() {
+    unsafe {
+        let p: *const isize = null();
+        assert_eq!(p.as_ref(), None);
+
+        let q: *const isize = &2;
+        assert_eq!(q.as_ref().unwrap(), &2);
+
+        let p: *mut isize = null_mut();
+        assert_eq!(p.as_ref(), None);
+
+        let q: *mut isize = &mut 2;
+        assert_eq!(q.as_ref().unwrap(), &2);
+
+        // Lifetime inference
+        let u = 2isize;
+        {
+            let p = &u as *const isize;
+            assert_eq!(p.as_ref().unwrap(), &2);
+        }
+    }
+}
+
+#[test]
+fn test_as_mut() {
+    unsafe {
+        let p: *mut isize = null_mut();
+        assert!(p.as_mut() == None);
+
+        let q: *mut isize = &mut 2;
+        assert!(q.as_mut().unwrap() == &mut 2);
+
+        // Lifetime inference
+        let mut u = 2isize;
+        {
+            let p = &mut u as *mut isize;
+            assert!(p.as_mut().unwrap() == &mut 2);
+        }
+    }
+}
+
+#[test]
+fn test_ptr_addition() {
+    unsafe {
+        let xs = vec![5; 16];
+        let mut ptr = xs.as_ptr();
+        let end = ptr.offset(16);
+
+        while ptr < end {
+            assert_eq!(*ptr, 5);
+            ptr = ptr.offset(1);
+        }
+
+        let mut xs_mut = xs;
+        let mut m_ptr = xs_mut.as_mut_ptr();
+        let m_end = m_ptr.offset(16);
+
+        while m_ptr < m_end {
+            *m_ptr += 5;
+            m_ptr = m_ptr.offset(1);
+        }
+
+        assert!(xs_mut == vec![10; 16]);
+    }
+}
+
+#[test]
+fn test_ptr_subtraction() {
+    unsafe {
+        let xs = vec![0,1,2,3,4,5,6,7,8,9];
+        let mut idx = 9;
+        let ptr = xs.as_ptr();
+
+        while idx >= 0 {
+            assert_eq!(*(ptr.offset(idx as isize)), idx as isize);
+            idx = idx - 1;
+        }
+
+        let mut xs_mut = xs;
+        let m_start = xs_mut.as_mut_ptr();
+        let mut m_ptr = m_start.offset(9);
+
+        while m_ptr >= m_start {
+            *m_ptr += *m_ptr;
+            m_ptr = m_ptr.offset(-1);
+        }
+
+        assert_eq!(xs_mut, [0,2,4,6,8,10,12,14,16,18]);
+    }
+}
+
+#[test]
+fn test_set_memory() {
+    let mut xs = [0u8; 20];
+    let ptr = xs.as_mut_ptr();
+    unsafe { write_bytes(ptr, 5u8, xs.len()); }
+    assert!(xs == [5u8; 20]);
+}
+
+#[test]
+fn test_unsized_unique() {
+    let xs: &mut [i32] = &mut [1, 2, 3];
+    let ptr = unsafe { Unique::new(xs as *mut [i32]) };
+    let ys = unsafe { &mut **ptr };
+    let zs: &mut [i32] = &mut [1, 2, 3];
+    assert!(ys == zs);
+}
+
+#[test]
+#[allow(warnings)]
+// Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the
+// ABI, or even point to an actual executable code, because the function itself is never invoked.
+#[no_mangle]
+pub fn test_variadic_fnptr() {
+    use core::hash::{Hash, SipHasher};
+    extern {
+        fn test_variadic_fnptr(_: u64, ...) -> f64;
+    }
+    let p: unsafe extern fn(u64, ...) -> f64 = test_variadic_fnptr;
+    let q = p.clone();
+    assert_eq!(p, q);
+    assert!(!(p < q));
+    let mut s = SipHasher::new();
+    assert_eq!(p.hash(&mut s), q.hash(&mut s));
+}
+
+#[test]
+fn write_unaligned_drop() {
+    thread_local! {
+        static DROPS: RefCell<Vec<u32>> = RefCell::new(Vec::new());
+    }
+
+    struct Dropper(u32);
+
+    impl Drop for Dropper {
+        fn drop(&mut self) {
+            DROPS.with(|d| d.borrow_mut().push(self.0));
+        }
+    }
+
+    {
+        let c = Dropper(0);
+        let mut t = Dropper(1);
+        unsafe { write_unaligned(&mut t, c); }
+    }
+    DROPS.with(|d| assert_eq!(*d.borrow(), [0]));
+}
diff --git a/src/libcore/tests/result.rs b/src/libcore/tests/result.rs
new file mode 100644
index 00000000000..4c5f19dee12
--- /dev/null
+++ b/src/libcore/tests/result.rs
@@ -0,0 +1,204 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn op1() -> Result<isize, &'static str> { Ok(666) }
+fn op2() -> Result<isize, &'static str> { Err("sadface") }
+
+#[test]
+fn test_and() {
+    assert_eq!(op1().and(Ok(667)).unwrap(), 667);
+    assert_eq!(op1().and(Err::<i32, &'static str>("bad")).unwrap_err(),
+               "bad");
+
+    assert_eq!(op2().and(Ok(667)).unwrap_err(), "sadface");
+    assert_eq!(op2().and(Err::<i32,&'static str>("bad")).unwrap_err(),
+               "sadface");
+}
+
+#[test]
+fn test_and_then() {
+    assert_eq!(op1().and_then(|i| Ok::<isize, &'static str>(i + 1)).unwrap(), 667);
+    assert_eq!(op1().and_then(|_| Err::<isize, &'static str>("bad")).unwrap_err(),
+               "bad");
+
+    assert_eq!(op2().and_then(|i| Ok::<isize, &'static str>(i + 1)).unwrap_err(),
+               "sadface");
+    assert_eq!(op2().and_then(|_| Err::<isize, &'static str>("bad")).unwrap_err(),
+               "sadface");
+}
+
+#[test]
+fn test_or() {
+    assert_eq!(op1().or(Ok::<_, &'static str>(667)).unwrap(), 666);
+    assert_eq!(op1().or(Err("bad")).unwrap(), 666);
+
+    assert_eq!(op2().or(Ok::<_, &'static str>(667)).unwrap(), 667);
+    assert_eq!(op2().or(Err("bad")).unwrap_err(), "bad");
+}
+
+#[test]
+fn test_or_else() {
+    assert_eq!(op1().or_else(|_| Ok::<isize, &'static str>(667)).unwrap(), 666);
+    assert_eq!(op1().or_else(|e| Err::<isize, &'static str>(e)).unwrap(), 666);
+
+    assert_eq!(op2().or_else(|_| Ok::<isize, &'static str>(667)).unwrap(), 667);
+    assert_eq!(op2().or_else(|e| Err::<isize, &'static str>(e)).unwrap_err(),
+               "sadface");
+}
+
+#[test]
+fn test_impl_map() {
+    assert!(Ok::<isize, isize>(1).map(|x| x + 1) == Ok(2));
+    assert!(Err::<isize, isize>(1).map(|x| x + 1) == Err(1));
+}
+
+#[test]
+fn test_impl_map_err() {
+    assert!(Ok::<isize, isize>(1).map_err(|x| x + 1) == Ok(1));
+    assert!(Err::<isize, isize>(1).map_err(|x| x + 1) == Err(2));
+}
+
+#[test]
+fn test_collect() {
+    let v: Result<Vec<isize>, ()> = (0..0).map(|_| Ok::<isize, ()>(0)).collect();
+    assert!(v == Ok(vec![]));
+
+    let v: Result<Vec<isize>, ()> = (0..3).map(|x| Ok::<isize, ()>(x)).collect();
+    assert!(v == Ok(vec![0, 1, 2]));
+
+    let v: Result<Vec<isize>, isize> = (0..3).map(|x| {
+        if x > 1 { Err(x) } else { Ok(x) }
+    }).collect();
+    assert!(v == Err(2));
+
+    // test that it does not take more elements than it needs
+    let mut functions: [Box<Fn() -> Result<(), isize>>; 3] =
+        [box || Ok(()), box || Err(1), box || panic!()];
+
+    let v: Result<Vec<()>, isize> = functions.iter_mut().map(|f| (*f)()).collect();
+    assert!(v == Err(1));
+}
+
+#[test]
+fn test_fmt_default() {
+    let ok: Result<isize, &'static str> = Ok(100);
+    let err: Result<isize, &'static str> = Err("Err");
+
+    let s = format!("{:?}", ok);
+    assert_eq!(s, "Ok(100)");
+    let s = format!("{:?}", err);
+    assert_eq!(s, "Err(\"Err\")");
+}
+
+#[test]
+fn test_unwrap_or() {
+    let ok: Result<isize, &'static str> = Ok(100);
+    let ok_err: Result<isize, &'static str> = Err("Err");
+
+    assert_eq!(ok.unwrap_or(50), 100);
+    assert_eq!(ok_err.unwrap_or(50), 50);
+}
+
+#[test]
+fn test_unwrap_or_else() {
+    fn handler(msg: &'static str) -> isize {
+        if msg == "I got this." {
+            50
+        } else {
+            panic!("BadBad")
+        }
+    }
+
+    let ok: Result<isize, &'static str> = Ok(100);
+    let ok_err: Result<isize, &'static str> = Err("I got this.");
+
+    assert_eq!(ok.unwrap_or_else(handler), 100);
+    assert_eq!(ok_err.unwrap_or_else(handler), 50);
+}
+
+#[test]
+#[should_panic]
+pub fn test_unwrap_or_else_panic() {
+    fn handler(msg: &'static str) -> isize {
+        if msg == "I got this." {
+            50
+        } else {
+            panic!("BadBad")
+        }
+    }
+
+    let bad_err: Result<isize, &'static str> = Err("Unrecoverable mess.");
+    let _ : isize = bad_err.unwrap_or_else(handler);
+}
+
+
+#[test]
+pub fn test_expect_ok() {
+    let ok: Result<isize, &'static str> = Ok(100);
+    assert_eq!(ok.expect("Unexpected error"), 100);
+}
+#[test]
+#[should_panic(expected="Got expected error: \"All good\"")]
+pub fn test_expect_err() {
+    let err: Result<isize, &'static str> = Err("All good");
+    err.expect("Got expected error");
+}
+
+
+#[test]
+pub fn test_expect_err_err() {
+    let ok: Result<&'static str, isize> = Err(100);
+    assert_eq!(ok.expect_err("Unexpected ok"), 100);
+}
+#[test]
+#[should_panic(expected="Got expected ok: \"All good\"")]
+pub fn test_expect_err_ok() {
+    let err: Result<&'static str, isize> = Ok("All good");
+    err.expect_err("Got expected ok");
+}
+
+#[test]
+pub fn test_iter() {
+    let ok: Result<isize, &'static str> = Ok(100);
+    let mut it = ok.iter();
+    assert_eq!(it.size_hint(), (1, Some(1)));
+    assert_eq!(it.next(), Some(&100));
+    assert_eq!(it.size_hint(), (0, Some(0)));
+    assert!(it.next().is_none());
+    assert_eq!((&ok).into_iter().next(), Some(&100));
+
+    let err: Result<isize, &'static str> = Err("error");
+    assert_eq!(err.iter().next(), None);
+}
+
+#[test]
+pub fn test_iter_mut() {
+    let mut ok: Result<isize, &'static str> = Ok(100);
+    for loc in ok.iter_mut() {
+        *loc = 200;
+    }
+    assert_eq!(ok, Ok(200));
+    for loc in &mut ok {
+        *loc = 300;
+    }
+    assert_eq!(ok, Ok(300));
+
+    let mut err: Result<isize, &'static str> = Err("error");
+    for loc in err.iter_mut() {
+        *loc = 200;
+    }
+    assert_eq!(err, Err("error"));
+}
+
+#[test]
+pub fn test_unwrap_or_default() {
+    assert_eq!(op1().unwrap_or_default(), 666);
+    assert_eq!(op2().unwrap_or_default(), 0);
+}
diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs
new file mode 100644
index 00000000000..15047204e50
--- /dev/null
+++ b/src/libcore/tests/slice.rs
@@ -0,0 +1,304 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::cmp::Ordering::{Equal, Greater, Less};
+use core::slice::heapsort;
+use core::result::Result::{Ok, Err};
+use rand::{Rng, XorShiftRng};
+
+#[test]
+fn test_binary_search() {
+    let b = [1, 2, 4, 6, 8, 9];
+    assert!(b.binary_search_by(|v| v.cmp(&6)) == Ok(3));
+    assert!(b.binary_search_by(|v| v.cmp(&5)) == Err(3));
+    let b = [1, 2, 4, 6, 7, 8, 9];
+    assert!(b.binary_search_by(|v| v.cmp(&6)) == Ok(3));
+    assert!(b.binary_search_by(|v| v.cmp(&5)) == Err(3));
+    let b = [1, 2, 4, 6, 8, 9];
+    assert!(b.binary_search_by(|v| v.cmp(&8)) == Ok(4));
+    assert!(b.binary_search_by(|v| v.cmp(&7)) == Err(4));
+    let b = [1, 2, 4, 6, 7, 8, 9];
+    assert!(b.binary_search_by(|v| v.cmp(&8)) == Ok(5));
+    let b = [1, 2, 4, 5, 6, 8, 9];
+    assert!(b.binary_search_by(|v| v.cmp(&7)) == Err(5));
+    assert!(b.binary_search_by(|v| v.cmp(&0)) == Err(0));
+    let b = [1, 2, 4, 5, 6, 8];
+    assert!(b.binary_search_by(|v| v.cmp(&9)) == Err(6));
+}
+
+#[test]
+fn test_iterator_nth() {
+    let v: &[_] = &[0, 1, 2, 3, 4];
+    for i in 0..v.len() {
+        assert_eq!(v.iter().nth(i).unwrap(), &v[i]);
+    }
+    assert_eq!(v.iter().nth(v.len()), None);
+
+    let mut iter = v.iter();
+    assert_eq!(iter.nth(2).unwrap(), &v[2]);
+    assert_eq!(iter.nth(1).unwrap(), &v[4]);
+}
+
+#[test]
+fn test_iterator_last() {
+    let v: &[_] = &[0, 1, 2, 3, 4];
+    assert_eq!(v.iter().last().unwrap(), &4);
+    assert_eq!(v[..1].iter().last().unwrap(), &0);
+}
+
+#[test]
+fn test_iterator_count() {
+    let v: &[_] = &[0, 1, 2, 3, 4];
+    assert_eq!(v.iter().count(), 5);
+
+    let mut iter2 = v.iter();
+    iter2.next();
+    iter2.next();
+    assert_eq!(iter2.count(), 3);
+}
+
+#[test]
+fn test_chunks_count() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let c = v.chunks(3);
+    assert_eq!(c.count(), 2);
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4];
+    let c2 = v2.chunks(2);
+    assert_eq!(c2.count(), 3);
+
+    let v3: &[i32] = &[];
+    let c3 = v3.chunks(2);
+    assert_eq!(c3.count(), 0);
+}
+
+#[test]
+fn test_chunks_nth() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let mut c = v.chunks(2);
+    assert_eq!(c.nth(1).unwrap()[1], 3);
+    assert_eq!(c.next().unwrap()[0], 4);
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4];
+    let mut c2 = v2.chunks(3);
+    assert_eq!(c2.nth(1).unwrap()[1], 4);
+    assert_eq!(c2.next(), None);
+}
+
+#[test]
+fn test_chunks_last() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let c = v.chunks(2);
+    assert_eq!(c.last().unwrap()[1], 5);
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4];
+    let c2 = v2.chunks(2);
+    assert_eq!(c2.last().unwrap()[0], 4);
+}
+
+#[test]
+fn test_chunks_mut_count() {
+    let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+    let c = v.chunks_mut(3);
+    assert_eq!(c.count(), 2);
+
+    let mut v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
+    let c2 = v2.chunks_mut(2);
+    assert_eq!(c2.count(), 3);
+
+    let mut v3: &mut [i32] = &mut [];
+    let c3 = v3.chunks_mut(2);
+    assert_eq!(c3.count(), 0);
+}
+
+#[test]
+fn test_chunks_mut_nth() {
+    let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+    let mut c = v.chunks_mut(2);
+    assert_eq!(c.nth(1).unwrap()[1], 3);
+    assert_eq!(c.next().unwrap()[0], 4);
+
+    let mut v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
+    let mut c2 = v2.chunks_mut(3);
+    assert_eq!(c2.nth(1).unwrap()[1], 4);
+    assert_eq!(c2.next(), None);
+}
+
+#[test]
+fn test_chunks_mut_last() {
+    let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+    let c = v.chunks_mut(2);
+    assert_eq!(c.last().unwrap()[1], 5);
+
+    let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
+    let c2 = v2.chunks_mut(2);
+    assert_eq!(c2.last().unwrap()[0], 4);
+}
+
+#[test]
+fn test_windows_count() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let c = v.windows(3);
+    assert_eq!(c.count(), 4);
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4];
+    let c2 = v2.windows(6);
+    assert_eq!(c2.count(), 0);
+
+    let v3: &[i32] = &[];
+    let c3 = v3.windows(2);
+    assert_eq!(c3.count(), 0);
+}
+
+#[test]
+fn test_windows_nth() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let mut c = v.windows(2);
+    assert_eq!(c.nth(2).unwrap()[1], 3);
+    assert_eq!(c.next().unwrap()[0], 3);
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4];
+    let mut c2 = v2.windows(4);
+    assert_eq!(c2.nth(1).unwrap()[1], 2);
+    assert_eq!(c2.next(), None);
+}
+
+#[test]
+fn test_windows_last() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let c = v.windows(2);
+    assert_eq!(c.last().unwrap()[1], 5);
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4];
+    let c2 = v2.windows(2);
+    assert_eq!(c2.last().unwrap()[0], 3);
+}
+
+#[test]
+fn get_range() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    assert_eq!(v.get(..), Some(&[0, 1, 2, 3, 4, 5][..]));
+    assert_eq!(v.get(..2), Some(&[0, 1][..]));
+    assert_eq!(v.get(2..), Some(&[2, 3, 4, 5][..]));
+    assert_eq!(v.get(1..4), Some(&[1, 2, 3][..]));
+    assert_eq!(v.get(7..), None);
+    assert_eq!(v.get(7..10), None);
+}
+
+#[test]
+fn get_mut_range() {
+    let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+    assert_eq!(v.get_mut(..), Some(&mut [0, 1, 2, 3, 4, 5][..]));
+    assert_eq!(v.get_mut(..2), Some(&mut [0, 1][..]));
+    assert_eq!(v.get_mut(2..), Some(&mut [2, 3, 4, 5][..]));
+    assert_eq!(v.get_mut(1..4), Some(&mut [1, 2, 3][..]));
+    assert_eq!(v.get_mut(7..), None);
+    assert_eq!(v.get_mut(7..10), None);
+}
+
+#[test]
+fn get_unchecked_range() {
+    unsafe {
+        let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+        assert_eq!(v.get_unchecked(..), &[0, 1, 2, 3, 4, 5][..]);
+        assert_eq!(v.get_unchecked(..2), &[0, 1][..]);
+        assert_eq!(v.get_unchecked(2..), &[2, 3, 4, 5][..]);
+        assert_eq!(v.get_unchecked(1..4), &[1, 2, 3][..]);
+    }
+}
+
+#[test]
+fn get_unchecked_mut_range() {
+    unsafe {
+        let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+        assert_eq!(v.get_unchecked_mut(..), &mut [0, 1, 2, 3, 4, 5][..]);
+        assert_eq!(v.get_unchecked_mut(..2), &mut [0, 1][..]);
+        assert_eq!(v.get_unchecked_mut(2..), &mut[2, 3, 4, 5][..]);
+        assert_eq!(v.get_unchecked_mut(1..4), &mut [1, 2, 3][..]);
+    }
+}
+
+#[test]
+fn test_find_rfind() {
+    let v = [0, 1, 2, 3, 4, 5];
+    let mut iter = v.iter();
+    let mut i = v.len();
+    while let Some(&elt) = iter.rfind(|_| true) {
+        i -= 1;
+        assert_eq!(elt, v[i]);
+    }
+    assert_eq!(i, 0);
+    assert_eq!(v.iter().rfind(|&&x| x <= 3), Some(&3));
+}
+
+#[test]
+fn sort_unstable() {
+    let mut v = [0; 600];
+    let mut tmp = [0; 600];
+    let mut rng = XorShiftRng::new_unseeded();
+
+    for len in (2..25).chain(500..510) {
+        let v = &mut v[0..len];
+        let tmp = &mut tmp[0..len];
+
+        for &modulus in &[5, 10, 100, 1000] {
+            for _ in 0..100 {
+                for i in 0..len {
+                    v[i] = rng.gen::<i32>() % modulus;
+                }
+
+                // Sort in default order.
+                tmp.copy_from_slice(v);
+                tmp.sort_unstable();
+                assert!(tmp.windows(2).all(|w| w[0] <= w[1]));
+
+                // Sort in ascending order.
+                tmp.copy_from_slice(v);
+                tmp.sort_unstable_by(|a, b| a.cmp(b));
+                assert!(tmp.windows(2).all(|w| w[0] <= w[1]));
+
+                // Sort in descending order.
+                tmp.copy_from_slice(v);
+                tmp.sort_unstable_by(|a, b| b.cmp(a));
+                assert!(tmp.windows(2).all(|w| w[0] >= w[1]));
+
+                // Test heapsort using `<` operator.
+                tmp.copy_from_slice(v);
+                heapsort(tmp, |a, b| a < b);
+                assert!(tmp.windows(2).all(|w| w[0] <= w[1]));
+
+                // Test heapsort using `>` operator.
+                tmp.copy_from_slice(v);
+                heapsort(tmp, |a, b| a > b);
+                assert!(tmp.windows(2).all(|w| w[0] >= w[1]));
+            }
+        }
+    }
+
+    // Sort using a completely random comparison function.
+    // This will reorder the elements *somehow*, but won't panic.
+    for i in 0..v.len() {
+        v[i] = i as i32;
+    }
+    v.sort_unstable_by(|_, _| *rng.choose(&[Less, Equal, Greater]).unwrap());
+    v.sort_unstable();
+    for i in 0..v.len() {
+        assert_eq!(v[i], i as i32);
+    }
+
+    // Should not panic.
+    [0i32; 0].sort_unstable();
+    [(); 10].sort_unstable();
+    [(); 100].sort_unstable();
+
+    let mut v = [0xDEADBEEFu64];
+    v.sort_unstable();
+    assert!(v == [0xDEADBEEF]);
+}
diff --git a/src/libcore/tests/str.rs b/src/libcore/tests/str.rs
new file mode 100644
index 00000000000..08daafccc54
--- /dev/null
+++ b/src/libcore/tests/str.rs
@@ -0,0 +1,11 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// All `str` tests live in collectionstests::str
diff --git a/src/libcore/tests/tuple.rs b/src/libcore/tests/tuple.rs
new file mode 100644
index 00000000000..4fe5e0a740b
--- /dev/null
+++ b/src/libcore/tests/tuple.rs
@@ -0,0 +1,68 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::cmp::Ordering::{Equal, Less, Greater};
+
+#[test]
+fn test_clone() {
+    let a = (1, "2");
+    let b = a.clone();
+    assert_eq!(a, b);
+}
+
+#[test]
+fn test_tuple_cmp() {
+    let (small, big) = ((1, 2, 3), (3, 2, 1));
+
+    let nan = 0.0f64/0.0;
+
+    // PartialEq
+    assert_eq!(small, small);
+    assert_eq!(big, big);
+    assert!(small != big);
+    assert!(big != small);
+
+    // PartialOrd
+    assert!(small < big);
+    assert!(!(small < small));
+    assert!(!(big < small));
+    assert!(!(big < big));
+
+    assert!(small <= small);
+    assert!(big <= big);
+
+    assert!(big > small);
+    assert!(small >= small);
+    assert!(big >= small);
+    assert!(big >= big);
+
+    assert!(!((1.0f64, 2.0f64) < (nan, 3.0)));
+    assert!(!((1.0f64, 2.0f64) <= (nan, 3.0)));
+    assert!(!((1.0f64, 2.0f64) > (nan, 3.0)));
+    assert!(!((1.0f64, 2.0f64) >= (nan, 3.0)));
+    assert!(((1.0f64, 2.0f64) < (2.0, nan)));
+    assert!(!((2.0f64, 2.0f64) < (2.0, nan)));
+
+    // Ord
+    assert!(small.cmp(&small) == Equal);
+    assert!(big.cmp(&big) == Equal);
+    assert!(small.cmp(&big) == Less);
+    assert!(big.cmp(&small) == Greater);
+}
+
+#[test]
+fn test_show() {
+    let s = format!("{:?}", (1,));
+    assert_eq!(s, "(1,)");
+    let s = format!("{:?}", (1, true));
+    assert_eq!(s, "(1, true)");
+    let s = format!("{:?}", (1, "hi", true));
+    assert_eq!(s, "(1, \"hi\", true)");
+}