]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #40578 - michaelwoerister:shorter-compiletest-stamps, r=alexcrichton
authorCorey Farwell <coreyf@rwell.org>
Wed, 22 Mar 2017 23:30:26 +0000 (19:30 -0400)
committerGitHub <noreply@github.com>
Wed, 22 Mar 2017 23:30:26 +0000 (19:30 -0400)
Make the filenames of .stamp files generated by compiletest shorter

Otherwise we run into filename length limitations on some file systems. See https://bugs.launchpad.net/ecryptfs/+bug/344878 for an example where we only can have ~145 characters for filenames.

r? @alexcrichton

43 files changed:
appveyor.yml
src/bootstrap/config.rs
src/libcollections/benches/lib.rs
src/libcollections/benches/slice.rs
src/libcollections/lib.rs
src/libcollections/slice.rs
src/libcollectionstest/slice.rs
src/libcore/lib.rs
src/libcore/slice.rs [deleted file]
src/libcore/slice/mod.rs [new file with mode: 0644]
src/libcore/slice/sort.rs [new file with mode: 0644]
src/libcoretest/lib.rs
src/libcoretest/slice.rs
src/librustc/hir/def.rs
src/librustc_metadata/decoder.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/macros.rs
src/librustc_resolve/resolve_imports.rs
src/libsyntax/ast.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/quote.rs
src/libsyntax/ext/tt/macro_parser.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs
src/test/compile-fail/E0178.rs
src/test/compile-fail/duplicate-check-macro-exports.rs [new file with mode: 0644]
src/test/compile-fail/issue-34334.rs
src/test/compile-fail/privacy/restricted/tuple-struct-fields/test.rs
src/test/compile-fail/privacy/restricted/tuple-struct-fields/test2.rs
src/test/compile-fail/privacy/restricted/tuple-struct-fields/test3.rs
src/test/compile-fail/trait-object-macro-matcher.rs [new file with mode: 0644]
src/test/compile-fail/trait-object-reference-without-parens-suggestion.rs
src/test/parse-fail/bounds-obj-parens.rs
src/test/parse-fail/issue-17904.rs
src/test/parse-fail/removed-syntax-ptr-lifetime.rs
src/test/parse-fail/removed-syntax-uniq-mut-ty.rs
src/test/parse-fail/trailing-plus-in-bounds.rs
src/test/parse-fail/trait-object-macro-matcher.rs [new file with mode: 0644]
src/test/parse-fail/trait-object-polytrait-priority.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs
src/test/run-pass-fulldeps/issue-40663.rs [new file with mode: 0644]
src/test/run-pass/issue-28279.rs
src/test/run-pass/macro-nested_definition_issue-31946.rs [new file with mode: 0644]

index 499f7d602e3684ec22c39d3afcacd773e067f64a..0e7ebf12a2a91ad46964477afcdaee128ae893c0 100644 (file)
@@ -43,14 +43,14 @@ environment:
   # *not* use debug assertions and llvm assertions. This is because they take
   # too long on appveyor and this is tested by rustbuild below.
   - MSYS_BITS: 32
-    RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu
+    RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-ninja
     SCRIPT: python x.py test
     MINGW_URL: https://s3.amazonaws.com/rust-lang-ci
     MINGW_ARCHIVE: i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z
     MINGW_DIR: mingw32
   - MSYS_BITS: 64
     SCRIPT: python x.py test
-    RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu
+    RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-ninja
     MINGW_URL: https://s3.amazonaws.com/rust-lang-ci
     MINGW_ARCHIVE: x86_64-4.9.2-release-win32-seh-rt_v4-rev4.7z
     MINGW_DIR: mingw64
@@ -68,7 +68,7 @@ environment:
     SCRIPT: python x.py dist
     DEPLOY: 1
   - MSYS_BITS: 32
-    RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-extended
+    RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-extended --enable-ninja
     SCRIPT: python x.py dist
     MINGW_URL: https://s3.amazonaws.com/rust-lang-ci
     MINGW_ARCHIVE: i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z
@@ -76,7 +76,7 @@ environment:
     DEPLOY: 1
   - MSYS_BITS: 64
     SCRIPT: python x.py dist
-    RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-extended
+    RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-extended --enable-ninja
     MINGW_URL: https://s3.amazonaws.com/rust-lang-ci
     MINGW_ARCHIVE: x86_64-4.9.2-release-win32-seh-rt_v4-rev4.7z
     MINGW_DIR: mingw64
@@ -116,9 +116,16 @@ install:
 
   # Download and install sccache
   - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-pc-windows-msvc
-  - mv 2017-03-16-sccache-x86_64-pc-windows-msvc sccache
+  - mv 2017-03-16-sccache-x86_64-pc-windows-msvc sccache.exe
   - set PATH=%PATH%;%CD%
 
+  # Download and install ninja
+  #
+  # Note that this is originally from the github releases patch of Ninja
+  - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-15-ninja-win.zip
+  - 7z x 2017-03-15-ninja-win.zip
+  # - set PATH=%PATH%;%CD% -- this already happens above for sccache
+
   # Install InnoSetup to get `iscc` used to produce installers
   - appveyor-retry choco install -y InnoSetup
   - set PATH="C:\Program Files (x86)\Inno Setup 5";%PATH%
index b1d1d79b9eaa3c58d4e8b4f5575f45c054a275aa..52ebf401aefd6d3eff0eab632e4dee97b1df6ac7 100644 (file)
@@ -23,7 +23,7 @@
 use num_cpus;
 use rustc_serialize::Decodable;
 use toml::{Parser, Decoder, Value};
-use util::push_exe_path;
+use util::{exe, push_exe_path};
 
 /// Global configuration for the entire build and/or bootstrap.
 ///
@@ -584,10 +584,10 @@ macro_rules! check {
                     self.python = Some(path);
                 }
                 "CFG_ENABLE_CCACHE" if value == "1" => {
-                    self.ccache = Some("ccache".to_string());
+                    self.ccache = Some(exe("ccache", &self.build));
                 }
                 "CFG_ENABLE_SCCACHE" if value == "1" => {
-                    self.ccache = Some("sccache".to_string());
+                    self.ccache = Some(exe("sccache", &self.build));
                 }
                 "CFG_CONFIGURE_ARGS" if value.len() > 0 => {
                     self.configure_args = value.split_whitespace()
index 1a21db5e344e3556e232eda8a5e89a588440e2fd..42064e9ca575056b9811ce91cec267ac75ed055d 100644 (file)
@@ -11,6 +11,7 @@
 #![deny(warnings)]
 
 #![feature(rand)]
+#![feature(sort_unstable)]
 #![feature(test)]
 
 extern crate test;
index eb4b76509f913693d45627b0e21aa5d1ea094ad2..7195a9f9bf2c6ad53134af4398c2b92bb41b96f7 100644 (file)
@@ -169,6 +169,7 @@ fn random_inserts(b: &mut Bencher) {
         }
     })
 }
+
 #[bench]
 fn random_removes(b: &mut Bencher) {
     let mut rng = thread_rng();
@@ -216,65 +217,76 @@ fn gen_mostly_descending(len: usize) -> Vec<u64> {
     v
 }
 
-fn gen_big_random(len: usize) -> Vec<[u64; 16]> {
+fn gen_strings(len: usize) -> Vec<String> {
     let mut rng = thread_rng();
-    rng.gen_iter().map(|x| [x; 16]).take(len).collect()
-}
-
-fn gen_big_ascending(len: usize) -> Vec<[u64; 16]> {
-    (0..len as u64).map(|x| [x; 16]).take(len).collect()
+    let mut v = vec![];
+    for _ in 0..len {
+        let n = rng.gen::<usize>() % 20 + 1;
+        v.push(rng.gen_ascii_chars().take(n).collect());
+    }
+    v
 }
 
-fn gen_big_descending(len: usize) -> Vec<[u64; 16]> {
-    (0..len as u64).rev().map(|x| [x; 16]).take(len).collect()
+fn gen_big_random(len: usize) -> Vec<[u64; 16]> {
+    let mut rng = thread_rng();
+    rng.gen_iter().map(|x| [x; 16]).take(len).collect()
 }
 
-macro_rules! sort_bench {
-    ($name:ident, $gen:expr, $len:expr) => {
+macro_rules! sort {
+    ($f:ident, $name:ident, $gen:expr, $len:expr) => {
         #[bench]
         fn $name(b: &mut Bencher) {
-            b.iter(|| $gen($len).sort());
+            b.iter(|| $gen($len).$f());
             b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64;
         }
     }
 }
 
-sort_bench!(sort_small_random, gen_random, 10);
-sort_bench!(sort_small_ascending, gen_ascending, 10);
-sort_bench!(sort_small_descending, gen_descending, 10);
-
-sort_bench!(sort_small_big_random, gen_big_random, 10);
-sort_bench!(sort_small_big_ascending, gen_big_ascending, 10);
-sort_bench!(sort_small_big_descending, gen_big_descending, 10);
-
-sort_bench!(sort_medium_random, gen_random, 100);
-sort_bench!(sort_medium_ascending, gen_ascending, 100);
-sort_bench!(sort_medium_descending, gen_descending, 100);
-
-sort_bench!(sort_large_random, gen_random, 10000);
-sort_bench!(sort_large_ascending, gen_ascending, 10000);
-sort_bench!(sort_large_descending, gen_descending, 10000);
-sort_bench!(sort_large_mostly_ascending, gen_mostly_ascending, 10000);
-sort_bench!(sort_large_mostly_descending, gen_mostly_descending, 10000);
-
-sort_bench!(sort_large_big_random, gen_big_random, 10000);
-sort_bench!(sort_large_big_ascending, gen_big_ascending, 10000);
-sort_bench!(sort_large_big_descending, gen_big_descending, 10000);
+macro_rules! sort_expensive {
+    ($f:ident, $name:ident, $gen:expr, $len:expr) => {
+        #[bench]
+        fn $name(b: &mut Bencher) {
+            b.iter(|| {
+                let mut v = $gen($len);
+                let mut count = 0;
+                v.$f(|a: &u64, b: &u64| {
+                    count += 1;
+                    if count % 1_000_000_000 == 0 {
+                        panic!("should not happen");
+                    }
+                    (*a as f64).cos().partial_cmp(&(*b as f64).cos()).unwrap()
+                });
+                black_box(count);
+            });
+            b.bytes = $len as u64 * mem::size_of::<u64>() as u64;
+        }
+    }
+}
 
-#[bench]
-fn sort_large_random_expensive(b: &mut Bencher) {
-    let len = 10000;
-    b.iter(|| {
-        let mut v = gen_random(len);
-        let mut count = 0;
-        v.sort_by(|a: &u64, b: &u64| {
-            count += 1;
-            if count % 1_000_000_000 == 0 {
-                panic!("should not happen");
-            }
-            (*a as f64).cos().partial_cmp(&(*b as f64).cos()).unwrap()
-        });
-        black_box(count);
-    });
-    b.bytes = len as u64 * mem::size_of::<u64>() as u64;
-}
\ No newline at end of file
+sort!(sort, sort_small_ascending, gen_ascending, 10);
+sort!(sort, sort_small_descending, gen_descending, 10);
+sort!(sort, sort_small_random, gen_random, 10);
+sort!(sort, sort_small_big_random, gen_big_random, 10);
+sort!(sort, sort_medium_random, gen_random, 100);
+sort!(sort, sort_large_ascending, gen_ascending, 10000);
+sort!(sort, sort_large_descending, gen_descending, 10000);
+sort!(sort, sort_large_mostly_ascending, gen_mostly_ascending, 10000);
+sort!(sort, sort_large_mostly_descending, gen_mostly_descending, 10000);
+sort!(sort, sort_large_random, gen_random, 10000);
+sort!(sort, sort_large_big_random, gen_big_random, 10000);
+sort!(sort, sort_large_strings, gen_strings, 10000);
+sort_expensive!(sort_by, sort_large_random_expensive, gen_random, 10000);
+
+sort!(sort_unstable, sort_unstable_small_ascending, gen_ascending, 10);
+sort!(sort_unstable, sort_unstable_small_descending, gen_descending, 10);
+sort!(sort_unstable, sort_unstable_small_random, gen_random, 10);
+sort!(sort_unstable, sort_unstable_small_big_random, gen_big_random, 10);
+sort!(sort_unstable, sort_unstable_medium_random, gen_random, 100);
+sort!(sort_unstable, sort_unstable_large_ascending, gen_ascending, 10000);
+sort!(sort_unstable, sort_unstable_large_descending, gen_descending, 10000);
+sort!(sort_unstable, sort_unstable_large_mostly_ascending, gen_mostly_ascending, 10000);
+sort!(sort_unstable, sort_unstable_large_mostly_descending, gen_mostly_descending, 10000);
+sort!(sort_unstable, sort_unstable_large_random, gen_random, 10000);
+sort!(sort_unstable, sort_unstable_large_big_random, gen_big_random, 10000);
+sort!(sort_unstable, sort_unstable_large_strings, gen_strings, 10000);
+sort_expensive!(sort_unstable_by, sort_unstable_large_random_expensive, gen_random, 10000);
index 10650dab583c392bb295e69f91425e3cdf645a58..72e950bc91fa978a37b6a927f8fd0208579a8984 100644 (file)
@@ -52,6 +52,7 @@
 #![feature(shared)]
 #![feature(slice_get_slice)]
 #![feature(slice_patterns)]
+#![cfg_attr(not(test), feature(sort_unstable))]
 #![feature(specialization)]
 #![feature(staged_api)]
 #![feature(str_internals)]
index 653310b8cb591839a7f49691a38c3fbaff8d6569..5233887620a91e48dff6b371181661d6a3f90122 100644 (file)
@@ -1092,6 +1092,39 @@ pub fn sort(&mut self)
         merge_sort(self, |a, b| a.lt(b));
     }
 
+    /// Sorts the slice using `compare` to compare elements.
+    ///
+    /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case.
+    ///
+    /// # Current implementation
+    ///
+    /// The current algorithm is an adaptive, iterative merge sort inspired by
+    /// [timsort](https://en.wikipedia.org/wiki/Timsort).
+    /// It is designed to be very fast in cases where the slice is nearly sorted, or consists of
+    /// two or more sorted sequences concatenated one after another.
+    ///
+    /// Also, it allocates temporary storage half the size of `self`, but for short slices a
+    /// non-allocating insertion sort is used instead.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = [5, 4, 1, 3, 2];
+    /// v.sort_by(|a, b| a.cmp(b));
+    /// assert!(v == [1, 2, 3, 4, 5]);
+    ///
+    /// // reverse sorting
+    /// v.sort_by(|a, b| b.cmp(a));
+    /// assert!(v == [5, 4, 3, 2, 1]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn sort_by<F>(&mut self, mut compare: F)
+        where F: FnMut(&T, &T) -> Ordering
+    {
+        merge_sort(self, |a, b| compare(a, b) == Less);
+    }
+
     /// Sorts the slice using `f` to extract a key to compare elements by.
     ///
     /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case.
@@ -1122,37 +1155,118 @@ pub fn sort_by_key<B, F>(&mut self, mut f: F)
         merge_sort(self, |a, b| f(a).lt(&f(b)));
     }
 
-    /// Sorts the slice using `compare` to compare elements.
+    /// Sorts the slice, but may not preserve the order of equal elements.
     ///
-    /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case.
+    /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate),
+    /// and `O(n log n)` worst-case.
     ///
     /// # Current implementation
     ///
-    /// The current algorithm is an adaptive, iterative merge sort inspired by
-    /// [timsort](https://en.wikipedia.org/wiki/Timsort).
-    /// It is designed to be very fast in cases where the slice is nearly sorted, or consists of
-    /// two or more sorted sequences concatenated one after another.
+    /// The current algorithm is based on Orson Peters' [pdqsort][pattern-defeating quicksort],
+    /// which is a quicksort variant designed to be very fast on certain kinds of patterns,
+    /// sometimes achieving linear time. It is randomized but deterministic, and falls back to
+    /// heapsort on degenerate inputs.
     ///
-    /// Also, it allocates temporary storage half the size of `self`, but for short slices a
-    /// non-allocating insertion sort is used instead.
+    /// It is generally faster than stable sorting, except in a few special cases, e.g. when the
+    /// slice consists of several concatenated sorted sequences.
     ///
     /// # Examples
     ///
     /// ```
+    /// #![feature(sort_unstable)]
+    ///
+    /// let mut v = [-5, 4, 1, -3, 2];
+    ///
+    /// v.sort_unstable();
+    /// assert!(v == [-5, -3, 1, 2, 4]);
+    /// ```
+    ///
+    /// [pdqsort]: https://github.com/orlp/pdqsort
+    // FIXME #40585: Mention `sort_unstable` in the documentation for `sort`.
+    #[unstable(feature = "sort_unstable", issue = "40585")]
+    #[inline]
+    pub fn sort_unstable(&mut self)
+        where T: Ord
+    {
+        core_slice::SliceExt::sort_unstable(self);
+    }
+
+    /// Sorts the slice using `compare` to compare elements, but may not preserve the order of
+    /// equal elements.
+    ///
+    /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate),
+    /// and `O(n log n)` worst-case.
+    ///
+    /// # Current implementation
+    ///
+    /// The current algorithm is based on Orson Peters' [pdqsort][pattern-defeating quicksort],
+    /// which is a quicksort variant designed to be very fast on certain kinds of patterns,
+    /// sometimes achieving linear time. It is randomized but deterministic, and falls back to
+    /// heapsort on degenerate inputs.
+    ///
+    /// It is generally faster than stable sorting, except in a few special cases, e.g. when the
+    /// slice consists of several concatenated sorted sequences.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(sort_unstable)]
+    ///
     /// let mut v = [5, 4, 1, 3, 2];
-    /// v.sort_by(|a, b| a.cmp(b));
+    /// v.sort_unstable_by(|a, b| a.cmp(b));
     /// assert!(v == [1, 2, 3, 4, 5]);
     ///
     /// // reverse sorting
-    /// v.sort_by(|a, b| b.cmp(a));
+    /// v.sort_unstable_by(|a, b| b.cmp(a));
     /// assert!(v == [5, 4, 3, 2, 1]);
     /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
+    ///
+    /// [pdqsort]: https://github.com/orlp/pdqsort
+    // FIXME #40585: Mention `sort_unstable_by` in the documentation for `sort_by`.
+    #[unstable(feature = "sort_unstable", issue = "40585")]
     #[inline]
-    pub fn sort_by<F>(&mut self, mut compare: F)
+    pub fn sort_unstable_by<F>(&mut self, compare: F)
         where F: FnMut(&T, &T) -> Ordering
     {
-        merge_sort(self, |a, b| compare(a, b) == Less);
+        core_slice::SliceExt::sort_unstable_by(self, compare);
+    }
+
+    /// Sorts the slice using `f` to extract a key to compare elements by, but may not preserve the
+    /// order of equal elements.
+    ///
+    /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate),
+    /// and `O(n log n)` worst-case.
+    ///
+    /// # Current implementation
+    ///
+    /// The current algorithm is based on Orson Peters' [pdqsort][pattern-defeating quicksort],
+    /// which is a quicksort variant designed to be very fast on certain kinds of patterns,
+    /// sometimes achieving linear time. It is randomized but deterministic, and falls back to
+    /// heapsort on degenerate inputs.
+    ///
+    /// It is generally faster than stable sorting, except in a few special cases, e.g. when the
+    /// slice consists of several concatenated sorted sequences.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(sort_unstable)]
+    ///
+    /// let mut v = [-5i32, 4, 1, -3, 2];
+    ///
+    /// v.sort_unstable_by_key(|k| k.abs());
+    /// assert!(v == [1, 2, -3, 4, -5]);
+    /// ```
+    ///
+    /// [pdqsort]: https://github.com/orlp/pdqsort
+    // FIXME #40585: Mention `sort_unstable_by_key` in the documentation for `sort_by_key`.
+    #[unstable(feature = "sort_unstable", issue = "40585")]
+    #[inline]
+    pub fn sort_unstable_by_key<B, F>(&mut self, f: F)
+        where F: FnMut(&T) -> B,
+              B: Ord
+    {
+        core_slice::SliceExt::sort_unstable_by_key(self, f);
     }
 
     /// Copies the elements from `src` into `self`.
@@ -1553,28 +1667,20 @@ fn drop(&mut self) {
 fn merge_sort<T, F>(v: &mut [T], mut is_less: F)
     where F: FnMut(&T, &T) -> bool
 {
+    // Slices of up to this length get sorted using insertion sort.
+    const MAX_INSERTION: usize = 20;
+    // Very short runs are extended using insertion sort to span at least this many elements.
+    const MIN_RUN: usize = 10;
+
     // Sorting has no meaningful behavior on zero-sized types.
     if size_of::<T>() == 0 {
         return;
     }
 
-    // FIXME #12092: These numbers are platform-specific and need more extensive testing/tuning.
-    //
-    // If `v` has length up to `max_insertion`, simply switch to insertion sort because it is going
-    // to perform better than merge sort. For bigger types `T`, the threshold is smaller.
-    //
-    // Short runs are extended using insertion sort to span at least `min_run` elements, in order
-    // to improve performance.
-    let (max_insertion, min_run) = if size_of::<T>() <= 2 * mem::size_of::<usize>() {
-        (64, 32)
-    } else {
-        (32, 16)
-    };
-
     let len = v.len();
 
     // Short arrays get sorted in-place via insertion sort to avoid allocations.
-    if len <= max_insertion {
+    if len <= MAX_INSERTION {
         if len >= 2 {
             for i in (0..len-1).rev() {
                 insert_head(&mut v[i..], &mut is_less);
@@ -1618,7 +1724,7 @@ fn merge_sort<T, F>(v: &mut [T], mut is_less: F)
 
         // Insert some more elements into the run if it's too short. Insertion sort is faster than
         // merge sort on short sequences, so this significantly improves performance.
-        while start > 0 && end - start < min_run {
+        while start > 0 && end - start < MIN_RUN {
             start -= 1;
             insert_head(&mut v[start..end], &mut is_less);
         }
index a7f7baf38518c186751d04f02574ba9bdac7e7ba..00d4dbe9c0458fc36e50bb73eddd14af471abca8 100644 (file)
@@ -399,9 +399,10 @@ fn test_sort() {
         }
     }
 
-    // shouldn't panic
-    let mut v: [i32; 0] = [];
-    v.sort();
+    // Should not panic.
+    [0i32; 0].sort();
+    [(); 10].sort();
+    [(); 100].sort();
 
     let mut v = [0xDEADBEEFu64];
     v.sort();
@@ -441,13 +442,6 @@ fn test_sort_stability() {
     }
 }
 
-#[test]
-fn test_sort_zero_sized_type() {
-    // Should not panic.
-    [(); 10].sort();
-    [(); 100].sort();
-}
-
 #[test]
 fn test_concat() {
     let v: [Vec<i32>; 0] = [];
index 3d124a8aa8b75275cdc59844a945cc250576e5a6..af61342749319655b6803d3afb66e33a4eb77ba6 100644 (file)
 #![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/slice.rs b/src/libcore/slice.rs
deleted file mode 100644 (file)
index 22658f9..0000000
+++ /dev/null
@@ -1,2382 +0,0 @@
-// 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.
-
-//! Slice management and manipulation
-//!
-//! For more details see [`std::slice`].
-//!
-//! [`std::slice`]: ../../std/slice/index.html
-
-#![stable(feature = "rust1", since = "1.0.0")]
-
-// How this module is organized.
-//
-// The library infrastructure for slices is fairly messy. There's
-// a lot of stuff defined here. Let's keep it clean.
-//
-// Since slices don't support inherent methods; all operations
-// on them are defined on traits, which are then reexported from
-// the prelude for convenience. So there are a lot of traits here.
-//
-// The layout of this file is thus:
-//
-// * Slice-specific 'extension' traits and their implementations. This
-//   is where most of the slice API resides.
-// * Implementations of a few common traits with important slice ops.
-// * Definitions of a bunch of iterators.
-// * Free functions.
-// * The `raw` and `bytes` submodules.
-// * Boilerplate trait implementations.
-
-use borrow::Borrow;
-use cmp::Ordering::{self, Less, Equal, Greater};
-use cmp;
-use fmt;
-use intrinsics::assume;
-use iter::*;
-use ops::{FnMut, self};
-use option::Option;
-use option::Option::{None, Some};
-use result::Result;
-use result::Result::{Ok, Err};
-use ptr;
-use mem;
-use marker::{Copy, Send, Sync, Sized, self};
-use iter_private::TrustedRandomAccess;
-
-#[repr(C)]
-struct Repr<T> {
-    pub data: *const T,
-    pub len: usize,
-}
-
-//
-// Extension traits
-//
-
-/// Extension methods for slices.
-#[unstable(feature = "core_slice_ext",
-           reason = "stable interface provided by `impl [T]` in later crates",
-           issue = "32110")]
-#[allow(missing_docs)] // documented elsewhere
-pub trait SliceExt {
-    type Item;
-
-    #[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;
-    #[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;
-    #[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;
-    #[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>;
-    #[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>;
-    #[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>;
-    #[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;
-    #[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;
-    #[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;
-    #[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>;
-    #[stable(feature = "core", since = "1.6.0")]
-    fn as_mut_ptr(&mut self) -> *mut Self::Item;
-
-    #[stable(feature = "core", since = "1.6.0")]
-    fn contains(&self, x: &Self::Item) -> bool where Self::Item: PartialEq;
-
-    #[stable(feature = "core", since = "1.6.0")]
-    fn starts_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq;
-
-    #[stable(feature = "core", since = "1.6.0")]
-    fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq;
-
-    #[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;
-}
-
-// Use macros to be generic over const/mut
-macro_rules! slice_offset {
-    ($ptr:expr, $by:expr) => {{
-        let ptr = $ptr;
-        if size_from_ptr(ptr) == 0 {
-            (ptr as *mut i8).wrapping_offset($by) as _
-        } else {
-            ptr.offset($by)
-        }
-    }};
-}
-
-// make a &T from a *const T
-macro_rules! make_ref {
-    ($ptr:expr) => {{
-        let ptr = $ptr;
-        if size_from_ptr(ptr) == 0 {
-            // Use a non-null pointer value
-            &*(1 as *mut _)
-        } else {
-            &*ptr
-        }
-    }};
-}
-
-// make a &mut T from a *mut T
-macro_rules! make_ref_mut {
-    ($ptr:expr) => {{
-        let ptr = $ptr;
-        if size_from_ptr(ptr) == 0 {
-            // Use a non-null pointer value
-            &mut *(1 as *mut _)
-        } else {
-            &mut *ptr
-        }
-    }};
-}
-
-#[unstable(feature = "core_slice_ext",
-           reason = "stable interface provided by `impl [T]` in later crates",
-           issue = "32110")]
-impl<T> SliceExt for [T] {
-    type Item = T;
-
-    #[inline]
-    fn split_at(&self, mid: usize) -> (&[T], &[T]) {
-        (&self[..mid], &self[mid..])
-    }
-
-    #[inline]
-    fn iter(&self) -> Iter<T> {
-        unsafe {
-            let p = if mem::size_of::<T>() == 0 {
-                1 as *const _
-            } else {
-                let p = self.as_ptr();
-                assume(!p.is_null());
-                p
-            };
-
-            Iter {
-                ptr: p,
-                end: slice_offset!(p, self.len() as isize),
-                _marker: marker::PhantomData
-            }
-        }
-    }
-
-    #[inline]
-    fn split<P>(&self, pred: P) -> Split<T, P> where P: FnMut(&T) -> bool {
-        Split {
-            v: self,
-            pred: pred,
-            finished: false
-        }
-    }
-
-    #[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
-            }
-        }
-    }
-
-    #[inline]
-    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
-            }
-        }
-    }
-
-    #[inline]
-    fn windows(&self, size: usize) -> Windows<T> {
-        assert!(size != 0);
-        Windows { v: self, size: size }
-    }
-
-    #[inline]
-    fn chunks(&self, size: usize) -> Chunks<T> {
-        assert!(size != 0);
-        Chunks { v: self, size: size }
-    }
-
-    #[inline]
-    fn get<I>(&self, index: I) -> Option<&I::Output>
-        where I: SliceIndex<T>
-    {
-        index.get(self)
-    }
-
-    #[inline]
-    fn first(&self) -> Option<&T> {
-        if self.is_empty() { None } else { Some(&self[0]) }
-    }
-
-    #[inline]
-    fn split_first(&self) -> Option<(&T, &[T])> {
-        if self.is_empty() { None } else { Some((&self[0], &self[1..])) }
-    }
-
-    #[inline]
-    fn split_last(&self) -> Option<(&T, &[T])> {
-        let len = self.len();
-        if len == 0 { None } else { Some((&self[len - 1], &self[..(len - 1)])) }
-    }
-
-    #[inline]
-    fn last(&self) -> Option<&T> {
-        if self.is_empty() { None } else { Some(&self[self.len() - 1]) }
-    }
-
-    #[inline]
-    unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
-        where I: SliceIndex<T>
-    {
-        index.get_unchecked(self)
-    }
-
-    #[inline]
-    fn as_ptr(&self) -> *const T {
-        self as *const [T] as *const T
-    }
-
-    fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize>
-        where F: FnMut(&'a T) -> Ordering
-    {
-        let mut base = 0usize;
-        let mut s = self;
-
-        loop {
-            let (head, tail) = s.split_at(s.len() >> 1);
-            if tail.is_empty() {
-                return Err(base)
-            }
-            match f(&tail[0]) {
-                Less => {
-                    base += head.len() + 1;
-                    s = &tail[1..];
-                }
-                Greater => s = head,
-                Equal => return Ok(base + head.len()),
-            }
-        }
-    }
-
-    #[inline]
-    fn len(&self) -> usize {
-        unsafe {
-            mem::transmute::<&[T], Repr<T>>(self).len
-        }
-    }
-
-    #[inline]
-    fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
-        where I: SliceIndex<T>
-    {
-        index.get_mut(self)
-    }
-
-    #[inline]
-    fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
-        let len = self.len();
-        let ptr = self.as_mut_ptr();
-
-        unsafe {
-            assert!(mid <= len);
-
-            (from_raw_parts_mut(ptr, mid),
-             from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
-        }
-    }
-
-    #[inline]
-    fn iter_mut(&mut self) -> IterMut<T> {
-        unsafe {
-            let p = if mem::size_of::<T>() == 0 {
-                1 as *mut _
-            } else {
-                let p = self.as_mut_ptr();
-                assume(!p.is_null());
-                p
-            };
-
-            IterMut {
-                ptr: p,
-                end: slice_offset!(p, self.len() as isize),
-                _marker: marker::PhantomData
-            }
-        }
-    }
-
-    #[inline]
-    fn last_mut(&mut self) -> Option<&mut T> {
-        let len = self.len();
-        if len == 0 { return None; }
-        Some(&mut self[len - 1])
-    }
-
-    #[inline]
-    fn first_mut(&mut self) -> Option<&mut T> {
-        if self.is_empty() { None } else { Some(&mut self[0]) }
-    }
-
-    #[inline]
-    fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
-        if self.is_empty() { None } else {
-            let split = self.split_at_mut(1);
-            Some((&mut split.0[0], split.1))
-        }
-    }
-
-    #[inline]
-    fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
-        let len = self.len();
-        if len == 0 { None } else {
-            let split = self.split_at_mut(len - 1);
-            Some((&mut split.1[0], split.0))
-        }
-    }
-
-    #[inline]
-    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
-    {
-        SplitNMut {
-            inner: GenericSplitN {
-                iter: self.split_mut(pred),
-                count: n,
-                invert: false
-            }
-        }
-    }
-
-    #[inline]
-    fn rsplitn_mut<P>(&mut self, n: usize, pred: P) -> RSplitNMut<T, P> where
-        P: FnMut(&T) -> bool,
-    {
-        RSplitNMut {
-            inner: GenericSplitN {
-                iter: self.split_mut(pred),
-                count: n,
-                invert: true
-            }
-        }
-   }
-
-    #[inline]
-    fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<T> {
-        assert!(chunk_size > 0);
-        ChunksMut { v: self, chunk_size: chunk_size }
-    }
-
-    #[inline]
-    fn swap(&mut self, a: usize, b: usize) {
-        unsafe {
-            // Can't take two mutable loans from one vector, so instead just cast
-            // them to their raw pointers to do the swap
-            let pa: *mut T = &mut self[a];
-            let pb: *mut T = &mut self[b];
-            ptr::swap(pa, pb);
-        }
-    }
-
-    fn reverse(&mut self) {
-        let mut i: usize = 0;
-        let ln = self.len();
-        while i < ln / 2 {
-            // Unsafe swap to avoid the bounds check in safe swap.
-            unsafe {
-                let pa: *mut T = self.get_unchecked_mut(i);
-                let pb: *mut T = self.get_unchecked_mut(ln - i - 1);
-                ptr::swap(pa, pb);
-            }
-            i += 1;
-        }
-    }
-
-    #[inline]
-    unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
-        where I: SliceIndex<T>
-    {
-        index.get_unchecked_mut(self)
-    }
-
-    #[inline]
-    fn as_mut_ptr(&mut self) -> *mut T {
-        self as *mut [T] as *mut T
-    }
-
-    #[inline]
-    fn contains(&self, x: &T) -> bool where T: PartialEq {
-        self.iter().any(|elt| *x == *elt)
-    }
-
-    #[inline]
-    fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq {
-        let n = needle.len();
-        self.len() >= n && needle == &self[..n]
-    }
-
-    #[inline]
-    fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq {
-        let (m, n) = (self.len(), needle.len());
-        m >= n && needle == &self[m-n..]
-    }
-
-    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))
-    }
-
-    #[inline]
-    fn clone_from_slice(&mut self, src: &[T]) where T: Clone {
-        assert!(self.len() == src.len(),
-                "destination and source slices have different lengths");
-        // NOTE: We need to explicitly slice them to the same length
-        // for bounds checking to be elided, and the optimizer will
-        // generate memcpy for simple cases (for example T = u8).
-        let len = self.len();
-        let src = &src[..len];
-        for i in 0..len {
-            self[i].clone_from(&src[i]);
-        }
-    }
-
-    #[inline]
-    fn copy_from_slice(&mut self, src: &[T]) where T: Copy {
-        assert!(self.len() == src.len(),
-                "destination and source slices have different lengths");
-        unsafe {
-            ptr::copy_nonoverlapping(
-                src.as_ptr(), self.as_mut_ptr(), self.len());
-        }
-    }
-
-    #[inline]
-    fn binary_search_by_key<'a, B, F, Q: ?Sized>(&'a self, b: &Q, mut f: F) -> Result<usize, usize>
-        where F: FnMut(&'a Self::Item) -> B,
-              B: Borrow<Q>,
-              Q: Ord
-    {
-        self.binary_search_by(|k| f(k).borrow().cmp(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>
-{
-    type Output = I::Output;
-
-    #[inline]
-    fn index(&self, index: I) -> &I::Output {
-        index.index(self)
-    }
-}
-
-#[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>
-{
-    #[inline]
-    fn index_mut(&mut self, index: I) -> &mut I::Output {
-        index.index_mut(self)
-    }
-}
-
-#[inline(never)]
-#[cold]
-fn slice_index_len_fail(index: usize, len: usize) -> ! {
-    panic!("index {} out of range for slice of length {}", index, len);
-}
-
-#[inline(never)]
-#[cold]
-fn slice_index_order_fail(index: usize, end: usize) -> ! {
-    panic!("slice index starts at {} but ends at {}", index, end);
-}
-
-/// 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> {
-    /// 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>;
-
-    /// Returns a mutable reference to the output at this location, if in
-    /// bounds.
-    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;
-
-    /// 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;
-
-    /// Returns a shared reference to the output at this location, panicking
-    /// if out of bounds.
-    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;
-}
-
-#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
-impl<T> SliceIndex<T> for usize {
-    type Output = T;
-
-    #[inline]
-    fn get(self, slice: &[T]) -> Option<&T> {
-        if self < slice.len() {
-            unsafe {
-                Some(self.get_unchecked(slice))
-            }
-        } else {
-            None
-        }
-    }
-
-    #[inline]
-    fn get_mut(self, slice: &mut [T]) -> Option<&mut T> {
-        if self < slice.len() {
-            unsafe {
-                Some(self.get_unchecked_mut(slice))
-            }
-        } else {
-            None
-        }
-    }
-
-    #[inline]
-    unsafe fn get_unchecked(self, slice: &[T]) -> &T {
-        &*slice.as_ptr().offset(self as isize)
-    }
-
-    #[inline]
-    unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut T {
-        &mut *slice.as_mut_ptr().offset(self as isize)
-    }
-
-    #[inline]
-    fn index(self, slice: &[T]) -> &T {
-        // NB: use intrinsic indexing
-        &(*slice)[self]
-    }
-
-    #[inline]
-    fn index_mut(self, slice: &mut [T]) -> &mut T {
-        // NB: use intrinsic indexing
-        &mut (*slice)[self]
-    }
-}
-
-#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
-impl<T> SliceIndex<T> for  ops::Range<usize> {
-    type Output = [T];
-
-    #[inline]
-    fn get(self, slice: &[T]) -> Option<&[T]> {
-        if self.start > self.end || self.end > slice.len() {
-            None
-        } else {
-            unsafe {
-                Some(self.get_unchecked(slice))
-            }
-        }
-    }
-
-    #[inline]
-    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
-        if self.start > self.end || self.end > slice.len() {
-            None
-        } else {
-            unsafe {
-                Some(self.get_unchecked_mut(slice))
-            }
-        }
-    }
-
-    #[inline]
-    unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
-        from_raw_parts(slice.as_ptr().offset(self.start as isize), self.end - self.start)
-    }
-
-    #[inline]
-    unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
-        from_raw_parts_mut(slice.as_mut_ptr().offset(self.start as isize), self.end - self.start)
-    }
-
-    #[inline]
-    fn index(self, slice: &[T]) -> &[T] {
-        if self.start > self.end {
-            slice_index_order_fail(self.start, self.end);
-        } else if self.end > slice.len() {
-            slice_index_len_fail(self.end, slice.len());
-        }
-        unsafe {
-            self.get_unchecked(slice)
-        }
-    }
-
-    #[inline]
-    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
-        if self.start > self.end {
-            slice_index_order_fail(self.start, self.end);
-        } else if self.end > slice.len() {
-            slice_index_len_fail(self.end, slice.len());
-        }
-        unsafe {
-            self.get_unchecked_mut(slice)
-        }
-    }
-}
-
-#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
-impl<T> SliceIndex<T> for ops::RangeTo<usize> {
-    type Output = [T];
-
-    #[inline]
-    fn get(self, slice: &[T]) -> Option<&[T]> {
-        (0..self.end).get(slice)
-    }
-
-    #[inline]
-    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
-        (0..self.end).get_mut(slice)
-    }
-
-    #[inline]
-    unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
-        (0..self.end).get_unchecked(slice)
-    }
-
-    #[inline]
-    unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
-        (0..self.end).get_unchecked_mut(slice)
-    }
-
-    #[inline]
-    fn index(self, slice: &[T]) -> &[T] {
-        (0..self.end).index(slice)
-    }
-
-    #[inline]
-    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
-        (0..self.end).index_mut(slice)
-    }
-}
-
-#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
-impl<T> SliceIndex<T> for ops::RangeFrom<usize> {
-    type Output = [T];
-
-    #[inline]
-    fn get(self, slice: &[T]) -> Option<&[T]> {
-        (self.start..slice.len()).get(slice)
-    }
-
-    #[inline]
-    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
-        (self.start..slice.len()).get_mut(slice)
-    }
-
-    #[inline]
-    unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
-        (self.start..slice.len()).get_unchecked(slice)
-    }
-
-    #[inline]
-    unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
-        (self.start..slice.len()).get_unchecked_mut(slice)
-    }
-
-    #[inline]
-    fn index(self, slice: &[T]) -> &[T] {
-        (self.start..slice.len()).index(slice)
-    }
-
-    #[inline]
-    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
-        (self.start..slice.len()).index_mut(slice)
-    }
-}
-
-#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
-impl<T> SliceIndex<T> for ops::RangeFull {
-    type Output = [T];
-
-    #[inline]
-    fn get(self, slice: &[T]) -> Option<&[T]> {
-        Some(slice)
-    }
-
-    #[inline]
-    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
-        Some(slice)
-    }
-
-    #[inline]
-    unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
-        slice
-    }
-
-    #[inline]
-    unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
-        slice
-    }
-
-    #[inline]
-    fn index(self, slice: &[T]) -> &[T] {
-        slice
-    }
-
-    #[inline]
-    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
-        slice
-    }
-}
-
-
-#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
-impl<T> SliceIndex<T> for ops::RangeInclusive<usize> {
-    type Output = [T];
-
-    #[inline]
-    fn get(self, slice: &[T]) -> Option<&[T]> {
-        match self {
-            ops::RangeInclusive::Empty { .. } => Some(&[]),
-            ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => None,
-            ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).get(slice),
-        }
-    }
-
-    #[inline]
-    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
-        match self {
-            ops::RangeInclusive::Empty { .. } => Some(&mut []),
-            ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => None,
-            ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).get_mut(slice),
-        }
-    }
-
-    #[inline]
-    unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
-        match self {
-            ops::RangeInclusive::Empty { .. } => &[],
-            ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).get_unchecked(slice),
-        }
-    }
-
-    #[inline]
-    unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
-        match self {
-            ops::RangeInclusive::Empty { .. } => &mut [],
-            ops::RangeInclusive::NonEmpty { start, end } => {
-                (start..end + 1).get_unchecked_mut(slice)
-            }
-        }
-    }
-
-    #[inline]
-    fn index(self, slice: &[T]) -> &[T] {
-        match self {
-            ops::RangeInclusive::Empty { .. } => &[],
-            ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => {
-                panic!("attempted to index slice up to maximum usize");
-            },
-            ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).index(slice),
-        }
-    }
-
-    #[inline]
-    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
-        match self {
-            ops::RangeInclusive::Empty { .. } => &mut [],
-            ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => {
-                panic!("attempted to index slice up to maximum usize");
-            },
-            ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).index_mut(slice),
-        }
-    }
-}
-
-#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
-impl<T> SliceIndex<T> for ops::RangeToInclusive<usize> {
-    type Output = [T];
-
-    #[inline]
-    fn get(self, slice: &[T]) -> Option<&[T]> {
-        (0...self.end).get(slice)
-    }
-
-    #[inline]
-    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
-        (0...self.end).get_mut(slice)
-    }
-
-    #[inline]
-    unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
-        (0...self.end).get_unchecked(slice)
-    }
-
-    #[inline]
-    unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
-        (0...self.end).get_unchecked_mut(slice)
-    }
-
-    #[inline]
-    fn index(self, slice: &[T]) -> &[T] {
-        (0...self.end).index(slice)
-    }
-
-    #[inline]
-    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
-        (0...self.end).index_mut(slice)
-    }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Common traits
-////////////////////////////////////////////////////////////////////////////////
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> Default for &'a [T] {
-    /// Creates an empty slice.
-    fn default() -> &'a [T] { &[] }
-}
-
-#[stable(feature = "mut_slice_default", since = "1.5.0")]
-impl<'a, T> Default for &'a mut [T] {
-    /// Creates a mutable empty slice.
-    fn default() -> &'a mut [T] { &mut [] }
-}
-
-//
-// Iterators
-//
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> IntoIterator for &'a [T] {
-    type Item = &'a T;
-    type IntoIter = Iter<'a, T>;
-
-    fn into_iter(self) -> Iter<'a, T> {
-        self.iter()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> IntoIterator for &'a mut [T] {
-    type Item = &'a mut T;
-    type IntoIter = IterMut<'a, T>;
-
-    fn into_iter(self) -> IterMut<'a, T> {
-        self.iter_mut()
-    }
-}
-
-#[inline(always)]
-fn size_from_ptr<T>(_: *const T) -> usize {
-    mem::size_of::<T>()
-}
-
-// The shared definition of the `Iter` and `IterMut` iterators
-macro_rules! iterator {
-    (struct $name:ident -> $ptr:ty, $elem:ty, $mkref:ident) => {
-        #[stable(feature = "rust1", since = "1.0.0")]
-        impl<'a, T> Iterator for $name<'a, T> {
-            type Item = $elem;
-
-            #[inline]
-            fn next(&mut self) -> Option<$elem> {
-                // could be implemented with slices, but this avoids bounds checks
-                unsafe {
-                    if mem::size_of::<T>() != 0 {
-                        assume(!self.ptr.is_null());
-                        assume(!self.end.is_null());
-                    }
-                    if self.ptr == self.end {
-                        None
-                    } else {
-                        Some($mkref!(self.ptr.post_inc()))
-                    }
-                }
-            }
-
-            #[inline]
-            fn size_hint(&self) -> (usize, Option<usize>) {
-                let exact = ptrdistance(self.ptr, self.end);
-                (exact, Some(exact))
-            }
-
-            #[inline]
-            fn count(self) -> usize {
-                self.len()
-            }
-
-            #[inline]
-            fn nth(&mut self, n: usize) -> Option<$elem> {
-                // Call helper method. Can't put the definition here because mut versus const.
-                self.iter_nth(n)
-            }
-
-            #[inline]
-            fn last(mut self) -> Option<$elem> {
-                self.next_back()
-            }
-
-            fn all<F>(&mut self, mut predicate: F) -> bool
-                where F: FnMut(Self::Item) -> bool,
-            {
-                self.search_while(true, move |elt| {
-                    if predicate(elt) {
-                        SearchWhile::Continue
-                    } else {
-                        SearchWhile::Done(false)
-                    }
-                })
-            }
-
-            fn any<F>(&mut self, mut predicate: F) -> bool
-                where F: FnMut(Self::Item) -> bool,
-            {
-                !self.all(move |elt| !predicate(elt))
-            }
-
-            fn find<F>(&mut self, mut predicate: F) -> Option<Self::Item>
-                where F: FnMut(&Self::Item) -> bool,
-            {
-                self.search_while(None, move |elt| {
-                    if predicate(&elt) {
-                        SearchWhile::Done(Some(elt))
-                    } else {
-                        SearchWhile::Continue
-                    }
-                })
-            }
-
-            fn position<F>(&mut self, mut predicate: F) -> Option<usize>
-                where F: FnMut(Self::Item) -> bool,
-            {
-                let mut index = 0;
-                self.search_while(None, move |elt| {
-                    if predicate(elt) {
-                        SearchWhile::Done(Some(index))
-                    } else {
-                        index += 1;
-                        SearchWhile::Continue
-                    }
-                })
-            }
-
-            fn rposition<F>(&mut self, mut predicate: F) -> Option<usize>
-                where F: FnMut(Self::Item) -> bool,
-            {
-                let mut index = self.len();
-                self.rsearch_while(None, move |elt| {
-                    index -= 1;
-                    if predicate(elt) {
-                        SearchWhile::Done(Some(index))
-                    } else {
-                        SearchWhile::Continue
-                    }
-                })
-            }
-        }
-
-        #[stable(feature = "rust1", since = "1.0.0")]
-        impl<'a, T> DoubleEndedIterator for $name<'a, T> {
-            #[inline]
-            fn next_back(&mut self) -> Option<$elem> {
-                // could be implemented with slices, but this avoids bounds checks
-                unsafe {
-                    if mem::size_of::<T>() != 0 {
-                        assume(!self.ptr.is_null());
-                        assume(!self.end.is_null());
-                    }
-                    if self.end == self.ptr {
-                        None
-                    } else {
-                        Some($mkref!(self.end.pre_dec()))
-                    }
-                }
-            }
-        }
-
-        // search_while is a generalization of the internal iteration methods.
-        impl<'a, T> $name<'a, T> {
-            // search through the iterator's element using the closure `g`.
-            // if no element was found, return `default`.
-            fn search_while<Acc, G>(&mut self, default: Acc, mut g: G) -> Acc
-                where Self: Sized,
-                      G: FnMut($elem) -> SearchWhile<Acc>
-            {
-                // manual unrolling is needed when there are conditional exits from the loop
-                unsafe {
-                    while ptrdistance(self.ptr, self.end) >= 4 {
-                        search_while!(g($mkref!(self.ptr.post_inc())));
-                        search_while!(g($mkref!(self.ptr.post_inc())));
-                        search_while!(g($mkref!(self.ptr.post_inc())));
-                        search_while!(g($mkref!(self.ptr.post_inc())));
-                    }
-                    while self.ptr != self.end {
-                        search_while!(g($mkref!(self.ptr.post_inc())));
-                    }
-                }
-                default
-            }
-
-            fn rsearch_while<Acc, G>(&mut self, default: Acc, mut g: G) -> Acc
-                where Self: Sized,
-                      G: FnMut($elem) -> SearchWhile<Acc>
-            {
-                unsafe {
-                    while ptrdistance(self.ptr, self.end) >= 4 {
-                        search_while!(g($mkref!(self.end.pre_dec())));
-                        search_while!(g($mkref!(self.end.pre_dec())));
-                        search_while!(g($mkref!(self.end.pre_dec())));
-                        search_while!(g($mkref!(self.end.pre_dec())));
-                    }
-                    while self.ptr != self.end {
-                        search_while!(g($mkref!(self.end.pre_dec())));
-                    }
-                }
-                default
-            }
-        }
-    }
-}
-
-macro_rules! make_slice {
-    ($start: expr, $end: expr) => {{
-        let start = $start;
-        let diff = ($end as usize).wrapping_sub(start as usize);
-        if size_from_ptr(start) == 0 {
-            // use a non-null pointer value
-            unsafe { from_raw_parts(1 as *const _, diff) }
-        } else {
-            let len = diff / size_from_ptr(start);
-            unsafe { from_raw_parts(start, len) }
-        }
-    }}
-}
-
-macro_rules! make_mut_slice {
-    ($start: expr, $end: expr) => {{
-        let start = $start;
-        let diff = ($end as usize).wrapping_sub(start as usize);
-        if size_from_ptr(start) == 0 {
-            // use a non-null pointer value
-            unsafe { from_raw_parts_mut(1 as *mut _, diff) }
-        } else {
-            let len = diff / size_from_ptr(start);
-            unsafe { from_raw_parts_mut(start, len) }
-        }
-    }}
-}
-
-// An enum used for controlling the execution of `.search_while()`.
-enum SearchWhile<T> {
-    // Continue searching
-    Continue,
-    // Fold is complete and will return this value
-    Done(T),
-}
-
-// helper macro for search while's control flow
-macro_rules! search_while {
-    ($e:expr) => {
-        match $e {
-            SearchWhile::Continue => { }
-            SearchWhile::Done(done) => return done,
-        }
-    }
-}
-
-/// Immutable slice iterator
-///
-/// This struct is created by the [`iter`] method on [slices].
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// // First, we declare a type which has `iter` method to get the `Iter` struct (&[usize here]):
-/// let slice = &[1, 2, 3];
-///
-/// // Then, we iterate over it:
-/// for element in slice.iter() {
-///     println!("{}", element);
-/// }
-/// ```
-///
-/// [`iter`]: ../../std/primitive.slice.html#method.iter
-/// [slices]: ../../std/primitive.slice.html
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Iter<'a, T: 'a> {
-    ptr: *const T,
-    end: *const T,
-    _marker: marker::PhantomData<&'a T>,
-}
-
-#[stable(feature = "core_impl_debug", since = "1.9.0")]
-impl<'a, T: 'a + fmt::Debug> fmt::Debug for Iter<'a, T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_tuple("Iter")
-            .field(&self.as_slice())
-            .finish()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<'a, T: Sync> Sync for Iter<'a, T> {}
-#[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<'a, T: Sync> Send for Iter<'a, T> {}
-
-impl<'a, T> Iter<'a, T> {
-    /// View the underlying data as a subslice of the original data.
-    ///
-    /// This has the same lifetime as the original slice, and so the
-    /// iterator can continue to be used while this exists.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// // First, we declare a type which has the `iter` method to get the `Iter`
-    /// // struct (&[usize here]):
-    /// let slice = &[1, 2, 3];
-    ///
-    /// // Then, we get the iterator:
-    /// let mut iter = slice.iter();
-    /// // So if we print what `as_slice` method returns here, we have "[1, 2, 3]":
-    /// println!("{:?}", iter.as_slice());
-    ///
-    /// // Next, we move to the second element of the slice:
-    /// iter.next();
-    /// // Now `as_slice` returns "[2, 3]":
-    /// println!("{:?}", iter.as_slice());
-    /// ```
-    #[stable(feature = "iter_to_slice", since = "1.4.0")]
-    pub fn as_slice(&self) -> &'a [T] {
-        make_slice!(self.ptr, self.end)
-    }
-
-    // Helper function for Iter::nth
-    fn iter_nth(&mut self, n: usize) -> Option<&'a T> {
-        match self.as_slice().get(n) {
-            Some(elem_ref) => unsafe {
-                self.ptr = slice_offset!(self.ptr, (n as isize).wrapping_add(1));
-                Some(elem_ref)
-            },
-            None => {
-                self.ptr = self.end;
-                None
-            }
-        }
-    }
-}
-
-iterator!{struct Iter -> *const T, &'a T, make_ref}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> ExactSizeIterator for Iter<'a, T> {
-    fn is_empty(&self) -> bool {
-        self.ptr == self.end
-    }
-}
-
-#[unstable(feature = "fused", issue = "35602")]
-impl<'a, T> FusedIterator for Iter<'a, T> {}
-
-#[unstable(feature = "trusted_len", issue = "37572")]
-unsafe impl<'a, T> TrustedLen for Iter<'a, T> {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> Clone for Iter<'a, T> {
-    fn clone(&self) -> Iter<'a, T> { Iter { ptr: self.ptr, end: self.end, _marker: self._marker } }
-}
-
-#[stable(feature = "slice_iter_as_ref", since = "1.12.0")]
-impl<'a, T> AsRef<[T]> for Iter<'a, T> {
-    fn as_ref(&self) -> &[T] {
-        self.as_slice()
-    }
-}
-
-/// Mutable slice iterator.
-///
-/// This struct is created by the [`iter_mut`] method on [slices].
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// // First, we declare a type which has `iter_mut` method to get the `IterMut`
-/// // struct (&[usize here]):
-/// let mut slice = &mut [1, 2, 3];
-///
-/// // Then, we iterate over it and increment each element value:
-/// for element in slice.iter_mut() {
-///     *element += 1;
-/// }
-///
-/// // We now have "[2, 3, 4]":
-/// println!("{:?}", slice);
-/// ```
-///
-/// [`iter_mut`]: ../../std/primitive.slice.html#method.iter_mut
-/// [slices]: ../../std/primitive.slice.html
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct IterMut<'a, T: 'a> {
-    ptr: *mut T,
-    end: *mut T,
-    _marker: marker::PhantomData<&'a mut T>,
-}
-
-#[stable(feature = "core_impl_debug", since = "1.9.0")]
-impl<'a, T: 'a + fmt::Debug> fmt::Debug for IterMut<'a, T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_tuple("IterMut")
-            .field(&make_slice!(self.ptr, self.end))
-            .finish()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<'a, T: Sync> Sync for IterMut<'a, T> {}
-#[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<'a, T: Send> Send for IterMut<'a, T> {}
-
-impl<'a, T> IterMut<'a, T> {
-    /// View the underlying data as a subslice of the original data.
-    ///
-    /// To avoid creating `&mut` references that alias, this is forced
-    /// to consume the iterator. Consider using the `Slice` and
-    /// `SliceMut` implementations for obtaining slices with more
-    /// restricted lifetimes that do not consume the iterator.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// // First, we declare a type which has `iter_mut` method to get the `IterMut`
-    /// // struct (&[usize here]):
-    /// let mut slice = &mut [1, 2, 3];
-    ///
-    /// {
-    ///     // Then, we get the iterator:
-    ///     let mut iter = slice.iter_mut();
-    ///     // We move to next element:
-    ///     iter.next();
-    ///     // So if we print what `into_slice` method returns here, we have "[2, 3]":
-    ///     println!("{:?}", iter.into_slice());
-    /// }
-    ///
-    /// // Now let's modify a value of the slice:
-    /// {
-    ///     // First we get back the iterator:
-    ///     let mut iter = slice.iter_mut();
-    ///     // We change the value of the first element of the slice returned by the `next` method:
-    ///     *iter.next().unwrap() += 1;
-    /// }
-    /// // Now slice is "[2, 2, 3]":
-    /// println!("{:?}", slice);
-    /// ```
-    #[stable(feature = "iter_to_slice", since = "1.4.0")]
-    pub fn into_slice(self) -> &'a mut [T] {
-        make_mut_slice!(self.ptr, self.end)
-    }
-
-    // Helper function for IterMut::nth
-    fn iter_nth(&mut self, n: usize) -> Option<&'a mut T> {
-        match make_mut_slice!(self.ptr, self.end).get_mut(n) {
-            Some(elem_ref) => unsafe {
-                self.ptr = slice_offset!(self.ptr, (n as isize).wrapping_add(1));
-                Some(elem_ref)
-            },
-            None => {
-                self.ptr = self.end;
-                None
-            }
-        }
-    }
-}
-
-iterator!{struct IterMut -> *mut T, &'a mut T, make_ref_mut}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
-    fn is_empty(&self) -> bool {
-        self.ptr == self.end
-    }
-}
-
-#[unstable(feature = "fused", issue = "35602")]
-impl<'a, T> FusedIterator for IterMut<'a, T> {}
-
-#[unstable(feature = "trusted_len", issue = "37572")]
-unsafe impl<'a, T> TrustedLen for IterMut<'a, T> {}
-
-
-// Return the number of elements of `T` from `start` to `end`.
-// 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 })
-}
-
-// 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
-    #[inline(always)]
-    unsafe fn post_inc(&mut self) -> Self {
-        let current = *self;
-        *self = self.slice_offset(1);
-        current
-    }
-
-    /// Decrement self by 1, and return the new value
-    #[inline(always)]
-    unsafe fn pre_dec(&mut self) -> Self {
-        *self = self.slice_offset(-1);
-        *self
-    }
-}
-
-impl<T> PointerExt for *const T {
-    #[inline(always)]
-    unsafe fn slice_offset(self, i: isize) -> Self {
-        slice_offset!(self, i)
-    }
-}
-
-impl<T> PointerExt for *mut T {
-    #[inline(always)]
-    unsafe fn slice_offset(self, i: isize) -> Self {
-        slice_offset!(self, i)
-    }
-}
-
-/// An internal abstraction over the splitting iterators, so that
-/// splitn, splitn_mut etc can be implemented once.
-#[doc(hidden)]
-trait SplitIter: DoubleEndedIterator {
-    /// Mark the underlying iterator as complete, extracting the remaining
-    /// portion of the slice.
-    fn finish(&mut self) -> Option<Self::Item>;
-}
-
-/// An iterator over subslices separated by elements that match a predicate
-/// function.
-///
-/// This struct is created by the [`split`] method on [slices].
-///
-/// [`split`]: ../../std/primitive.slice.html#method.split
-/// [slices]: ../../std/primitive.slice.html
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Split<'a, T:'a, P> where P: FnMut(&T) -> bool {
-    v: &'a [T],
-    pred: P,
-    finished: bool
-}
-
-#[stable(feature = "core_impl_debug", since = "1.9.0")]
-impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for Split<'a, T, P> where P: FnMut(&T) -> bool {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("Split")
-            .field("v", &self.v)
-            .field("finished", &self.finished)
-            .finish()
-    }
-}
-
-// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, P> Clone for Split<'a, T, P> where P: Clone + FnMut(&T) -> bool {
-    fn clone(&self) -> Split<'a, T, P> {
-        Split {
-            v: self.v,
-            pred: self.pred.clone(),
-            finished: self.finished,
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, P> Iterator for Split<'a, T, P> where P: FnMut(&T) -> bool {
-    type Item = &'a [T];
-
-    #[inline]
-    fn next(&mut self) -> Option<&'a [T]> {
-        if self.finished { return None; }
-
-        match self.v.iter().position(|x| (self.pred)(x)) {
-            None => self.finish(),
-            Some(idx) => {
-                let ret = Some(&self.v[..idx]);
-                self.v = &self.v[idx + 1..];
-                ret
-            }
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        if self.finished {
-            (0, Some(0))
-        } else {
-            (1, Some(self.v.len() + 1))
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, P> DoubleEndedIterator for Split<'a, T, P> where P: FnMut(&T) -> bool {
-    #[inline]
-    fn next_back(&mut self) -> Option<&'a [T]> {
-        if self.finished { return None; }
-
-        match self.v.iter().rposition(|x| (self.pred)(x)) {
-            None => self.finish(),
-            Some(idx) => {
-                let ret = Some(&self.v[idx + 1..]);
-                self.v = &self.v[..idx];
-                ret
-            }
-        }
-    }
-}
-
-impl<'a, T, P> SplitIter for Split<'a, T, P> where P: FnMut(&T) -> bool {
-    #[inline]
-    fn finish(&mut self) -> Option<&'a [T]> {
-        if self.finished { None } else { self.finished = true; Some(self.v) }
-    }
-}
-
-#[unstable(feature = "fused", issue = "35602")]
-impl<'a, T, P> FusedIterator for Split<'a, T, P> where P: FnMut(&T) -> bool {}
-
-/// An iterator over the subslices of the vector which are separated
-/// by elements that match `pred`.
-///
-/// This struct is created by the [`split_mut`] method on [slices].
-///
-/// [`split_mut`]: ../../std/primitive.slice.html#method.split_mut
-/// [slices]: ../../std/primitive.slice.html
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct SplitMut<'a, T:'a, P> where P: FnMut(&T) -> bool {
-    v: &'a mut [T],
-    pred: P,
-    finished: bool
-}
-
-#[stable(feature = "core_impl_debug", since = "1.9.0")]
-impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("SplitMut")
-            .field("v", &self.v)
-            .field("finished", &self.finished)
-            .finish()
-    }
-}
-
-impl<'a, T, P> SplitIter for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {
-    #[inline]
-    fn finish(&mut self) -> Option<&'a mut [T]> {
-        if self.finished {
-            None
-        } else {
-            self.finished = true;
-            Some(mem::replace(&mut self.v, &mut []))
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, P> Iterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {
-    type Item = &'a mut [T];
-
-    #[inline]
-    fn next(&mut self) -> Option<&'a mut [T]> {
-        if self.finished { return None; }
-
-        let idx_opt = { // work around borrowck limitations
-            let pred = &mut self.pred;
-            self.v.iter().position(|x| (*pred)(x))
-        };
-        match idx_opt {
-            None => self.finish(),
-            Some(idx) => {
-                let tmp = mem::replace(&mut self.v, &mut []);
-                let (head, tail) = tmp.split_at_mut(idx);
-                self.v = &mut tail[1..];
-                Some(head)
-            }
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        if self.finished {
-            (0, Some(0))
-        } else {
-            // if the predicate doesn't match anything, we yield one slice
-            // if it matches every element, we yield len+1 empty slices.
-            (1, Some(self.v.len() + 1))
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, P> DoubleEndedIterator for SplitMut<'a, T, P> where
-    P: FnMut(&T) -> bool,
-{
-    #[inline]
-    fn next_back(&mut self) -> Option<&'a mut [T]> {
-        if self.finished { return None; }
-
-        let idx_opt = { // work around borrowck limitations
-            let pred = &mut self.pred;
-            self.v.iter().rposition(|x| (*pred)(x))
-        };
-        match idx_opt {
-            None => self.finish(),
-            Some(idx) => {
-                let tmp = mem::replace(&mut self.v, &mut []);
-                let (head, tail) = tmp.split_at_mut(idx);
-                self.v = head;
-                Some(&mut tail[1..])
-            }
-        }
-    }
-}
-
-#[unstable(feature = "fused", issue = "35602")]
-impl<'a, T, P> FusedIterator for SplitMut<'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.
-#[derive(Debug)]
-struct GenericSplitN<I> {
-    iter: I,
-    count: usize,
-    invert: bool
-}
-
-impl<T, I: SplitIter<Item=T>> Iterator for GenericSplitN<I> {
-    type Item = T;
-
-    #[inline]
-    fn next(&mut self) -> Option<T> {
-        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()}
-            }
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (lower, upper_opt) = self.iter.size_hint();
-        (lower, upper_opt.map(|upper| cmp::min(self.count, upper)))
-    }
-}
-
-/// An iterator over subslices separated by elements that match a predicate
-/// function, limited to a given number of splits.
-///
-/// This struct is created by the [`splitn`] method on [slices].
-///
-/// [`splitn`]: ../../std/primitive.slice.html#method.splitn
-/// [slices]: ../../std/primitive.slice.html
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct SplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool {
-    inner: GenericSplitN<Split<'a, T, P>>
-}
-
-#[stable(feature = "core_impl_debug", since = "1.9.0")]
-impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for SplitN<'a, T, P> where P: FnMut(&T) -> bool {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("SplitN")
-            .field("inner", &self.inner)
-            .finish()
-    }
-}
-
-/// An iterator over subslices separated by elements that match a
-/// predicate function, limited to a given number of splits, starting
-/// from the end of the slice.
-///
-/// This struct is created by the [`rsplitn`] method on [slices].
-///
-/// [`rsplitn`]: ../../std/primitive.slice.html#method.rsplitn
-/// [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>>
-}
-
-#[stable(feature = "core_impl_debug", since = "1.9.0")]
-impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for RSplitN<'a, T, P> where P: FnMut(&T) -> bool {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("RSplitN")
-            .field("inner", &self.inner)
-            .finish()
-    }
-}
-
-/// An iterator over subslices separated by elements that match a predicate
-/// function, limited to a given number of splits.
-///
-/// This struct is created by the [`splitn_mut`] method on [slices].
-///
-/// [`splitn_mut`]: ../../std/primitive.slice.html#method.splitn_mut
-/// [slices]: ../../std/primitive.slice.html
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct SplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool {
-    inner: GenericSplitN<SplitMut<'a, T, P>>
-}
-
-#[stable(feature = "core_impl_debug", since = "1.9.0")]
-impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for SplitNMut<'a, T, P> where P: FnMut(&T) -> bool {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("SplitNMut")
-            .field("inner", &self.inner)
-            .finish()
-    }
-}
-
-/// An iterator over subslices separated by elements that match a
-/// predicate function, limited to a given number of splits, starting
-/// from the end of the slice.
-///
-/// This struct is created by the [`rsplitn_mut`] method on [slices].
-///
-/// [`rsplitn_mut`]: ../../std/primitive.slice.html#method.rsplitn_mut
-/// [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>>
-}
-
-#[stable(feature = "core_impl_debug", since = "1.9.0")]
-impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for RSplitNMut<'a, T, P> where P: FnMut(&T) -> bool {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("RSplitNMut")
-            .field("inner", &self.inner)
-            .finish()
-    }
-}
-
-macro_rules! forward_iterator {
-    ($name:ident: $elem:ident, $iter_of:ty) => {
-        #[stable(feature = "rust1", since = "1.0.0")]
-        impl<'a, $elem, P> Iterator for $name<'a, $elem, P> where
-            P: FnMut(&T) -> bool
-        {
-            type Item = $iter_of;
-
-            #[inline]
-            fn next(&mut self) -> Option<$iter_of> {
-                self.inner.next()
-            }
-
-            #[inline]
-            fn size_hint(&self) -> (usize, Option<usize>) {
-                self.inner.size_hint()
-            }
-        }
-
-        #[unstable(feature = "fused", issue = "35602")]
-        impl<'a, $elem, P> FusedIterator for $name<'a, $elem, P>
-            where P: FnMut(&T) -> bool {}
-    }
-}
-
-forward_iterator! { SplitN: T, &'a [T] }
-forward_iterator! { RSplitN: T, &'a [T] }
-forward_iterator! { SplitNMut: T, &'a mut [T] }
-forward_iterator! { RSplitNMut: T, &'a mut [T] }
-
-/// An iterator over overlapping subslices of length `size`.
-///
-/// This struct is created by the [`windows`] method on [slices].
-///
-/// [`windows`]: ../../std/primitive.slice.html#method.windows
-/// [slices]: ../../std/primitive.slice.html
-#[derive(Debug)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Windows<'a, T:'a> {
-    v: &'a [T],
-    size: usize
-}
-
-// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> Clone for Windows<'a, T> {
-    fn clone(&self) -> Windows<'a, T> {
-        Windows {
-            v: self.v,
-            size: self.size,
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> Iterator for Windows<'a, T> {
-    type Item = &'a [T];
-
-    #[inline]
-    fn next(&mut self) -> Option<&'a [T]> {
-        if self.size > self.v.len() {
-            None
-        } else {
-            let ret = Some(&self.v[..self.size]);
-            self.v = &self.v[1..];
-            ret
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        if self.size > self.v.len() {
-            (0, Some(0))
-        } else {
-            let size = self.v.len() - self.size + 1;
-            (size, Some(size))
-        }
-    }
-
-    #[inline]
-    fn count(self) -> usize {
-        self.len()
-    }
-
-    #[inline]
-    fn nth(&mut self, n: usize) -> Option<Self::Item> {
-        let (end, overflow) = self.size.overflowing_add(n);
-        if end > self.v.len() || overflow {
-            self.v = &[];
-            None
-        } else {
-            let nth = &self.v[n..end];
-            self.v = &self.v[n+1..];
-            Some(nth)
-        }
-    }
-
-    #[inline]
-    fn last(self) -> Option<Self::Item> {
-        if self.size > self.v.len() {
-            None
-        } else {
-            let start = self.v.len() - self.size;
-            Some(&self.v[start..])
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> DoubleEndedIterator for Windows<'a, T> {
-    #[inline]
-    fn next_back(&mut self) -> Option<&'a [T]> {
-        if self.size > self.v.len() {
-            None
-        } else {
-            let ret = Some(&self.v[self.v.len()-self.size..]);
-            self.v = &self.v[..self.v.len()-1];
-            ret
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> ExactSizeIterator for Windows<'a, T> {}
-
-#[unstable(feature = "fused", issue = "35602")]
-impl<'a, T> FusedIterator for Windows<'a, T> {}
-
-/// An iterator over a slice in (non-overlapping) chunks (`size` elements at a
-/// time).
-///
-/// When the slice len is not evenly divided by the chunk size, the last slice
-/// of the iteration will be the remainder.
-///
-/// This struct is created by the [`chunks`] method on [slices].
-///
-/// [`chunks`]: ../../std/primitive.slice.html#method.chunks
-/// [slices]: ../../std/primitive.slice.html
-#[derive(Debug)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Chunks<'a, T:'a> {
-    v: &'a [T],
-    size: usize
-}
-
-// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> Clone for Chunks<'a, T> {
-    fn clone(&self) -> Chunks<'a, T> {
-        Chunks {
-            v: self.v,
-            size: self.size,
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> Iterator for Chunks<'a, T> {
-    type Item = &'a [T];
-
-    #[inline]
-    fn next(&mut self) -> Option<&'a [T]> {
-        if self.v.is_empty() {
-            None
-        } else {
-            let chunksz = cmp::min(self.v.len(), self.size);
-            let (fst, snd) = self.v.split_at(chunksz);
-            self.v = snd;
-            Some(fst)
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        if self.v.is_empty() {
-            (0, Some(0))
-        } else {
-            let n = self.v.len() / self.size;
-            let rem = self.v.len() % self.size;
-            let n = if rem > 0 { n+1 } else { n };
-            (n, Some(n))
-        }
-    }
-
-    #[inline]
-    fn count(self) -> usize {
-        self.len()
-    }
-
-    #[inline]
-    fn nth(&mut self, n: usize) -> Option<Self::Item> {
-        let (start, overflow) = n.overflowing_mul(self.size);
-        if start >= self.v.len() || overflow {
-            self.v = &[];
-            None
-        } else {
-            let end = match start.checked_add(self.size) {
-                Some(sum) => cmp::min(self.v.len(), sum),
-                None => self.v.len(),
-            };
-            let nth = &self.v[start..end];
-            self.v = &self.v[end..];
-            Some(nth)
-        }
-    }
-
-    #[inline]
-    fn last(self) -> Option<Self::Item> {
-        if self.v.is_empty() {
-            None
-        } else {
-            let start = (self.v.len() - 1) / self.size * self.size;
-            Some(&self.v[start..])
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> DoubleEndedIterator for Chunks<'a, T> {
-    #[inline]
-    fn next_back(&mut self) -> Option<&'a [T]> {
-        if self.v.is_empty() {
-            None
-        } else {
-            let remainder = self.v.len() % self.size;
-            let chunksz = if remainder != 0 { remainder } else { self.size };
-            let (fst, snd) = self.v.split_at(self.v.len() - chunksz);
-            self.v = fst;
-            Some(snd)
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> ExactSizeIterator for Chunks<'a, T> {}
-
-#[unstable(feature = "fused", issue = "35602")]
-impl<'a, T> FusedIterator for Chunks<'a, T> {}
-
-/// An iterator over a slice in (non-overlapping) mutable chunks (`size`
-/// elements at a time). When the slice len is not evenly divided by the chunk
-/// size, the last slice of the iteration will be the remainder.
-///
-/// This struct is created by the [`chunks_mut`] method on [slices].
-///
-/// [`chunks_mut`]: ../../std/primitive.slice.html#method.chunks_mut
-/// [slices]: ../../std/primitive.slice.html
-#[derive(Debug)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct ChunksMut<'a, T:'a> {
-    v: &'a mut [T],
-    chunk_size: usize
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> Iterator for ChunksMut<'a, T> {
-    type Item = &'a mut [T];
-
-    #[inline]
-    fn next(&mut self) -> Option<&'a mut [T]> {
-        if self.v.is_empty() {
-            None
-        } else {
-            let sz = cmp::min(self.v.len(), self.chunk_size);
-            let tmp = mem::replace(&mut self.v, &mut []);
-            let (head, tail) = tmp.split_at_mut(sz);
-            self.v = tail;
-            Some(head)
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        if self.v.is_empty() {
-            (0, Some(0))
-        } else {
-            let n = self.v.len() / self.chunk_size;
-            let rem = self.v.len() % self.chunk_size;
-            let n = if rem > 0 { n + 1 } else { n };
-            (n, Some(n))
-        }
-    }
-
-    #[inline]
-    fn count(self) -> usize {
-        self.len()
-    }
-
-    #[inline]
-    fn nth(&mut self, n: usize) -> Option<&'a mut [T]> {
-        let (start, overflow) = n.overflowing_mul(self.chunk_size);
-        if start >= self.v.len() || overflow {
-            self.v = &mut [];
-            None
-        } else {
-            let end = match start.checked_add(self.chunk_size) {
-                Some(sum) => cmp::min(self.v.len(), sum),
-                None => self.v.len(),
-            };
-            let tmp = mem::replace(&mut self.v, &mut []);
-            let (head, tail) = tmp.split_at_mut(end);
-            let (_, nth) =  head.split_at_mut(start);
-            self.v = tail;
-            Some(nth)
-        }
-    }
-
-    #[inline]
-    fn last(self) -> Option<Self::Item> {
-        if self.v.is_empty() {
-            None
-        } else {
-            let start = (self.v.len() - 1) / self.chunk_size * self.chunk_size;
-            Some(&mut self.v[start..])
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> {
-    #[inline]
-    fn next_back(&mut self) -> Option<&'a mut [T]> {
-        if self.v.is_empty() {
-            None
-        } else {
-            let remainder = self.v.len() % self.chunk_size;
-            let sz = if remainder != 0 { remainder } else { self.chunk_size };
-            let tmp = mem::replace(&mut self.v, &mut []);
-            let tmp_len = tmp.len();
-            let (head, tail) = tmp.split_at_mut(tmp_len - sz);
-            self.v = head;
-            Some(tail)
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> ExactSizeIterator for ChunksMut<'a, T> {}
-
-#[unstable(feature = "fused", issue = "35602")]
-impl<'a, T> FusedIterator for ChunksMut<'a, T> {}
-
-//
-// Free functions
-//
-
-/// Forms a slice from a pointer and a length.
-///
-/// The `len` argument is the number of **elements**, not the number of bytes.
-///
-/// # Safety
-///
-/// This function is unsafe as there is no guarantee that the given pointer is
-/// valid for `len` elements, nor whether the lifetime inferred is a suitable
-/// lifetime for the returned slice.
-///
-/// `p` must be non-null, even for zero-length slices.
-///
-/// # Caveat
-///
-/// The lifetime for the returned slice is inferred from its usage. To
-/// prevent accidental misuse, it's suggested to tie the lifetime to whichever
-/// source lifetime is safe in the context, such as by providing a helper
-/// function taking the lifetime of a host value for the slice, or by explicit
-/// annotation.
-///
-/// # Examples
-///
-/// ```
-/// use std::slice;
-///
-/// // manifest a slice out of thin air!
-/// let ptr = 0x1234 as *const usize;
-/// let amt = 10;
-/// unsafe {
-///     let slice = slice::from_raw_parts(ptr, amt);
-/// }
-/// ```
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn from_raw_parts<'a, T>(p: *const T, len: usize) -> &'a [T] {
-    mem::transmute(Repr { data: p, len: len })
-}
-
-/// Performs the same functionality as `from_raw_parts`, except that a mutable
-/// slice is returned.
-///
-/// This function is unsafe for the same reasons as `from_raw_parts`, as well
-/// as not being able to provide a non-aliasing guarantee of the returned
-/// mutable slice.
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn from_raw_parts_mut<'a, T>(p: *mut T, len: usize) -> &'a mut [T] {
-    mem::transmute(Repr { data: p, len: len })
-}
-
-//
-// Comparison traits
-//
-
-extern {
-    /// Call implementation provided memcmp
-    ///
-    /// Interprets the data as u8.
-    ///
-    /// Return 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;
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A, B> PartialEq<[B]> for [A] where A: PartialEq<B> {
-    fn eq(&self, other: &[B]) -> bool {
-        SlicePartialEq::equal(self, other)
-    }
-
-    fn ne(&self, other: &[B]) -> bool {
-        SlicePartialEq::not_equal(self, other)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Eq> Eq for [T] {}
-
-/// Implements comparison of vectors lexicographically.
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Ord> Ord for [T] {
-    fn cmp(&self, other: &[T]) -> Ordering {
-        SliceOrd::compare(self, other)
-    }
-}
-
-/// Implements comparison of vectors lexicographically.
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: PartialOrd> PartialOrd for [T] {
-    fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
-        SlicePartialOrd::partial_compare(self, other)
-    }
-}
-
-#[doc(hidden)]
-// intermediate trait for specialization of slice's PartialEq
-trait SlicePartialEq<B> {
-    fn equal(&self, other: &[B]) -> bool;
-
-    fn not_equal(&self, other: &[B]) -> bool { !self.equal(other) }
-}
-
-// Generic slice equality
-impl<A, B> SlicePartialEq<B> for [A]
-    where A: PartialEq<B>
-{
-    default fn equal(&self, other: &[B]) -> bool {
-        if self.len() != other.len() {
-            return false;
-        }
-
-        for i in 0..self.len() {
-            if !self[i].eq(&other[i]) {
-                return false;
-            }
-        }
-
-        true
-    }
-}
-
-// Use memcmp for bytewise equality when the types allow
-impl<A> SlicePartialEq<A> for [A]
-    where A: PartialEq<A> + BytewiseEquality
-{
-    fn equal(&self, other: &[A]) -> bool {
-        if self.len() != other.len() {
-            return false;
-        }
-        if self.as_ptr() == other.as_ptr() {
-            return true;
-        }
-        unsafe {
-            let size = mem::size_of_val(self);
-            memcmp(self.as_ptr() as *const u8,
-                   other.as_ptr() as *const u8, size) == 0
-        }
-    }
-}
-
-#[doc(hidden)]
-// intermediate trait for specialization of slice's PartialOrd
-trait SlicePartialOrd<B> {
-    fn partial_compare(&self, other: &[B]) -> Option<Ordering>;
-}
-
-impl<A> SlicePartialOrd<A> for [A]
-    where A: PartialOrd
-{
-    default fn partial_compare(&self, other: &[A]) -> Option<Ordering> {
-        let l = cmp::min(self.len(), other.len());
-
-        // Slice to the loop iteration range to enable bound check
-        // elimination in the compiler
-        let lhs = &self[..l];
-        let rhs = &other[..l];
-
-        for i in 0..l {
-            match lhs[i].partial_cmp(&rhs[i]) {
-                Some(Ordering::Equal) => (),
-                non_eq => return non_eq,
-            }
-        }
-
-        self.len().partial_cmp(&other.len())
-    }
-}
-
-impl<A> SlicePartialOrd<A> for [A]
-    where A: Ord
-{
-    default fn partial_compare(&self, other: &[A]) -> Option<Ordering> {
-        Some(SliceOrd::compare(self, other))
-    }
-}
-
-#[doc(hidden)]
-// intermediate trait for specialization of slice's Ord
-trait SliceOrd<B> {
-    fn compare(&self, other: &[B]) -> Ordering;
-}
-
-impl<A> SliceOrd<A> for [A]
-    where A: Ord
-{
-    default fn compare(&self, other: &[A]) -> Ordering {
-        let l = cmp::min(self.len(), other.len());
-
-        // Slice to the loop iteration range to enable bound check
-        // elimination in the compiler
-        let lhs = &self[..l];
-        let rhs = &other[..l];
-
-        for i in 0..l {
-            match lhs[i].cmp(&rhs[i]) {
-                Ordering::Equal => (),
-                non_eq => return non_eq,
-            }
-        }
-
-        self.len().cmp(&other.len())
-    }
-}
-
-// memcmp compares a sequence of unsigned bytes lexicographically.
-// this matches the order we want for [u8], but no others (not even [i8]).
-impl SliceOrd<u8> for [u8] {
-    #[inline]
-    fn compare(&self, other: &[u8]) -> Ordering {
-        let order = unsafe {
-            memcmp(self.as_ptr(), other.as_ptr(),
-                   cmp::min(self.len(), other.len()))
-        };
-        if order == 0 {
-            self.len().cmp(&other.len())
-        } else if order < 0 {
-            Less
-        } else {
-            Greater
-        }
-    }
-}
-
-#[doc(hidden)]
-/// Trait implemented for types that can be compared for equality using
-/// their bytewise representation
-trait BytewiseEquality { }
-
-macro_rules! impl_marker_for {
-    ($traitname:ident, $($ty:ty)*) => {
-        $(
-            impl $traitname for $ty { }
-        )*
-    }
-}
-
-impl_marker_for!(BytewiseEquality,
-                 u8 i8 u16 i16 u32 i32 u64 i64 usize isize char bool);
-
-#[doc(hidden)]
-unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> {
-    unsafe fn get_unchecked(&mut self, i: usize) -> &'a T {
-        &*self.ptr.offset(i as isize)
-    }
-    fn may_have_side_effect() -> bool { false }
-}
-
-#[doc(hidden)]
-unsafe impl<'a, T> TrustedRandomAccess for IterMut<'a, T> {
-    unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut T {
-        &mut *self.ptr.offset(i as isize)
-    }
-    fn may_have_side_effect() -> bool { false }
-}
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
new file mode 100644 (file)
index 0000000..6f8b199
--- /dev/null
@@ -0,0 +1,2469 @@
+// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Slice management and manipulation
+//!
+//! For more details see [`std::slice`].
+//!
+//! [`std::slice`]: ../../std/slice/index.html
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+// How this module is organized.
+//
+// The library infrastructure for slices is fairly messy. There's
+// a lot of stuff defined here. Let's keep it clean.
+//
+// Since slices don't support inherent methods; all operations
+// on them are defined on traits, which are then reexported from
+// the prelude for convenience. So there are a lot of traits here.
+//
+// The layout of this file is thus:
+//
+// * Slice-specific 'extension' traits and their implementations. This
+//   is where most of the slice API resides.
+// * Implementations of a few common traits with important slice ops.
+// * Definitions of a bunch of iterators.
+// * Free functions.
+// * The `raw` and `bytes` submodules.
+// * Boilerplate trait implementations.
+
+use borrow::Borrow;
+use cmp::Ordering::{self, Less, Equal, Greater};
+use cmp;
+use fmt;
+use intrinsics::assume;
+use iter::*;
+use ops::{FnMut, self};
+use option::Option;
+use option::Option::{None, Some};
+use result::Result;
+use result::Result::{Ok, Err};
+use ptr;
+use mem;
+use marker::{Copy, Send, Sync, Sized, self};
+use iter_private::TrustedRandomAccess;
+
+mod sort;
+
+#[repr(C)]
+struct Repr<T> {
+    pub data: *const T,
+    pub len: usize,
+}
+
+//
+// Extension traits
+//
+
+/// Extension methods for slices.
+#[unstable(feature = "core_slice_ext",
+           reason = "stable interface provided by `impl [T]` in later crates",
+           issue = "32110")]
+#[allow(missing_docs)] // documented elsewhere
+pub trait SliceExt {
+    type Item;
+
+    #[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;
+
+    #[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;
+
+    #[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;
+
+    #[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>;
+
+    #[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>;
+
+    #[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>;
+
+    #[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;
+
+    #[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;
+
+    #[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;
+
+    #[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>;
+
+    #[stable(feature = "core", since = "1.6.0")]
+    fn as_mut_ptr(&mut self) -> *mut Self::Item;
+
+    #[stable(feature = "core", since = "1.6.0")]
+    fn contains(&self, x: &Self::Item) -> bool where Self::Item: PartialEq;
+
+    #[stable(feature = "core", since = "1.6.0")]
+    fn starts_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq;
+
+    #[stable(feature = "core", since = "1.6.0")]
+    fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq;
+
+    #[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
+macro_rules! slice_offset {
+    ($ptr:expr, $by:expr) => {{
+        let ptr = $ptr;
+        if size_from_ptr(ptr) == 0 {
+            (ptr as *mut i8).wrapping_offset($by) as _
+        } else {
+            ptr.offset($by)
+        }
+    }};
+}
+
+// make a &T from a *const T
+macro_rules! make_ref {
+    ($ptr:expr) => {{
+        let ptr = $ptr;
+        if size_from_ptr(ptr) == 0 {
+            // Use a non-null pointer value
+            &*(1 as *mut _)
+        } else {
+            &*ptr
+        }
+    }};
+}
+
+// make a &mut T from a *mut T
+macro_rules! make_ref_mut {
+    ($ptr:expr) => {{
+        let ptr = $ptr;
+        if size_from_ptr(ptr) == 0 {
+            // Use a non-null pointer value
+            &mut *(1 as *mut _)
+        } else {
+            &mut *ptr
+        }
+    }};
+}
+
+#[unstable(feature = "core_slice_ext",
+           reason = "stable interface provided by `impl [T]` in later crates",
+           issue = "32110")]
+impl<T> SliceExt for [T] {
+    type Item = T;
+
+    #[inline]
+    fn split_at(&self, mid: usize) -> (&[T], &[T]) {
+        (&self[..mid], &self[mid..])
+    }
+
+    #[inline]
+    fn iter(&self) -> Iter<T> {
+        unsafe {
+            let p = if mem::size_of::<T>() == 0 {
+                1 as *const _
+            } else {
+                let p = self.as_ptr();
+                assume(!p.is_null());
+                p
+            };
+
+            Iter {
+                ptr: p,
+                end: slice_offset!(p, self.len() as isize),
+                _marker: marker::PhantomData
+            }
+        }
+    }
+
+    #[inline]
+    fn split<P>(&self, pred: P) -> Split<T, P>
+        where P: FnMut(&T) -> bool
+    {
+        Split {
+            v: self,
+            pred: pred,
+            finished: false
+        }
+    }
+
+    #[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
+            }
+        }
+    }
+
+    #[inline]
+    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
+            }
+        }
+    }
+
+    #[inline]
+    fn windows(&self, size: usize) -> Windows<T> {
+        assert!(size != 0);
+        Windows { v: self, size: size }
+    }
+
+    #[inline]
+    fn chunks(&self, size: usize) -> Chunks<T> {
+        assert!(size != 0);
+        Chunks { v: self, size: size }
+    }
+
+    #[inline]
+    fn get<I>(&self, index: I) -> Option<&I::Output>
+        where I: SliceIndex<T>
+    {
+        index.get(self)
+    }
+
+    #[inline]
+    fn first(&self) -> Option<&T> {
+        if self.is_empty() { None } else { Some(&self[0]) }
+    }
+
+    #[inline]
+    fn split_first(&self) -> Option<(&T, &[T])> {
+        if self.is_empty() { None } else { Some((&self[0], &self[1..])) }
+    }
+
+    #[inline]
+    fn split_last(&self) -> Option<(&T, &[T])> {
+        let len = self.len();
+        if len == 0 { None } else { Some((&self[len - 1], &self[..(len - 1)])) }
+    }
+
+    #[inline]
+    fn last(&self) -> Option<&T> {
+        if self.is_empty() { None } else { Some(&self[self.len() - 1]) }
+    }
+
+    #[inline]
+    unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
+        where I: SliceIndex<T>
+    {
+        index.get_unchecked(self)
+    }
+
+    #[inline]
+    fn as_ptr(&self) -> *const T {
+        self as *const [T] as *const T
+    }
+
+    fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize>
+        where F: FnMut(&'a T) -> Ordering
+    {
+        let mut base = 0usize;
+        let mut s = self;
+
+        loop {
+            let (head, tail) = s.split_at(s.len() >> 1);
+            if tail.is_empty() {
+                return Err(base)
+            }
+            match f(&tail[0]) {
+                Less => {
+                    base += head.len() + 1;
+                    s = &tail[1..];
+                }
+                Greater => s = head,
+                Equal => return Ok(base + head.len()),
+            }
+        }
+    }
+
+    #[inline]
+    fn len(&self) -> usize {
+        unsafe {
+            mem::transmute::<&[T], Repr<T>>(self).len
+        }
+    }
+
+    #[inline]
+    fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
+        where I: SliceIndex<T>
+    {
+        index.get_mut(self)
+    }
+
+    #[inline]
+    fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
+        let len = self.len();
+        let ptr = self.as_mut_ptr();
+
+        unsafe {
+            assert!(mid <= len);
+
+            (from_raw_parts_mut(ptr, mid),
+             from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
+        }
+    }
+
+    #[inline]
+    fn iter_mut(&mut self) -> IterMut<T> {
+        unsafe {
+            let p = if mem::size_of::<T>() == 0 {
+                1 as *mut _
+            } else {
+                let p = self.as_mut_ptr();
+                assume(!p.is_null());
+                p
+            };
+
+            IterMut {
+                ptr: p,
+                end: slice_offset!(p, self.len() as isize),
+                _marker: marker::PhantomData
+            }
+        }
+    }
+
+    #[inline]
+    fn last_mut(&mut self) -> Option<&mut T> {
+        let len = self.len();
+        if len == 0 { return None; }
+        Some(&mut self[len - 1])
+    }
+
+    #[inline]
+    fn first_mut(&mut self) -> Option<&mut T> {
+        if self.is_empty() { None } else { Some(&mut self[0]) }
+    }
+
+    #[inline]
+    fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
+        if self.is_empty() { None } else {
+            let split = self.split_at_mut(1);
+            Some((&mut split.0[0], split.1))
+        }
+    }
+
+    #[inline]
+    fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
+        let len = self.len();
+        if len == 0 { None } else {
+            let split = self.split_at_mut(len - 1);
+            Some((&mut split.1[0], split.0))
+        }
+    }
+
+    #[inline]
+    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
+    {
+        SplitNMut {
+            inner: GenericSplitN {
+                iter: self.split_mut(pred),
+                count: n,
+                invert: false
+            }
+        }
+    }
+
+    #[inline]
+    fn rsplitn_mut<P>(&mut self, n: usize, pred: P) -> RSplitNMut<T, P> where
+        P: FnMut(&T) -> bool,
+    {
+        RSplitNMut {
+            inner: GenericSplitN {
+                iter: self.split_mut(pred),
+                count: n,
+                invert: true
+            }
+        }
+    }
+
+    #[inline]
+    fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<T> {
+        assert!(chunk_size > 0);
+        ChunksMut { v: self, chunk_size: chunk_size }
+    }
+
+    #[inline]
+    fn swap(&mut self, a: usize, b: usize) {
+        unsafe {
+            // Can't take two mutable loans from one vector, so instead just cast
+            // them to their raw pointers to do the swap
+            let pa: *mut T = &mut self[a];
+            let pb: *mut T = &mut self[b];
+            ptr::swap(pa, pb);
+        }
+    }
+
+    fn reverse(&mut self) {
+        let mut i: usize = 0;
+        let ln = self.len();
+        while i < ln / 2 {
+            // Unsafe swap to avoid the bounds check in safe swap.
+            unsafe {
+                let pa: *mut T = self.get_unchecked_mut(i);
+                let pb: *mut T = self.get_unchecked_mut(ln - i - 1);
+                ptr::swap(pa, pb);
+            }
+            i += 1;
+        }
+    }
+
+    #[inline]
+    unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
+        where I: SliceIndex<T>
+    {
+        index.get_unchecked_mut(self)
+    }
+
+    #[inline]
+    fn as_mut_ptr(&mut self) -> *mut T {
+        self as *mut [T] as *mut T
+    }
+
+    #[inline]
+    fn contains(&self, x: &T) -> bool where T: PartialEq {
+        self.iter().any(|elt| *x == *elt)
+    }
+
+    #[inline]
+    fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq {
+        let n = needle.len();
+        self.len() >= n && needle == &self[..n]
+    }
+
+    #[inline]
+    fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq {
+        let (m, n) = (self.len(), needle.len());
+        m >= n && needle == &self[m-n..]
+    }
+
+    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))
+    }
+
+    #[inline]
+    fn clone_from_slice(&mut self, src: &[T]) where T: Clone {
+        assert!(self.len() == src.len(),
+                "destination and source slices have different lengths");
+        // NOTE: We need to explicitly slice them to the same length
+        // for bounds checking to be elided, and the optimizer will
+        // generate memcpy for simple cases (for example T = u8).
+        let len = self.len();
+        let src = &src[..len];
+        for i in 0..len {
+            self[i].clone_from(&src[i]);
+        }
+    }
+
+    #[inline]
+    fn copy_from_slice(&mut self, src: &[T]) where T: Copy {
+        assert!(self.len() == src.len(),
+                "destination and source slices have different lengths");
+        unsafe {
+            ptr::copy_nonoverlapping(
+                src.as_ptr(), self.as_mut_ptr(), self.len());
+        }
+    }
+
+    #[inline]
+    fn binary_search_by_key<'a, B, F, Q: ?Sized>(&'a self, b: &Q, mut f: F) -> Result<usize, usize>
+        where F: FnMut(&'a Self::Item) -> B,
+              B: Borrow<Q>,
+              Q: Ord
+    {
+        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>
+{
+    type Output = I::Output;
+
+    #[inline]
+    fn index(&self, index: I) -> &I::Output {
+        index.index(self)
+    }
+}
+
+#[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>
+{
+    #[inline]
+    fn index_mut(&mut self, index: I) -> &mut I::Output {
+        index.index_mut(self)
+    }
+}
+
+#[inline(never)]
+#[cold]
+fn slice_index_len_fail(index: usize, len: usize) -> ! {
+    panic!("index {} out of range for slice of length {}", index, len);
+}
+
+#[inline(never)]
+#[cold]
+fn slice_index_order_fail(index: usize, end: usize) -> ! {
+    panic!("slice index starts at {} but ends at {}", index, end);
+}
+
+/// 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> {
+    /// 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>;
+
+    /// Returns a mutable reference to the output at this location, if in
+    /// bounds.
+    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;
+
+    /// 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;
+
+    /// Returns a shared reference to the output at this location, panicking
+    /// if out of bounds.
+    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;
+}
+
+#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
+impl<T> SliceIndex<T> for usize {
+    type Output = T;
+
+    #[inline]
+    fn get(self, slice: &[T]) -> Option<&T> {
+        if self < slice.len() {
+            unsafe {
+                Some(self.get_unchecked(slice))
+            }
+        } else {
+            None
+        }
+    }
+
+    #[inline]
+    fn get_mut(self, slice: &mut [T]) -> Option<&mut T> {
+        if self < slice.len() {
+            unsafe {
+                Some(self.get_unchecked_mut(slice))
+            }
+        } else {
+            None
+        }
+    }
+
+    #[inline]
+    unsafe fn get_unchecked(self, slice: &[T]) -> &T {
+        &*slice.as_ptr().offset(self as isize)
+    }
+
+    #[inline]
+    unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut T {
+        &mut *slice.as_mut_ptr().offset(self as isize)
+    }
+
+    #[inline]
+    fn index(self, slice: &[T]) -> &T {
+        // NB: use intrinsic indexing
+        &(*slice)[self]
+    }
+
+    #[inline]
+    fn index_mut(self, slice: &mut [T]) -> &mut T {
+        // NB: use intrinsic indexing
+        &mut (*slice)[self]
+    }
+}
+
+#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
+impl<T> SliceIndex<T> for  ops::Range<usize> {
+    type Output = [T];
+
+    #[inline]
+    fn get(self, slice: &[T]) -> Option<&[T]> {
+        if self.start > self.end || self.end > slice.len() {
+            None
+        } else {
+            unsafe {
+                Some(self.get_unchecked(slice))
+            }
+        }
+    }
+
+    #[inline]
+    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
+        if self.start > self.end || self.end > slice.len() {
+            None
+        } else {
+            unsafe {
+                Some(self.get_unchecked_mut(slice))
+            }
+        }
+    }
+
+    #[inline]
+    unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
+        from_raw_parts(slice.as_ptr().offset(self.start as isize), self.end - self.start)
+    }
+
+    #[inline]
+    unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
+        from_raw_parts_mut(slice.as_mut_ptr().offset(self.start as isize), self.end - self.start)
+    }
+
+    #[inline]
+    fn index(self, slice: &[T]) -> &[T] {
+        if self.start > self.end {
+            slice_index_order_fail(self.start, self.end);
+        } else if self.end > slice.len() {
+            slice_index_len_fail(self.end, slice.len());
+        }
+        unsafe {
+            self.get_unchecked(slice)
+        }
+    }
+
+    #[inline]
+    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
+        if self.start > self.end {
+            slice_index_order_fail(self.start, self.end);
+        } else if self.end > slice.len() {
+            slice_index_len_fail(self.end, slice.len());
+        }
+        unsafe {
+            self.get_unchecked_mut(slice)
+        }
+    }
+}
+
+#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
+impl<T> SliceIndex<T> for ops::RangeTo<usize> {
+    type Output = [T];
+
+    #[inline]
+    fn get(self, slice: &[T]) -> Option<&[T]> {
+        (0..self.end).get(slice)
+    }
+
+    #[inline]
+    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
+        (0..self.end).get_mut(slice)
+    }
+
+    #[inline]
+    unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
+        (0..self.end).get_unchecked(slice)
+    }
+
+    #[inline]
+    unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
+        (0..self.end).get_unchecked_mut(slice)
+    }
+
+    #[inline]
+    fn index(self, slice: &[T]) -> &[T] {
+        (0..self.end).index(slice)
+    }
+
+    #[inline]
+    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
+        (0..self.end).index_mut(slice)
+    }
+}
+
+#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
+impl<T> SliceIndex<T> for ops::RangeFrom<usize> {
+    type Output = [T];
+
+    #[inline]
+    fn get(self, slice: &[T]) -> Option<&[T]> {
+        (self.start..slice.len()).get(slice)
+    }
+
+    #[inline]
+    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
+        (self.start..slice.len()).get_mut(slice)
+    }
+
+    #[inline]
+    unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
+        (self.start..slice.len()).get_unchecked(slice)
+    }
+
+    #[inline]
+    unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
+        (self.start..slice.len()).get_unchecked_mut(slice)
+    }
+
+    #[inline]
+    fn index(self, slice: &[T]) -> &[T] {
+        (self.start..slice.len()).index(slice)
+    }
+
+    #[inline]
+    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
+        (self.start..slice.len()).index_mut(slice)
+    }
+}
+
+#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
+impl<T> SliceIndex<T> for ops::RangeFull {
+    type Output = [T];
+
+    #[inline]
+    fn get(self, slice: &[T]) -> Option<&[T]> {
+        Some(slice)
+    }
+
+    #[inline]
+    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
+        Some(slice)
+    }
+
+    #[inline]
+    unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
+        slice
+    }
+
+    #[inline]
+    unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
+        slice
+    }
+
+    #[inline]
+    fn index(self, slice: &[T]) -> &[T] {
+        slice
+    }
+
+    #[inline]
+    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
+        slice
+    }
+}
+
+
+#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
+impl<T> SliceIndex<T> for ops::RangeInclusive<usize> {
+    type Output = [T];
+
+    #[inline]
+    fn get(self, slice: &[T]) -> Option<&[T]> {
+        match self {
+            ops::RangeInclusive::Empty { .. } => Some(&[]),
+            ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => None,
+            ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).get(slice),
+        }
+    }
+
+    #[inline]
+    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
+        match self {
+            ops::RangeInclusive::Empty { .. } => Some(&mut []),
+            ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => None,
+            ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).get_mut(slice),
+        }
+    }
+
+    #[inline]
+    unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
+        match self {
+            ops::RangeInclusive::Empty { .. } => &[],
+            ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).get_unchecked(slice),
+        }
+    }
+
+    #[inline]
+    unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
+        match self {
+            ops::RangeInclusive::Empty { .. } => &mut [],
+            ops::RangeInclusive::NonEmpty { start, end } => {
+                (start..end + 1).get_unchecked_mut(slice)
+            }
+        }
+    }
+
+    #[inline]
+    fn index(self, slice: &[T]) -> &[T] {
+        match self {
+            ops::RangeInclusive::Empty { .. } => &[],
+            ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => {
+                panic!("attempted to index slice up to maximum usize");
+            },
+            ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).index(slice),
+        }
+    }
+
+    #[inline]
+    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
+        match self {
+            ops::RangeInclusive::Empty { .. } => &mut [],
+            ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => {
+                panic!("attempted to index slice up to maximum usize");
+            },
+            ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).index_mut(slice),
+        }
+    }
+}
+
+#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
+impl<T> SliceIndex<T> for ops::RangeToInclusive<usize> {
+    type Output = [T];
+
+    #[inline]
+    fn get(self, slice: &[T]) -> Option<&[T]> {
+        (0...self.end).get(slice)
+    }
+
+    #[inline]
+    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
+        (0...self.end).get_mut(slice)
+    }
+
+    #[inline]
+    unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
+        (0...self.end).get_unchecked(slice)
+    }
+
+    #[inline]
+    unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
+        (0...self.end).get_unchecked_mut(slice)
+    }
+
+    #[inline]
+    fn index(self, slice: &[T]) -> &[T] {
+        (0...self.end).index(slice)
+    }
+
+    #[inline]
+    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
+        (0...self.end).index_mut(slice)
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Common traits
+////////////////////////////////////////////////////////////////////////////////
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> Default for &'a [T] {
+    /// Creates an empty slice.
+    fn default() -> &'a [T] { &[] }
+}
+
+#[stable(feature = "mut_slice_default", since = "1.5.0")]
+impl<'a, T> Default for &'a mut [T] {
+    /// Creates a mutable empty slice.
+    fn default() -> &'a mut [T] { &mut [] }
+}
+
+//
+// Iterators
+//
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> IntoIterator for &'a [T] {
+    type Item = &'a T;
+    type IntoIter = Iter<'a, T>;
+
+    fn into_iter(self) -> Iter<'a, T> {
+        self.iter()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> IntoIterator for &'a mut [T] {
+    type Item = &'a mut T;
+    type IntoIter = IterMut<'a, T>;
+
+    fn into_iter(self) -> IterMut<'a, T> {
+        self.iter_mut()
+    }
+}
+
+#[inline(always)]
+fn size_from_ptr<T>(_: *const T) -> usize {
+    mem::size_of::<T>()
+}
+
+// The shared definition of the `Iter` and `IterMut` iterators
+macro_rules! iterator {
+    (struct $name:ident -> $ptr:ty, $elem:ty, $mkref:ident) => {
+        #[stable(feature = "rust1", since = "1.0.0")]
+        impl<'a, T> Iterator for $name<'a, T> {
+            type Item = $elem;
+
+            #[inline]
+            fn next(&mut self) -> Option<$elem> {
+                // could be implemented with slices, but this avoids bounds checks
+                unsafe {
+                    if mem::size_of::<T>() != 0 {
+                        assume(!self.ptr.is_null());
+                        assume(!self.end.is_null());
+                    }
+                    if self.ptr == self.end {
+                        None
+                    } else {
+                        Some($mkref!(self.ptr.post_inc()))
+                    }
+                }
+            }
+
+            #[inline]
+            fn size_hint(&self) -> (usize, Option<usize>) {
+                let exact = ptrdistance(self.ptr, self.end);
+                (exact, Some(exact))
+            }
+
+            #[inline]
+            fn count(self) -> usize {
+                self.len()
+            }
+
+            #[inline]
+            fn nth(&mut self, n: usize) -> Option<$elem> {
+                // Call helper method. Can't put the definition here because mut versus const.
+                self.iter_nth(n)
+            }
+
+            #[inline]
+            fn last(mut self) -> Option<$elem> {
+                self.next_back()
+            }
+
+            fn all<F>(&mut self, mut predicate: F) -> bool
+                where F: FnMut(Self::Item) -> bool,
+            {
+                self.search_while(true, move |elt| {
+                    if predicate(elt) {
+                        SearchWhile::Continue
+                    } else {
+                        SearchWhile::Done(false)
+                    }
+                })
+            }
+
+            fn any<F>(&mut self, mut predicate: F) -> bool
+                where F: FnMut(Self::Item) -> bool,
+            {
+                !self.all(move |elt| !predicate(elt))
+            }
+
+            fn find<F>(&mut self, mut predicate: F) -> Option<Self::Item>
+                where F: FnMut(&Self::Item) -> bool,
+            {
+                self.search_while(None, move |elt| {
+                    if predicate(&elt) {
+                        SearchWhile::Done(Some(elt))
+                    } else {
+                        SearchWhile::Continue
+                    }
+                })
+            }
+
+            fn position<F>(&mut self, mut predicate: F) -> Option<usize>
+                where F: FnMut(Self::Item) -> bool,
+            {
+                let mut index = 0;
+                self.search_while(None, move |elt| {
+                    if predicate(elt) {
+                        SearchWhile::Done(Some(index))
+                    } else {
+                        index += 1;
+                        SearchWhile::Continue
+                    }
+                })
+            }
+
+            fn rposition<F>(&mut self, mut predicate: F) -> Option<usize>
+                where F: FnMut(Self::Item) -> bool,
+            {
+                let mut index = self.len();
+                self.rsearch_while(None, move |elt| {
+                    index -= 1;
+                    if predicate(elt) {
+                        SearchWhile::Done(Some(index))
+                    } else {
+                        SearchWhile::Continue
+                    }
+                })
+            }
+        }
+
+        #[stable(feature = "rust1", since = "1.0.0")]
+        impl<'a, T> DoubleEndedIterator for $name<'a, T> {
+            #[inline]
+            fn next_back(&mut self) -> Option<$elem> {
+                // could be implemented with slices, but this avoids bounds checks
+                unsafe {
+                    if mem::size_of::<T>() != 0 {
+                        assume(!self.ptr.is_null());
+                        assume(!self.end.is_null());
+                    }
+                    if self.end == self.ptr {
+                        None
+                    } else {
+                        Some($mkref!(self.end.pre_dec()))
+                    }
+                }
+            }
+        }
+
+        // search_while is a generalization of the internal iteration methods.
+        impl<'a, T> $name<'a, T> {
+            // search through the iterator's element using the closure `g`.
+            // if no element was found, return `default`.
+            fn search_while<Acc, G>(&mut self, default: Acc, mut g: G) -> Acc
+                where Self: Sized,
+                      G: FnMut($elem) -> SearchWhile<Acc>
+            {
+                // manual unrolling is needed when there are conditional exits from the loop
+                unsafe {
+                    while ptrdistance(self.ptr, self.end) >= 4 {
+                        search_while!(g($mkref!(self.ptr.post_inc())));
+                        search_while!(g($mkref!(self.ptr.post_inc())));
+                        search_while!(g($mkref!(self.ptr.post_inc())));
+                        search_while!(g($mkref!(self.ptr.post_inc())));
+                    }
+                    while self.ptr != self.end {
+                        search_while!(g($mkref!(self.ptr.post_inc())));
+                    }
+                }
+                default
+            }
+
+            fn rsearch_while<Acc, G>(&mut self, default: Acc, mut g: G) -> Acc
+                where Self: Sized,
+                      G: FnMut($elem) -> SearchWhile<Acc>
+            {
+                unsafe {
+                    while ptrdistance(self.ptr, self.end) >= 4 {
+                        search_while!(g($mkref!(self.end.pre_dec())));
+                        search_while!(g($mkref!(self.end.pre_dec())));
+                        search_while!(g($mkref!(self.end.pre_dec())));
+                        search_while!(g($mkref!(self.end.pre_dec())));
+                    }
+                    while self.ptr != self.end {
+                        search_while!(g($mkref!(self.end.pre_dec())));
+                    }
+                }
+                default
+            }
+        }
+    }
+}
+
+macro_rules! make_slice {
+    ($start: expr, $end: expr) => {{
+        let start = $start;
+        let diff = ($end as usize).wrapping_sub(start as usize);
+        if size_from_ptr(start) == 0 {
+            // use a non-null pointer value
+            unsafe { from_raw_parts(1 as *const _, diff) }
+        } else {
+            let len = diff / size_from_ptr(start);
+            unsafe { from_raw_parts(start, len) }
+        }
+    }}
+}
+
+macro_rules! make_mut_slice {
+    ($start: expr, $end: expr) => {{
+        let start = $start;
+        let diff = ($end as usize).wrapping_sub(start as usize);
+        if size_from_ptr(start) == 0 {
+            // use a non-null pointer value
+            unsafe { from_raw_parts_mut(1 as *mut _, diff) }
+        } else {
+            let len = diff / size_from_ptr(start);
+            unsafe { from_raw_parts_mut(start, len) }
+        }
+    }}
+}
+
+// An enum used for controlling the execution of `.search_while()`.
+enum SearchWhile<T> {
+    // Continue searching
+    Continue,
+    // Fold is complete and will return this value
+    Done(T),
+}
+
+// helper macro for search while's control flow
+macro_rules! search_while {
+    ($e:expr) => {
+        match $e {
+            SearchWhile::Continue => { }
+            SearchWhile::Done(done) => return done,
+        }
+    }
+}
+
+/// Immutable slice iterator
+///
+/// This struct is created by the [`iter`] method on [slices].
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// // First, we declare a type which has `iter` method to get the `Iter` struct (&[usize here]):
+/// let slice = &[1, 2, 3];
+///
+/// // Then, we iterate over it:
+/// for element in slice.iter() {
+///     println!("{}", element);
+/// }
+/// ```
+///
+/// [`iter`]: ../../std/primitive.slice.html#method.iter
+/// [slices]: ../../std/primitive.slice.html
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Iter<'a, T: 'a> {
+    ptr: *const T,
+    end: *const T,
+    _marker: marker::PhantomData<&'a T>,
+}
+
+#[stable(feature = "core_impl_debug", since = "1.9.0")]
+impl<'a, T: 'a + fmt::Debug> fmt::Debug for Iter<'a, T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_tuple("Iter")
+            .field(&self.as_slice())
+            .finish()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+unsafe impl<'a, T: Sync> Sync for Iter<'a, T> {}
+#[stable(feature = "rust1", since = "1.0.0")]
+unsafe impl<'a, T: Sync> Send for Iter<'a, T> {}
+
+impl<'a, T> Iter<'a, T> {
+    /// View the underlying data as a subslice of the original data.
+    ///
+    /// This has the same lifetime as the original slice, and so the
+    /// iterator can continue to be used while this exists.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// // First, we declare a type which has the `iter` method to get the `Iter`
+    /// // struct (&[usize here]):
+    /// let slice = &[1, 2, 3];
+    ///
+    /// // Then, we get the iterator:
+    /// let mut iter = slice.iter();
+    /// // So if we print what `as_slice` method returns here, we have "[1, 2, 3]":
+    /// println!("{:?}", iter.as_slice());
+    ///
+    /// // Next, we move to the second element of the slice:
+    /// iter.next();
+    /// // Now `as_slice` returns "[2, 3]":
+    /// println!("{:?}", iter.as_slice());
+    /// ```
+    #[stable(feature = "iter_to_slice", since = "1.4.0")]
+    pub fn as_slice(&self) -> &'a [T] {
+        make_slice!(self.ptr, self.end)
+    }
+
+    // Helper function for Iter::nth
+    fn iter_nth(&mut self, n: usize) -> Option<&'a T> {
+        match self.as_slice().get(n) {
+            Some(elem_ref) => unsafe {
+                self.ptr = slice_offset!(self.ptr, (n as isize).wrapping_add(1));
+                Some(elem_ref)
+            },
+            None => {
+                self.ptr = self.end;
+                None
+            }
+        }
+    }
+}
+
+iterator!{struct Iter -> *const T, &'a T, make_ref}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> ExactSizeIterator for Iter<'a, T> {
+    fn is_empty(&self) -> bool {
+        self.ptr == self.end
+    }
+}
+
+#[unstable(feature = "fused", issue = "35602")]
+impl<'a, T> FusedIterator for Iter<'a, T> {}
+
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<'a, T> TrustedLen for Iter<'a, T> {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> Clone for Iter<'a, T> {
+    fn clone(&self) -> Iter<'a, T> { Iter { ptr: self.ptr, end: self.end, _marker: self._marker } }
+}
+
+#[stable(feature = "slice_iter_as_ref", since = "1.12.0")]
+impl<'a, T> AsRef<[T]> for Iter<'a, T> {
+    fn as_ref(&self) -> &[T] {
+        self.as_slice()
+    }
+}
+
+/// Mutable slice iterator.
+///
+/// This struct is created by the [`iter_mut`] method on [slices].
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// // First, we declare a type which has `iter_mut` method to get the `IterMut`
+/// // struct (&[usize here]):
+/// let mut slice = &mut [1, 2, 3];
+///
+/// // Then, we iterate over it and increment each element value:
+/// for element in slice.iter_mut() {
+///     *element += 1;
+/// }
+///
+/// // We now have "[2, 3, 4]":
+/// println!("{:?}", slice);
+/// ```
+///
+/// [`iter_mut`]: ../../std/primitive.slice.html#method.iter_mut
+/// [slices]: ../../std/primitive.slice.html
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct IterMut<'a, T: 'a> {
+    ptr: *mut T,
+    end: *mut T,
+    _marker: marker::PhantomData<&'a mut T>,
+}
+
+#[stable(feature = "core_impl_debug", since = "1.9.0")]
+impl<'a, T: 'a + fmt::Debug> fmt::Debug for IterMut<'a, T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_tuple("IterMut")
+            .field(&make_slice!(self.ptr, self.end))
+            .finish()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+unsafe impl<'a, T: Sync> Sync for IterMut<'a, T> {}
+#[stable(feature = "rust1", since = "1.0.0")]
+unsafe impl<'a, T: Send> Send for IterMut<'a, T> {}
+
+impl<'a, T> IterMut<'a, T> {
+    /// View the underlying data as a subslice of the original data.
+    ///
+    /// To avoid creating `&mut` references that alias, this is forced
+    /// to consume the iterator. Consider using the `Slice` and
+    /// `SliceMut` implementations for obtaining slices with more
+    /// restricted lifetimes that do not consume the iterator.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// // First, we declare a type which has `iter_mut` method to get the `IterMut`
+    /// // struct (&[usize here]):
+    /// let mut slice = &mut [1, 2, 3];
+    ///
+    /// {
+    ///     // Then, we get the iterator:
+    ///     let mut iter = slice.iter_mut();
+    ///     // We move to next element:
+    ///     iter.next();
+    ///     // So if we print what `into_slice` method returns here, we have "[2, 3]":
+    ///     println!("{:?}", iter.into_slice());
+    /// }
+    ///
+    /// // Now let's modify a value of the slice:
+    /// {
+    ///     // First we get back the iterator:
+    ///     let mut iter = slice.iter_mut();
+    ///     // We change the value of the first element of the slice returned by the `next` method:
+    ///     *iter.next().unwrap() += 1;
+    /// }
+    /// // Now slice is "[2, 2, 3]":
+    /// println!("{:?}", slice);
+    /// ```
+    #[stable(feature = "iter_to_slice", since = "1.4.0")]
+    pub fn into_slice(self) -> &'a mut [T] {
+        make_mut_slice!(self.ptr, self.end)
+    }
+
+    // Helper function for IterMut::nth
+    fn iter_nth(&mut self, n: usize) -> Option<&'a mut T> {
+        match make_mut_slice!(self.ptr, self.end).get_mut(n) {
+            Some(elem_ref) => unsafe {
+                self.ptr = slice_offset!(self.ptr, (n as isize).wrapping_add(1));
+                Some(elem_ref)
+            },
+            None => {
+                self.ptr = self.end;
+                None
+            }
+        }
+    }
+}
+
+iterator!{struct IterMut -> *mut T, &'a mut T, make_ref_mut}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
+    fn is_empty(&self) -> bool {
+        self.ptr == self.end
+    }
+}
+
+#[unstable(feature = "fused", issue = "35602")]
+impl<'a, T> FusedIterator for IterMut<'a, T> {}
+
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<'a, T> TrustedLen for IterMut<'a, T> {}
+
+
+// Return the number of elements of `T` from `start` to `end`.
+// 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 })
+}
+
+// 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
+    #[inline(always)]
+    unsafe fn post_inc(&mut self) -> Self {
+        let current = *self;
+        *self = self.slice_offset(1);
+        current
+    }
+
+    /// Decrement self by 1, and return the new value
+    #[inline(always)]
+    unsafe fn pre_dec(&mut self) -> Self {
+        *self = self.slice_offset(-1);
+        *self
+    }
+}
+
+impl<T> PointerExt for *const T {
+    #[inline(always)]
+    unsafe fn slice_offset(self, i: isize) -> Self {
+        slice_offset!(self, i)
+    }
+}
+
+impl<T> PointerExt for *mut T {
+    #[inline(always)]
+    unsafe fn slice_offset(self, i: isize) -> Self {
+        slice_offset!(self, i)
+    }
+}
+
+/// An internal abstraction over the splitting iterators, so that
+/// splitn, splitn_mut etc can be implemented once.
+#[doc(hidden)]
+trait SplitIter: DoubleEndedIterator {
+    /// Mark the underlying iterator as complete, extracting the remaining
+    /// portion of the slice.
+    fn finish(&mut self) -> Option<Self::Item>;
+}
+
+/// An iterator over subslices separated by elements that match a predicate
+/// function.
+///
+/// This struct is created by the [`split`] method on [slices].
+///
+/// [`split`]: ../../std/primitive.slice.html#method.split
+/// [slices]: ../../std/primitive.slice.html
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Split<'a, T:'a, P> where P: FnMut(&T) -> bool {
+    v: &'a [T],
+    pred: P,
+    finished: bool
+}
+
+#[stable(feature = "core_impl_debug", since = "1.9.0")]
+impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for Split<'a, T, P> where P: FnMut(&T) -> bool {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("Split")
+            .field("v", &self.v)
+            .field("finished", &self.finished)
+            .finish()
+    }
+}
+
+// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T, P> Clone for Split<'a, T, P> where P: Clone + FnMut(&T) -> bool {
+    fn clone(&self) -> Split<'a, T, P> {
+        Split {
+            v: self.v,
+            pred: self.pred.clone(),
+            finished: self.finished,
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T, P> Iterator for Split<'a, T, P> where P: FnMut(&T) -> bool {
+    type Item = &'a [T];
+
+    #[inline]
+    fn next(&mut self) -> Option<&'a [T]> {
+        if self.finished { return None; }
+
+        match self.v.iter().position(|x| (self.pred)(x)) {
+            None => self.finish(),
+            Some(idx) => {
+                let ret = Some(&self.v[..idx]);
+                self.v = &self.v[idx + 1..];
+                ret
+            }
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        if self.finished {
+            (0, Some(0))
+        } else {
+            (1, Some(self.v.len() + 1))
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T, P> DoubleEndedIterator for Split<'a, T, P> where P: FnMut(&T) -> bool {
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a [T]> {
+        if self.finished { return None; }
+
+        match self.v.iter().rposition(|x| (self.pred)(x)) {
+            None => self.finish(),
+            Some(idx) => {
+                let ret = Some(&self.v[idx + 1..]);
+                self.v = &self.v[..idx];
+                ret
+            }
+        }
+    }
+}
+
+impl<'a, T, P> SplitIter for Split<'a, T, P> where P: FnMut(&T) -> bool {
+    #[inline]
+    fn finish(&mut self) -> Option<&'a [T]> {
+        if self.finished { None } else { self.finished = true; Some(self.v) }
+    }
+}
+
+#[unstable(feature = "fused", issue = "35602")]
+impl<'a, T, P> FusedIterator for Split<'a, T, P> where P: FnMut(&T) -> bool {}
+
+/// An iterator over the subslices of the vector which are separated
+/// by elements that match `pred`.
+///
+/// This struct is created by the [`split_mut`] method on [slices].
+///
+/// [`split_mut`]: ../../std/primitive.slice.html#method.split_mut
+/// [slices]: ../../std/primitive.slice.html
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct SplitMut<'a, T:'a, P> where P: FnMut(&T) -> bool {
+    v: &'a mut [T],
+    pred: P,
+    finished: bool
+}
+
+#[stable(feature = "core_impl_debug", since = "1.9.0")]
+impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("SplitMut")
+            .field("v", &self.v)
+            .field("finished", &self.finished)
+            .finish()
+    }
+}
+
+impl<'a, T, P> SplitIter for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {
+    #[inline]
+    fn finish(&mut self) -> Option<&'a mut [T]> {
+        if self.finished {
+            None
+        } else {
+            self.finished = true;
+            Some(mem::replace(&mut self.v, &mut []))
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T, P> Iterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {
+    type Item = &'a mut [T];
+
+    #[inline]
+    fn next(&mut self) -> Option<&'a mut [T]> {
+        if self.finished { return None; }
+
+        let idx_opt = { // work around borrowck limitations
+            let pred = &mut self.pred;
+            self.v.iter().position(|x| (*pred)(x))
+        };
+        match idx_opt {
+            None => self.finish(),
+            Some(idx) => {
+                let tmp = mem::replace(&mut self.v, &mut []);
+                let (head, tail) = tmp.split_at_mut(idx);
+                self.v = &mut tail[1..];
+                Some(head)
+            }
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        if self.finished {
+            (0, Some(0))
+        } else {
+            // if the predicate doesn't match anything, we yield one slice
+            // if it matches every element, we yield len+1 empty slices.
+            (1, Some(self.v.len() + 1))
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T, P> DoubleEndedIterator for SplitMut<'a, T, P> where
+    P: FnMut(&T) -> bool,
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a mut [T]> {
+        if self.finished { return None; }
+
+        let idx_opt = { // work around borrowck limitations
+            let pred = &mut self.pred;
+            self.v.iter().rposition(|x| (*pred)(x))
+        };
+        match idx_opt {
+            None => self.finish(),
+            Some(idx) => {
+                let tmp = mem::replace(&mut self.v, &mut []);
+                let (head, tail) = tmp.split_at_mut(idx);
+                self.v = head;
+                Some(&mut tail[1..])
+            }
+        }
+    }
+}
+
+#[unstable(feature = "fused", issue = "35602")]
+impl<'a, T, P> FusedIterator for SplitMut<'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.
+#[derive(Debug)]
+struct GenericSplitN<I> {
+    iter: I,
+    count: usize,
+    invert: bool
+}
+
+impl<T, I: SplitIter<Item=T>> Iterator for GenericSplitN<I> {
+    type Item = T;
+
+    #[inline]
+    fn next(&mut self) -> Option<T> {
+        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()}
+            }
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let (lower, upper_opt) = self.iter.size_hint();
+        (lower, upper_opt.map(|upper| cmp::min(self.count, upper)))
+    }
+}
+
+/// An iterator over subslices separated by elements that match a predicate
+/// function, limited to a given number of splits.
+///
+/// This struct is created by the [`splitn`] method on [slices].
+///
+/// [`splitn`]: ../../std/primitive.slice.html#method.splitn
+/// [slices]: ../../std/primitive.slice.html
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct SplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool {
+    inner: GenericSplitN<Split<'a, T, P>>
+}
+
+#[stable(feature = "core_impl_debug", since = "1.9.0")]
+impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for SplitN<'a, T, P> where P: FnMut(&T) -> bool {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("SplitN")
+            .field("inner", &self.inner)
+            .finish()
+    }
+}
+
+/// An iterator over subslices separated by elements that match a
+/// predicate function, limited to a given number of splits, starting
+/// from the end of the slice.
+///
+/// This struct is created by the [`rsplitn`] method on [slices].
+///
+/// [`rsplitn`]: ../../std/primitive.slice.html#method.rsplitn
+/// [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>>
+}
+
+#[stable(feature = "core_impl_debug", since = "1.9.0")]
+impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for RSplitN<'a, T, P> where P: FnMut(&T) -> bool {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("RSplitN")
+            .field("inner", &self.inner)
+            .finish()
+    }
+}
+
+/// An iterator over subslices separated by elements that match a predicate
+/// function, limited to a given number of splits.
+///
+/// This struct is created by the [`splitn_mut`] method on [slices].
+///
+/// [`splitn_mut`]: ../../std/primitive.slice.html#method.splitn_mut
+/// [slices]: ../../std/primitive.slice.html
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct SplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool {
+    inner: GenericSplitN<SplitMut<'a, T, P>>
+}
+
+#[stable(feature = "core_impl_debug", since = "1.9.0")]
+impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for SplitNMut<'a, T, P> where P: FnMut(&T) -> bool {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("SplitNMut")
+            .field("inner", &self.inner)
+            .finish()
+    }
+}
+
+/// An iterator over subslices separated by elements that match a
+/// predicate function, limited to a given number of splits, starting
+/// from the end of the slice.
+///
+/// This struct is created by the [`rsplitn_mut`] method on [slices].
+///
+/// [`rsplitn_mut`]: ../../std/primitive.slice.html#method.rsplitn_mut
+/// [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>>
+}
+
+#[stable(feature = "core_impl_debug", since = "1.9.0")]
+impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for RSplitNMut<'a, T, P> where P: FnMut(&T) -> bool {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("RSplitNMut")
+            .field("inner", &self.inner)
+            .finish()
+    }
+}
+
+macro_rules! forward_iterator {
+    ($name:ident: $elem:ident, $iter_of:ty) => {
+        #[stable(feature = "rust1", since = "1.0.0")]
+        impl<'a, $elem, P> Iterator for $name<'a, $elem, P> where
+            P: FnMut(&T) -> bool
+        {
+            type Item = $iter_of;
+
+            #[inline]
+            fn next(&mut self) -> Option<$iter_of> {
+                self.inner.next()
+            }
+
+            #[inline]
+            fn size_hint(&self) -> (usize, Option<usize>) {
+                self.inner.size_hint()
+            }
+        }
+
+        #[unstable(feature = "fused", issue = "35602")]
+        impl<'a, $elem, P> FusedIterator for $name<'a, $elem, P>
+            where P: FnMut(&T) -> bool {}
+    }
+}
+
+forward_iterator! { SplitN: T, &'a [T] }
+forward_iterator! { RSplitN: T, &'a [T] }
+forward_iterator! { SplitNMut: T, &'a mut [T] }
+forward_iterator! { RSplitNMut: T, &'a mut [T] }
+
+/// An iterator over overlapping subslices of length `size`.
+///
+/// This struct is created by the [`windows`] method on [slices].
+///
+/// [`windows`]: ../../std/primitive.slice.html#method.windows
+/// [slices]: ../../std/primitive.slice.html
+#[derive(Debug)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Windows<'a, T:'a> {
+    v: &'a [T],
+    size: usize
+}
+
+// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> Clone for Windows<'a, T> {
+    fn clone(&self) -> Windows<'a, T> {
+        Windows {
+            v: self.v,
+            size: self.size,
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> Iterator for Windows<'a, T> {
+    type Item = &'a [T];
+
+    #[inline]
+    fn next(&mut self) -> Option<&'a [T]> {
+        if self.size > self.v.len() {
+            None
+        } else {
+            let ret = Some(&self.v[..self.size]);
+            self.v = &self.v[1..];
+            ret
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        if self.size > self.v.len() {
+            (0, Some(0))
+        } else {
+            let size = self.v.len() - self.size + 1;
+            (size, Some(size))
+        }
+    }
+
+    #[inline]
+    fn count(self) -> usize {
+        self.len()
+    }
+
+    #[inline]
+    fn nth(&mut self, n: usize) -> Option<Self::Item> {
+        let (end, overflow) = self.size.overflowing_add(n);
+        if end > self.v.len() || overflow {
+            self.v = &[];
+            None
+        } else {
+            let nth = &self.v[n..end];
+            self.v = &self.v[n+1..];
+            Some(nth)
+        }
+    }
+
+    #[inline]
+    fn last(self) -> Option<Self::Item> {
+        if self.size > self.v.len() {
+            None
+        } else {
+            let start = self.v.len() - self.size;
+            Some(&self.v[start..])
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> DoubleEndedIterator for Windows<'a, T> {
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a [T]> {
+        if self.size > self.v.len() {
+            None
+        } else {
+            let ret = Some(&self.v[self.v.len()-self.size..]);
+            self.v = &self.v[..self.v.len()-1];
+            ret
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> ExactSizeIterator for Windows<'a, T> {}
+
+#[unstable(feature = "fused", issue = "35602")]
+impl<'a, T> FusedIterator for Windows<'a, T> {}
+
+/// An iterator over a slice in (non-overlapping) chunks (`size` elements at a
+/// time).
+///
+/// When the slice len is not evenly divided by the chunk size, the last slice
+/// of the iteration will be the remainder.
+///
+/// This struct is created by the [`chunks`] method on [slices].
+///
+/// [`chunks`]: ../../std/primitive.slice.html#method.chunks
+/// [slices]: ../../std/primitive.slice.html
+#[derive(Debug)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Chunks<'a, T:'a> {
+    v: &'a [T],
+    size: usize
+}
+
+// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> Clone for Chunks<'a, T> {
+    fn clone(&self) -> Chunks<'a, T> {
+        Chunks {
+            v: self.v,
+            size: self.size,
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> Iterator for Chunks<'a, T> {
+    type Item = &'a [T];
+
+    #[inline]
+    fn next(&mut self) -> Option<&'a [T]> {
+        if self.v.is_empty() {
+            None
+        } else {
+            let chunksz = cmp::min(self.v.len(), self.size);
+            let (fst, snd) = self.v.split_at(chunksz);
+            self.v = snd;
+            Some(fst)
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        if self.v.is_empty() {
+            (0, Some(0))
+        } else {
+            let n = self.v.len() / self.size;
+            let rem = self.v.len() % self.size;
+            let n = if rem > 0 { n+1 } else { n };
+            (n, Some(n))
+        }
+    }
+
+    #[inline]
+    fn count(self) -> usize {
+        self.len()
+    }
+
+    #[inline]
+    fn nth(&mut self, n: usize) -> Option<Self::Item> {
+        let (start, overflow) = n.overflowing_mul(self.size);
+        if start >= self.v.len() || overflow {
+            self.v = &[];
+            None
+        } else {
+            let end = match start.checked_add(self.size) {
+                Some(sum) => cmp::min(self.v.len(), sum),
+                None => self.v.len(),
+            };
+            let nth = &self.v[start..end];
+            self.v = &self.v[end..];
+            Some(nth)
+        }
+    }
+
+    #[inline]
+    fn last(self) -> Option<Self::Item> {
+        if self.v.is_empty() {
+            None
+        } else {
+            let start = (self.v.len() - 1) / self.size * self.size;
+            Some(&self.v[start..])
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> DoubleEndedIterator for Chunks<'a, T> {
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a [T]> {
+        if self.v.is_empty() {
+            None
+        } else {
+            let remainder = self.v.len() % self.size;
+            let chunksz = if remainder != 0 { remainder } else { self.size };
+            let (fst, snd) = self.v.split_at(self.v.len() - chunksz);
+            self.v = fst;
+            Some(snd)
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> ExactSizeIterator for Chunks<'a, T> {}
+
+#[unstable(feature = "fused", issue = "35602")]
+impl<'a, T> FusedIterator for Chunks<'a, T> {}
+
+/// An iterator over a slice in (non-overlapping) mutable chunks (`size`
+/// elements at a time). When the slice len is not evenly divided by the chunk
+/// size, the last slice of the iteration will be the remainder.
+///
+/// This struct is created by the [`chunks_mut`] method on [slices].
+///
+/// [`chunks_mut`]: ../../std/primitive.slice.html#method.chunks_mut
+/// [slices]: ../../std/primitive.slice.html
+#[derive(Debug)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct ChunksMut<'a, T:'a> {
+    v: &'a mut [T],
+    chunk_size: usize
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> Iterator for ChunksMut<'a, T> {
+    type Item = &'a mut [T];
+
+    #[inline]
+    fn next(&mut self) -> Option<&'a mut [T]> {
+        if self.v.is_empty() {
+            None
+        } else {
+            let sz = cmp::min(self.v.len(), self.chunk_size);
+            let tmp = mem::replace(&mut self.v, &mut []);
+            let (head, tail) = tmp.split_at_mut(sz);
+            self.v = tail;
+            Some(head)
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        if self.v.is_empty() {
+            (0, Some(0))
+        } else {
+            let n = self.v.len() / self.chunk_size;
+            let rem = self.v.len() % self.chunk_size;
+            let n = if rem > 0 { n + 1 } else { n };
+            (n, Some(n))
+        }
+    }
+
+    #[inline]
+    fn count(self) -> usize {
+        self.len()
+    }
+
+    #[inline]
+    fn nth(&mut self, n: usize) -> Option<&'a mut [T]> {
+        let (start, overflow) = n.overflowing_mul(self.chunk_size);
+        if start >= self.v.len() || overflow {
+            self.v = &mut [];
+            None
+        } else {
+            let end = match start.checked_add(self.chunk_size) {
+                Some(sum) => cmp::min(self.v.len(), sum),
+                None => self.v.len(),
+            };
+            let tmp = mem::replace(&mut self.v, &mut []);
+            let (head, tail) = tmp.split_at_mut(end);
+            let (_, nth) =  head.split_at_mut(start);
+            self.v = tail;
+            Some(nth)
+        }
+    }
+
+    #[inline]
+    fn last(self) -> Option<Self::Item> {
+        if self.v.is_empty() {
+            None
+        } else {
+            let start = (self.v.len() - 1) / self.chunk_size * self.chunk_size;
+            Some(&mut self.v[start..])
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> {
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a mut [T]> {
+        if self.v.is_empty() {
+            None
+        } else {
+            let remainder = self.v.len() % self.chunk_size;
+            let sz = if remainder != 0 { remainder } else { self.chunk_size };
+            let tmp = mem::replace(&mut self.v, &mut []);
+            let tmp_len = tmp.len();
+            let (head, tail) = tmp.split_at_mut(tmp_len - sz);
+            self.v = head;
+            Some(tail)
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> ExactSizeIterator for ChunksMut<'a, T> {}
+
+#[unstable(feature = "fused", issue = "35602")]
+impl<'a, T> FusedIterator for ChunksMut<'a, T> {}
+
+//
+// Free functions
+//
+
+/// Forms a slice from a pointer and a length.
+///
+/// The `len` argument is the number of **elements**, not the number of bytes.
+///
+/// # Safety
+///
+/// This function is unsafe as there is no guarantee that the given pointer is
+/// valid for `len` elements, nor whether the lifetime inferred is a suitable
+/// lifetime for the returned slice.
+///
+/// `p` must be non-null, even for zero-length slices.
+///
+/// # Caveat
+///
+/// The lifetime for the returned slice is inferred from its usage. To
+/// prevent accidental misuse, it's suggested to tie the lifetime to whichever
+/// source lifetime is safe in the context, such as by providing a helper
+/// function taking the lifetime of a host value for the slice, or by explicit
+/// annotation.
+///
+/// # Examples
+///
+/// ```
+/// use std::slice;
+///
+/// // manifest a slice out of thin air!
+/// let ptr = 0x1234 as *const usize;
+/// let amt = 10;
+/// unsafe {
+///     let slice = slice::from_raw_parts(ptr, amt);
+/// }
+/// ```
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub unsafe fn from_raw_parts<'a, T>(p: *const T, len: usize) -> &'a [T] {
+    mem::transmute(Repr { data: p, len: len })
+}
+
+/// Performs the same functionality as `from_raw_parts`, except that a mutable
+/// slice is returned.
+///
+/// This function is unsafe for the same reasons as `from_raw_parts`, as well
+/// as not being able to provide a non-aliasing guarantee of the returned
+/// mutable slice.
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+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
+    ///
+    /// Interprets the data as u8.
+    ///
+    /// Return 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;
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A, B> PartialEq<[B]> for [A] where A: PartialEq<B> {
+    fn eq(&self, other: &[B]) -> bool {
+        SlicePartialEq::equal(self, other)
+    }
+
+    fn ne(&self, other: &[B]) -> bool {
+        SlicePartialEq::not_equal(self, other)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: Eq> Eq for [T] {}
+
+/// Implements comparison of vectors lexicographically.
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: Ord> Ord for [T] {
+    fn cmp(&self, other: &[T]) -> Ordering {
+        SliceOrd::compare(self, other)
+    }
+}
+
+/// Implements comparison of vectors lexicographically.
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: PartialOrd> PartialOrd for [T] {
+    fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
+        SlicePartialOrd::partial_compare(self, other)
+    }
+}
+
+#[doc(hidden)]
+// intermediate trait for specialization of slice's PartialEq
+trait SlicePartialEq<B> {
+    fn equal(&self, other: &[B]) -> bool;
+
+    fn not_equal(&self, other: &[B]) -> bool { !self.equal(other) }
+}
+
+// Generic slice equality
+impl<A, B> SlicePartialEq<B> for [A]
+    where A: PartialEq<B>
+{
+    default fn equal(&self, other: &[B]) -> bool {
+        if self.len() != other.len() {
+            return false;
+        }
+
+        for i in 0..self.len() {
+            if !self[i].eq(&other[i]) {
+                return false;
+            }
+        }
+
+        true
+    }
+}
+
+// Use memcmp for bytewise equality when the types allow
+impl<A> SlicePartialEq<A> for [A]
+    where A: PartialEq<A> + BytewiseEquality
+{
+    fn equal(&self, other: &[A]) -> bool {
+        if self.len() != other.len() {
+            return false;
+        }
+        if self.as_ptr() == other.as_ptr() {
+            return true;
+        }
+        unsafe {
+            let size = mem::size_of_val(self);
+            memcmp(self.as_ptr() as *const u8,
+                   other.as_ptr() as *const u8, size) == 0
+        }
+    }
+}
+
+#[doc(hidden)]
+// intermediate trait for specialization of slice's PartialOrd
+trait SlicePartialOrd<B> {
+    fn partial_compare(&self, other: &[B]) -> Option<Ordering>;
+}
+
+impl<A> SlicePartialOrd<A> for [A]
+    where A: PartialOrd
+{
+    default fn partial_compare(&self, other: &[A]) -> Option<Ordering> {
+        let l = cmp::min(self.len(), other.len());
+
+        // Slice to the loop iteration range to enable bound check
+        // elimination in the compiler
+        let lhs = &self[..l];
+        let rhs = &other[..l];
+
+        for i in 0..l {
+            match lhs[i].partial_cmp(&rhs[i]) {
+                Some(Ordering::Equal) => (),
+                non_eq => return non_eq,
+            }
+        }
+
+        self.len().partial_cmp(&other.len())
+    }
+}
+
+impl<A> SlicePartialOrd<A> for [A]
+    where A: Ord
+{
+    default fn partial_compare(&self, other: &[A]) -> Option<Ordering> {
+        Some(SliceOrd::compare(self, other))
+    }
+}
+
+#[doc(hidden)]
+// intermediate trait for specialization of slice's Ord
+trait SliceOrd<B> {
+    fn compare(&self, other: &[B]) -> Ordering;
+}
+
+impl<A> SliceOrd<A> for [A]
+    where A: Ord
+{
+    default fn compare(&self, other: &[A]) -> Ordering {
+        let l = cmp::min(self.len(), other.len());
+
+        // Slice to the loop iteration range to enable bound check
+        // elimination in the compiler
+        let lhs = &self[..l];
+        let rhs = &other[..l];
+
+        for i in 0..l {
+            match lhs[i].cmp(&rhs[i]) {
+                Ordering::Equal => (),
+                non_eq => return non_eq,
+            }
+        }
+
+        self.len().cmp(&other.len())
+    }
+}
+
+// memcmp compares a sequence of unsigned bytes lexicographically.
+// this matches the order we want for [u8], but no others (not even [i8]).
+impl SliceOrd<u8> for [u8] {
+    #[inline]
+    fn compare(&self, other: &[u8]) -> Ordering {
+        let order = unsafe {
+            memcmp(self.as_ptr(), other.as_ptr(),
+                   cmp::min(self.len(), other.len()))
+        };
+        if order == 0 {
+            self.len().cmp(&other.len())
+        } else if order < 0 {
+            Less
+        } else {
+            Greater
+        }
+    }
+}
+
+#[doc(hidden)]
+/// Trait implemented for types that can be compared for equality using
+/// their bytewise representation
+trait BytewiseEquality { }
+
+macro_rules! impl_marker_for {
+    ($traitname:ident, $($ty:ty)*) => {
+        $(
+            impl $traitname for $ty { }
+        )*
+    }
+}
+
+impl_marker_for!(BytewiseEquality,
+                 u8 i8 u16 i16 u32 i32 u64 i64 usize isize char bool);
+
+#[doc(hidden)]
+unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> {
+    unsafe fn get_unchecked(&mut self, i: usize) -> &'a T {
+        &*self.ptr.offset(i as isize)
+    }
+    fn may_have_side_effect() -> bool { false }
+}
+
+#[doc(hidden)]
+unsafe impl<'a, T> TrustedRandomAccess for IterMut<'a, T> {
+    unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut T {
+        &mut *self.ptr.offset(i as isize)
+    }
+    fn may_have_side_effect() -> bool { false }
+}
diff --git a/src/libcore/slice/sort.rs b/src/libcore/slice/sort.rs
new file mode 100644 (file)
index 0000000..fdfba33
--- /dev/null
@@ -0,0 +1,699 @@
+// 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 2..v.len()+1 {
+        shift_tail(&mut v[..i], 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 {
+        // A random number will be taken modulo this one. The modulus is a power of two so that we
+        // can simply take bitwise "and", thus avoiding costly CPU operations.
+        let modulus = (len / 4).next_power_of_two();
+        debug_assert!(modulus >= 1 && modulus <= len / 2);
+
+        // Pseudorandom number generation from the "Xorshift RNGs" paper by George Marsaglia.
+        let mut random = len;
+        random ^= random << 13;
+        random ^= random >> 17;
+        random ^= random << 5;
+        random &= modulus - 1;
+        debug_assert!(random < len / 2);
+
+        // The first index.
+        let a = len / 4 * 2;
+        debug_assert!(a >= 1 && a < len - 2);
+
+        // The second index.
+        let b = len / 4 + random;
+        debug_assert!(b >= 1 && b < len - 2);
+
+        // Swap neighbourhoods of `a` and `b`.
+        for i in 0..3 {
+            v.swap(a - 1 + i, b - 1 + i);
+        }
+    }
+}
+
+/// 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);
+}
index d84a1e227560ea45383e42759c491dee9c8564dd..d92c378160d2e0e4ba3eabcc5fcdc813675b07c4 100644 (file)
 #![feature(decode_utf8)]
 #![feature(fixed_size_array)]
 #![feature(flt2dec)]
+#![feature(fmt_internals)]
 #![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)]
-#![feature(fmt_internals)]
 
 extern crate core;
 extern crate test;
index ad39e6b081b425b7223a5b4d1459633caf0150f7..89bd3be08519ccd1259f808b7f8b8aafdee42acc 100644 (file)
@@ -8,7 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use core::slice::heapsort;
 use core::result::Result::{Ok, Err};
+use rand::{Rng, XorShiftRng};
 
 #[test]
 fn test_binary_search() {
@@ -139,9 +141,6 @@ fn test_chunks_mut_last() {
     assert_eq!(c2.last().unwrap()[0], 4);
 }
 
-
-
-
 #[test]
 fn test_windows_count() {
     let v: &[i32] = &[0, 1, 2, 3, 4, 5];
@@ -224,3 +223,57 @@ fn get_unchecked_mut_range() {
         assert_eq!(v.get_unchecked_mut(1..4), &mut [1, 2, 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]));
+            }
+        }
+    }
+
+    // Should not panic.
+    [0i32; 0].sort_unstable();
+    [(); 10].sort_unstable();
+    [(); 100].sort_unstable();
+
+    let mut v = [0xDEADBEEFu64];
+    v.sort_unstable();
+    assert!(v == [0xDEADBEEF]);
+}
index aedb8fef2885cf461cca140334147a030940e891..7bab4a8d725dc2bcdfd87fdde54c44d639c3973c 100644 (file)
@@ -12,6 +12,7 @@
 use util::nodemap::NodeMap;
 use syntax::ast;
 use syntax::ext::base::MacroKind;
+use syntax_pos::Span;
 use hir;
 
 #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
@@ -116,6 +117,7 @@ pub fn kind_name(&self) -> &'static str {
 pub struct Export {
     pub name: ast::Name, // The name of the target.
     pub def: Def, // The definition of the target.
+    pub span: Span, // The span of the target definition.
 }
 
 impl CtorKind {
index b4b9966cbe47b98138d8ad1afe0e3b047d5537a6..c2ad598b0c503c49acf8c080596f84360f411048 100644 (file)
@@ -683,7 +683,7 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F)
                         },
                         ext.kind()
                     );
-                    callback(def::Export { name: name, def: def });
+                    callback(def::Export { name: name, def: def, span: DUMMY_SP });
                 }
             }
             return
@@ -720,6 +720,7 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F)
                                 callback(def::Export {
                                     def: def,
                                     name: self.item_name(child_index),
+                                    span: self.entry(child_index).span.decode(self),
                                 });
                             }
                         }
@@ -732,12 +733,10 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F)
                 }
 
                 let def_key = self.def_key(child_index);
+                let span = child.span.decode(self);
                 if let (Some(def), Some(name)) =
                     (self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) {
-                    callback(def::Export {
-                        def: def,
-                        name: name,
-                    });
+                    callback(def::Export { def: def, name: name, span: span });
                     // For non-reexport structs and variants add their constructors to children.
                     // Reexport lists automatically contain constructors when necessary.
                     match def {
@@ -745,10 +744,7 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F)
                             if let Some(ctor_def_id) = self.get_struct_ctor_def_id(child_index) {
                                 let ctor_kind = self.get_ctor_kind(child_index);
                                 let ctor_def = Def::StructCtor(ctor_def_id, ctor_kind);
-                                callback(def::Export {
-                                    def: ctor_def,
-                                    name: name,
-                                });
+                                callback(def::Export { def: ctor_def, name: name, span: span });
                             }
                         }
                         Def::Variant(def_id) => {
@@ -756,10 +752,7 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F)
                             // value namespace, they are reserved for possible future use.
                             let ctor_kind = self.get_ctor_kind(child_index);
                             let ctor_def = Def::VariantCtor(def_id, ctor_kind);
-                            callback(def::Export {
-                                def: ctor_def,
-                                name: name,
-                            });
+                            callback(def::Export { def: ctor_def, name: name, span: span });
                         }
                         _ => {}
                     }
index be905a9d0f94a904af2bed118631f52007dd7985..c33d5b9b6e16bb14bb4980039c00deac67c22c5c 100644 (file)
@@ -605,7 +605,7 @@ fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>, expa
             let ident = Ident::with_empty_ctxt(name);
             let result = self.resolve_ident_in_module(module, ident, MacroNS, false, None);
             if let Ok(binding) = result {
-                self.macro_exports.push(Export { name: name, def: binding.def() });
+                self.macro_exports.push(Export { name: name, def: binding.def(), span: span });
             } else {
                 span_err!(self.session, span, E0470, "reexported macro not found");
             }
index df3be8fa0f810cb22bc639830b0f88776a0a1295..99fc1c142f6815fd2cc097699e3fd0be0e02cd2b 100644 (file)
@@ -230,12 +230,12 @@ fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>)
                         attrs.remove(i);
                     } else {
                         let mut tokens = Vec::new();
-                        for (i, path) in traits.iter().enumerate() {
-                            if i > 0 {
+                        for (j, path) in traits.iter().enumerate() {
+                            if j > 0 {
                                 tokens.push(TokenTree::Token(attrs[i].span, Token::Comma).into());
                             }
-                            for (j, segment) in path.segments.iter().enumerate() {
-                                if j > 0 {
+                            for (k, segment) in path.segments.iter().enumerate() {
+                                if k > 0 {
                                     tokens.push(TokenTree::Token(path.span, Token::ModSep).into());
                                 }
                                 let tok = Token::Ident(segment.identifier);
@@ -653,7 +653,7 @@ pub fn define_macro(&mut self, item: &ast::Item, legacy_scope: &mut LegacyScope<
 
         if attr::contains_name(&item.attrs, "macro_export") {
             let def = Def::Macro(def_id, MacroKind::Bang);
-            self.macro_exports.push(Export { name: ident.name, def: def });
+            self.macro_exports.push(Export { name: ident.name, def: def, span: item.span });
         }
     }
 
index dbc8bca548b769a1334f15facf53288a0a7e8845..2f4ac12cd7363bf2604c8d738206947802300f27 100644 (file)
@@ -21,7 +21,7 @@
 use rustc::lint::builtin::PRIVATE_IN_PUBLIC;
 use rustc::hir::def_id::DefId;
 use rustc::hir::def::*;
-use rustc::util::nodemap::FxHashSet;
+use rustc::util::nodemap::FxHashMap;
 
 use syntax::ast::{Ident, NodeId};
 use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
@@ -763,10 +763,11 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
         *module.globs.borrow_mut() = Vec::new();
 
         let mut reexports = Vec::new();
+        let mut exported_macro_names = FxHashMap();
         if module as *const _ == self.graph_root as *const _ {
-            let mut exported_macro_names = FxHashSet();
-            for export in mem::replace(&mut self.macro_exports, Vec::new()).into_iter().rev() {
-                if exported_macro_names.insert(export.name) {
+            let macro_exports = mem::replace(&mut self.macro_exports, Vec::new());
+            for export in macro_exports.into_iter().rev() {
+                if exported_macro_names.insert(export.name, export.span).is_none() {
                     reexports.push(export);
                 }
             }
@@ -786,7 +787,17 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
                     if !def.def_id().is_local() {
                         self.session.cstore.export_macros(def.def_id().krate);
                     }
-                    reexports.push(Export { name: ident.name, def: def });
+                    if let Def::Macro(..) = def {
+                        if let Some(&span) = exported_macro_names.get(&ident.name) {
+                            let msg =
+                                format!("a macro named `{}` has already been exported", ident);
+                            self.session.struct_span_err(span, &msg)
+                                .span_label(span, &format!("`{}` already exported", ident))
+                                .span_note(binding.span, "previous macro export here")
+                                .emit();
+                        }
+                    }
+                    reexports.push(Export { name: ident.name, def: def, span: binding.span });
                 }
             }
 
index 84fb69a7f1094e46dc51c5fa3b2be8c0e514e289..4347046b6b8088651e413766e9958231a5772d96 100644 (file)
@@ -17,7 +17,7 @@
 pub use symbol::Symbol as Name;
 pub use util::ThinVec;
 
-use syntax_pos::{mk_sp, Span, DUMMY_SP, ExpnId};
+use syntax_pos::{mk_sp, BytePos, Span, DUMMY_SP, ExpnId};
 use codemap::{respan, Spanned};
 use abi::Abi;
 use ext::hygiene::SyntaxContext;
@@ -1716,6 +1716,16 @@ pub struct PolyTraitRef {
     pub span: Span,
 }
 
+impl PolyTraitRef {
+    pub fn new(lifetimes: Vec<LifetimeDef>, path: Path, lo: BytePos, hi: BytePos) -> Self {
+        PolyTraitRef {
+            bound_lifetimes: lifetimes,
+            trait_ref: TraitRef { path: path, ref_id: DUMMY_NODE_ID },
+            span: mk_sp(lo, hi),
+        }
+    }
+}
+
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Visibility {
     Public,
index c1816582bc6ca2418c8bc361f841d4c77b35a17a..6abeb4b0b2805f9b642c6eaa7f7a2e9c82d56119 100644 (file)
@@ -657,7 +657,7 @@ pub fn parse_expansion(&mut self, kind: ExpansionKind, macro_legacy_warnings: bo
             }
             ExpansionKind::Expr => Expansion::Expr(self.parse_expr()?),
             ExpansionKind::OptExpr => Expansion::OptExpr(Some(self.parse_expr()?)),
-            ExpansionKind::Ty => Expansion::Ty(self.parse_ty_no_plus()?),
+            ExpansionKind::Ty => Expansion::Ty(self.parse_ty()?),
             ExpansionKind::Pat => Expansion::Pat(self.parse_pat()?),
         })
     }
index 10b7249743b8c49762cf2cc38d9dd672a0a8a618..d7a85baa3fff56b127eefdea5fcd24be5aa7a677 100644 (file)
@@ -414,7 +414,7 @@ pub fn parse_arm_panic(parser: &mut Parser) -> Arm {
 }
 
 pub fn parse_ty_panic(parser: &mut Parser) -> P<Ty> {
-    panictry!(parser.parse_ty_no_plus())
+    panictry!(parser.parse_ty())
 }
 
 pub fn parse_stmt_panic(parser: &mut Parser) -> Option<Stmt> {
index 6385d206a0cb90bacbf863a2f97a1405be614fc4..ed17f0f956cf3b5367f8a77dd6c0cae0fbd4b833 100644 (file)
@@ -512,7 +512,7 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
         },
         "pat" => token::NtPat(panictry!(p.parse_pat())),
         "expr" => token::NtExpr(panictry!(p.parse_expr())),
-        "ty" => token::NtTy(panictry!(p.parse_ty_no_plus())),
+        "ty" => token::NtTy(panictry!(p.parse_ty())),
         // this could be handled like a token, since it is one
         "ident" => match p.token {
             token::Ident(sn) => {
index 0a97accead6a2a0684de30a0a71c81afda1e30c2..df4ccc94c0421cbb9397a459079f405fac7f5a29 100644 (file)
@@ -41,7 +41,7 @@
 use ast::RangeEnd;
 use {ast, attr};
 use codemap::{self, CodeMap, Spanned, spanned, respan};
-use syntax_pos::{self, Span, Pos, BytePos, mk_sp};
+use syntax_pos::{self, Span, BytePos, mk_sp};
 use errors::{self, DiagnosticBuilder};
 use parse::{self, classify, token};
 use parse::common::SeqSep;
@@ -1116,57 +1116,13 @@ pub fn token_is_bare_fn_keyword(&mut self) -> bool {
             self.check_keyword(keywords::Extern)
     }
 
-    pub fn get_lifetime(&mut self) -> ast::Ident {
+    fn get_label(&mut self) -> ast::Ident {
         match self.token {
             token::Lifetime(ref ident) => *ident,
             _ => self.bug("not a lifetime"),
         }
     }
 
-    pub fn parse_for_in_type(&mut self) -> PResult<'a, TyKind> {
-        /*
-        Parses whatever can come after a `for` keyword in a type.
-        The `for` hasn't been consumed.
-
-        - for <'lt> [unsafe] [extern "ABI"] fn (S) -> T
-        - for <'lt> path::foo(a, b) + Trait + 'a
-        */
-
-        let lo = self.span.lo;
-        let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
-
-        // examine next token to decide to do
-        if self.token_is_bare_fn_keyword() {
-            self.parse_ty_bare_fn(lifetime_defs)
-        } else {
-            let hi = self.span.hi;
-            let trait_ref = self.parse_trait_ref()?;
-            let poly_trait_ref = PolyTraitRef { bound_lifetimes: lifetime_defs,
-                                                trait_ref: trait_ref,
-                                                span: mk_sp(lo, hi)};
-            let other_bounds = if self.eat(&token::BinOp(token::Plus)) {
-                self.parse_ty_param_bounds()?
-            } else {
-                Vec::new()
-            };
-            let all_bounds =
-                Some(TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None)).into_iter()
-                .chain(other_bounds)
-                .collect();
-            Ok(ast::TyKind::TraitObject(all_bounds))
-        }
-    }
-
-    pub fn parse_impl_trait_type(&mut self) -> PResult<'a, TyKind> {
-        // Parses whatever can come after a `impl` keyword in a type.
-        // The `impl` has already been consumed.
-        Ok(ast::TyKind::ImplTrait(self.parse_ty_param_bounds()?))
-    }
-
-    pub fn parse_ty_path(&mut self) -> PResult<'a, TyKind> {
-        Ok(TyKind::Path(None, self.parse_path(PathStyle::Type)?))
-    }
-
     /// parse a TyKind::BareFn type:
     pub fn parse_ty_bare_fn(&mut self, lifetime_defs: Vec<LifetimeDef>)
                             -> PResult<'a, TyKind> {
@@ -1347,84 +1303,9 @@ pub fn parse_ret_ty(&mut self) -> PResult<'a, FunctionRetTy> {
         }
     }
 
-    /// Parse a type.
+    // Parse a type
     pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
-        let lo = self.span.lo;
-        let lhs = self.parse_ty_no_plus()?;
-
-        if !self.eat(&token::BinOp(token::Plus)) {
-            return Ok(lhs);
-        }
-
-        let mut bounds = self.parse_ty_param_bounds()?;
-
-        // In type grammar, `+` is treated like a binary operator,
-        // and hence both L and R side are required.
-        if bounds.is_empty() {
-            let prev_span = self.prev_span;
-            self.span_err(prev_span,
-                          "at least one type parameter bound \
-                          must be specified");
-        }
-
-        let mut lhs = lhs.unwrap();
-        if let TyKind::Paren(ty) = lhs.node {
-            // We have to accept the first bound in parens for backward compatibility.
-            // Example: `(Bound) + Bound + Bound`
-            lhs = ty.unwrap();
-        }
-        if let TyKind::Path(None, path) = lhs.node {
-            let poly_trait_ref = PolyTraitRef {
-                bound_lifetimes: Vec::new(),
-                trait_ref: TraitRef { path: path, ref_id: lhs.id },
-                span: lhs.span,
-            };
-            let poly_trait_ref = TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None);
-            bounds.insert(0, poly_trait_ref);
-        } else {
-            let mut err = struct_span_err!(self.sess.span_diagnostic, lhs.span, E0178,
-                                            "expected a path on the left-hand side \
-                                            of `+`, not `{}`",
-                                            pprust::ty_to_string(&lhs));
-            err.span_label(lhs.span, &format!("expected a path"));
-            let hi = bounds.iter().map(|x| match *x {
-                TraitTyParamBound(ref tr, _) => tr.span.hi,
-                RegionTyParamBound(ref r) => r.span.hi,
-            }).max_by_key(|x| x.to_usize());
-            let full_span = hi.map(|hi| Span {
-                lo: lhs.span.lo,
-                hi: hi,
-                expn_id: lhs.span.expn_id,
-            });
-            match (&lhs.node, full_span) {
-                (&TyKind::Rptr(ref lifetime, ref mut_ty), Some(full_span)) => {
-                    let ty_str = pprust::to_string(|s| {
-                        use print::pp::word;
-                        use print::pprust::PrintState;
-
-                        word(&mut s.s, "&")?;
-                        s.print_opt_lifetime(lifetime)?;
-                        s.print_mutability(mut_ty.mutbl)?;
-                        s.popen()?;
-                        s.print_type(&mut_ty.ty)?;
-                        s.print_bounds(" +", &bounds)?;
-                        s.pclose()
-                    });
-                    err.span_suggestion(full_span, "try adding parentheses (per RFC 438):",
-                                        ty_str);
-                }
-
-                _ => {
-                    help!(&mut err,
-                                "perhaps you forgot parentheses? (per RFC 438)");
-                }
-            }
-            err.emit();
-        }
-
-        let sp = mk_sp(lo, self.prev_span.hi);
-        let sum = TyKind::TraitObject(bounds);
-        Ok(P(Ty {id: ast::DUMMY_NODE_ID, node: sum, span: sp}))
+        self.parse_ty_common(true)
     }
 
     /// Parse a type in restricted contexts where `+` is not permitted.
@@ -1432,15 +1313,17 @@ pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
     ///     `+` is prohibited to maintain operator priority (P(+) < P(&)).
     /// Example 2: `value1 as TYPE + value2`
     ///     `+` is prohibited to avoid interactions with expression grammar.
-    pub fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
+    fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
+        self.parse_ty_common(false)
+    }
+
+    fn parse_ty_common(&mut self, allow_plus: bool) -> PResult<'a, P<Ty>> {
         maybe_whole!(self, NtTy, |x| x);
 
         let lo = self.span.lo;
-
-        let t = if self.eat(&token::OpenDelim(token::Paren)) {
-            // (t) is a parenthesized ty
-            // (t,) is the type of a tuple with only one field,
-            // of type t
+        let node = if self.eat(&token::OpenDelim(token::Paren)) {
+            // `(TYPE)` is a parenthesized type.
+            // `(TYPE,)` is a tuple with a single field of type TYPE.
             let mut ts = vec![];
             let mut last_comma = false;
             while self.token != token::CloseDelim(token::Paren) {
@@ -1452,81 +1335,162 @@ pub fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
                     break;
                 }
             }
-
             self.expect(&token::CloseDelim(token::Paren))?;
+
             if ts.len() == 1 && !last_comma {
-                TyKind::Paren(ts.into_iter().nth(0).unwrap())
+                let ty = ts.into_iter().nth(0).unwrap().unwrap();
+                match ty.node {
+                    // Accept `(Trait1) + Trait2 + 'a` for backward compatibility (#39318).
+                    TyKind::Path(None, ref path)
+                            if allow_plus && self.token == token::BinOp(token::Plus) => {
+                        self.bump(); // `+`
+                        let pt = PolyTraitRef::new(Vec::new(), path.clone(), lo, self.prev_span.hi);
+                        let mut bounds = vec![TraitTyParamBound(pt, TraitBoundModifier::None)];
+                        bounds.append(&mut self.parse_ty_param_bounds()?);
+                        TyKind::TraitObject(bounds)
+                    }
+                    _ => TyKind::Paren(P(ty))
+                }
             } else {
                 TyKind::Tup(ts)
             }
         } else if self.eat(&token::Not) {
+            // Never type `!`
             TyKind::Never
         } else if self.eat(&token::BinOp(token::Star)) {
-            // STAR POINTER (bare pointer?)
+            // Raw pointer
             TyKind::Ptr(self.parse_ptr()?)
         } else if self.eat(&token::OpenDelim(token::Bracket)) {
-            // VECTOR
+            // Array or slice
             let t = self.parse_ty()?;
-
-            // Parse the `; e` in `[ i32; e ]`
-            // where `e` is a const expression
+            // Parse optional `; EXPR` in `[TYPE; EXPR]`
             let t = match self.maybe_parse_fixed_length_of_vec()? {
                 None => TyKind::Slice(t),
-                Some(suffix) => TyKind::Array(t, suffix)
+                Some(suffix) => TyKind::Array(t, suffix),
             };
             self.expect(&token::CloseDelim(token::Bracket))?;
             t
-        } else if self.check(&token::BinOp(token::And)) ||
-                  self.check(&token::AndAnd) {
-            // BORROWED POINTER
+        } else if self.check(&token::BinOp(token::And)) || self.check(&token::AndAnd) {
+            // Reference
             self.expect_and()?;
             self.parse_borrowed_pointee()?
-        } else if self.check_keyword(keywords::For) {
-            // FIXME `+` has incorrect priority in trait object types starting with `for` (#39317).
-            self.parse_for_in_type()?
-        } else if self.eat_keyword(keywords::Impl) {
-            // FIXME figure out priority of `+` in `impl Trait1 + Trait2` (#34511).
-            self.parse_impl_trait_type()?
-        } else if self.token_is_bare_fn_keyword() {
-            // BARE FUNCTION
-            self.parse_ty_bare_fn(Vec::new())?
         } else if self.eat_keyword_noexpect(keywords::Typeof) {
-            // TYPEOF
+            // `typeof(EXPR)`
             // In order to not be ambiguous, the type must be surrounded by parens.
             self.expect(&token::OpenDelim(token::Paren))?;
             let e = self.parse_expr()?;
             self.expect(&token::CloseDelim(token::Paren))?;
             TyKind::Typeof(e)
+        } else if self.eat(&token::Underscore) {
+            // A type to be inferred `_`
+            TyKind::Infer
         } else if self.eat_lt() {
+            // Qualified path
             let (qself, path) = self.parse_qualified_path(PathStyle::Type)?;
             TyKind::Path(Some(qself), path)
         } else if self.token.is_path_start() {
+            // Simple path
             let path = self.parse_path(PathStyle::Type)?;
             if self.eat(&token::Not) {
-                // MACRO INVOCATION
+                // Macro invocation in type position
                 let (_, tts) = self.expect_delimited_token_tree()?;
-                let hi = self.span.hi;
-                TyKind::Mac(spanned(lo, hi, Mac_ { path: path, tts: tts }))
+                TyKind::Mac(spanned(lo, self.span.hi, Mac_ { path: path, tts: tts }))
             } else {
-                // NAMED TYPE
-                TyKind::Path(None, path)
+                // Just a type path or bound list (trait object type) starting with a trait.
+                //   `Type`
+                //   `Trait1 + Trait2 + 'a`
+                if allow_plus && self.eat(&token::BinOp(token::Plus)) {
+                    let poly_trait = PolyTraitRef::new(Vec::new(), path, lo, self.prev_span.hi);
+                    let mut bounds = vec![TraitTyParamBound(poly_trait, TraitBoundModifier::None)];
+                    bounds.append(&mut self.parse_ty_param_bounds()?);
+                    TyKind::TraitObject(bounds)
+                } else {
+                    TyKind::Path(None, path)
+                }
             }
-        } else if self.eat(&token::Underscore) {
-            // TYPE TO BE INFERRED
-            TyKind::Infer
+        } else if self.token_is_bare_fn_keyword() {
+            // Function pointer type
+            self.parse_ty_bare_fn(Vec::new())?
+        } else if self.check_keyword(keywords::For) {
+            // Function pointer type or bound list (trait object type) starting with a poly-trait.
+            //   `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
+            //   `for<'lt> Trait1<'lt> + Trait2 + 'a`
+            let lo = self.span.lo;
+            let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
+            if self.token_is_bare_fn_keyword() {
+                self.parse_ty_bare_fn(lifetime_defs)?
+            } else {
+                let path = self.parse_path(PathStyle::Type)?;
+                let poly_trait = PolyTraitRef::new(lifetime_defs, path, lo, self.prev_span.hi);
+                let mut bounds = vec![TraitTyParamBound(poly_trait, TraitBoundModifier::None)];
+                if allow_plus && self.eat(&token::BinOp(token::Plus)) {
+                    bounds.append(&mut self.parse_ty_param_bounds()?)
+                }
+                TyKind::TraitObject(bounds)
+            }
+        } else if self.eat_keyword(keywords::Impl) {
+            // FIXME: figure out priority of `+` in `impl Trait1 + Trait2` (#34511).
+            TyKind::ImplTrait(self.parse_ty_param_bounds()?)
+        } else if self.check(&token::Question) {
+            // Bound list (trait object type)
+            // Bound lists starting with `'lt` are not currently supported (#40043)
+            TyKind::TraitObject(self.parse_ty_param_bounds_common(allow_plus)?)
         } else {
             let msg = format!("expected type, found {}", self.this_token_descr());
             return Err(self.fatal(&msg));
         };
 
-        let sp = mk_sp(lo, self.prev_span.hi);
-        Ok(P(Ty {id: ast::DUMMY_NODE_ID, node: t, span: sp}))
+        let span = mk_sp(lo, self.prev_span.hi);
+        let ty = Ty { node: node, span: span, id: ast::DUMMY_NODE_ID };
+
+        // Try to recover from use of `+` with incorrect priority.
+        self.maybe_recover_from_bad_type_plus(allow_plus, &ty)?;
+
+        Ok(P(ty))
     }
 
-    pub fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
-        // look for `&'lt` or `&'foo ` and interpret `foo` as the region name:
-        let opt_lifetime = self.eat_lifetime();
-        let mutbl = self.parse_mutability()?;
+    fn maybe_recover_from_bad_type_plus(&mut self, allow_plus: bool, ty: &Ty) -> PResult<'a, ()> {
+        // Do not add `+` to expected tokens.
+        if !allow_plus || self.token != token::BinOp(token::Plus) {
+            return Ok(())
+        }
+
+        self.bump(); // `+`
+        let bounds = self.parse_ty_param_bounds()?;
+        let sum_span = mk_sp(ty.span.lo, self.prev_span.hi);
+
+        let mut err = struct_span_err!(self.sess.span_diagnostic, ty.span, E0178,
+            "expected a path on the left-hand side of `+`, not `{}`", pprust::ty_to_string(&ty));
+        err.span_label(ty.span, &format!("expected a path"));
+
+        match ty.node {
+            TyKind::Rptr(ref lifetime, ref mut_ty) => {
+                let sum_with_parens = pprust::to_string(|s| {
+                    use print::pp::word;
+                    use print::pprust::PrintState;
+
+                    word(&mut s.s, "&")?;
+                    s.print_opt_lifetime(lifetime)?;
+                    s.print_mutability(mut_ty.mutbl)?;
+                    s.popen()?;
+                    s.print_type(&mut_ty.ty)?;
+                    s.print_bounds(" +", &bounds)?;
+                    s.pclose()
+                });
+                err.span_suggestion(sum_span, "try adding parentheses:", sum_with_parens);
+            }
+            TyKind::Ptr(..) | TyKind::BareFn(..) => {
+                help!(&mut err, "perhaps you forgot parentheses?");
+            }
+            _ => {}
+        }
+        err.emit();
+        Ok(())
+    }
+
+    fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
+        let opt_lifetime = if self.check_lifetime() { Some(self.expect_lifetime()) } else { None };
+        let mutbl = self.parse_mutability();
         let ty = self.parse_ty_no_plus()?;
         return Ok(TyKind::Rptr(opt_lifetime, MutTy { ty: ty, mutbl: mutbl }));
     }
@@ -1927,30 +1891,28 @@ pub fn parse_path_segments_without_types(&mut self)
         }
     }
 
-    /// Parse single lifetime 'a or nothing.
-    pub fn eat_lifetime(&mut self) -> Option<Lifetime> {
+    fn check_lifetime(&mut self) -> bool {
+        self.expected_tokens.push(TokenType::Lifetime);
+        self.token.is_lifetime()
+    }
+
+    /// Parse single lifetime 'a or panic.
+    fn expect_lifetime(&mut self) -> Lifetime {
         match self.token {
             token::Lifetime(ident) => {
                 self.bump();
-                Some(Lifetime {
-                    id: ast::DUMMY_NODE_ID,
-                    span: self.prev_span,
-                    name: ident.name
-                })
-            }
-            _ => {
-                self.expected_tokens.push(TokenType::Lifetime);
-                None
+                Lifetime { name: ident.name, span: self.prev_span, id: ast::DUMMY_NODE_ID }
             }
+            _ => self.span_bug(self.span, "not a lifetime")
         }
     }
 
     /// Parse mutability (`mut` or nothing).
-    pub fn parse_mutability(&mut self) -> PResult<'a, Mutability> {
+    fn parse_mutability(&mut self) -> Mutability {
         if self.eat_keyword(keywords::Mut) {
-            Ok(Mutability::Mutable)
+            Mutability::Mutable
         } else {
-            Ok(Mutability::Immutable)
+            Mutability::Immutable
         }
     }
 
@@ -2207,7 +2169,7 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                     return self.parse_while_expr(None, lo, attrs);
                 }
                 if self.token.is_lifetime() {
-                    let label = Spanned { node: self.get_lifetime(),
+                    let label = Spanned { node: self.get_label(),
                                           span: self.span };
                     let lo = self.span.lo;
                     self.bump();
@@ -2230,7 +2192,7 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                 if self.eat_keyword(keywords::Continue) {
                     let ex = if self.token.is_lifetime() {
                         let ex = ExprKind::Continue(Some(Spanned{
-                            node: self.get_lifetime(),
+                            node: self.get_label(),
                             span: self.span
                         }));
                         self.bump();
@@ -2267,7 +2229,7 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                 } else if self.eat_keyword(keywords::Break) {
                     let lt = if self.token.is_lifetime() {
                         let spanned_lt = Spanned {
-                            node: self.get_lifetime(),
+                            node: self.get_label(),
                             span: self.span
                         };
                         self.bump();
@@ -2700,7 +2662,7 @@ pub fn parse_prefix_expr(&mut self,
             }
             token::BinOp(token::And) | token::AndAnd => {
                 self.expect_and()?;
-                let m = self.parse_mutability()?;
+                let m = self.parse_mutability();
                 let e = self.parse_prefix_expr(None);
                 let (span, e) = self.interpolated_or_expr_span(e)?;
                 hi = span.hi;
@@ -3422,7 +3384,7 @@ pub fn parse_pat(&mut self) -> PResult<'a, P<Pat>> {
             token::BinOp(token::And) | token::AndAnd => {
                 // Parse &pat / &mut pat
                 self.expect_and()?;
-                let mutbl = self.parse_mutability()?;
+                let mutbl = self.parse_mutability();
                 if let token::Lifetime(ident) = self.token {
                     return Err(self.fatal(&format!("unexpected lifetime `{}` in pattern", ident)));
                 }
@@ -3449,7 +3411,7 @@ pub fn parse_pat(&mut self) -> PResult<'a, P<Pat>> {
                 pat = self.parse_pat_ident(BindingMode::ByValue(Mutability::Mutable))?;
             } else if self.eat_keyword(keywords::Ref) {
                 // Parse ref ident @ pat / ref mut ident @ pat
-                let mutbl = self.parse_mutability()?;
+                let mutbl = self.parse_mutability();
                 pat = self.parse_pat_ident(BindingMode::ByRef(mutbl))?;
             } else if self.eat_keyword(keywords::Box) {
                 // Parse box pat
@@ -4069,30 +4031,32 @@ fn warn_missing_semicolon(&self) {
     // BOUND = TY_BOUND | LT_BOUND
     // LT_BOUND = LIFETIME (e.g. `'a`)
     // TY_BOUND = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g. `?for<'a: 'b> m::Trait<'a>`)
-    fn parse_ty_param_bounds(&mut self) -> PResult<'a, TyParamBounds>
-    {
+    fn parse_ty_param_bounds_common(&mut self, allow_plus: bool) -> PResult<'a, TyParamBounds> {
         let mut bounds = Vec::new();
         loop {
             let question = if self.eat(&token::Question) { Some(self.prev_span) } else { None };
-            if let Some(lifetime) = self.eat_lifetime() {
+            if self.check_lifetime() {
                 if let Some(question_span) = question {
                     self.span_err(question_span,
                                   "`?` may only modify trait bounds, not lifetime bounds");
                 }
-                bounds.push(RegionTyParamBound(lifetime));
-            } else {if self.check_keyword(keywords::For) || self.check_path() {
-                let poly_trait_ref = self.parse_poly_trait_ref()?;
+                bounds.push(RegionTyParamBound(self.expect_lifetime()));
+            } else if self.check_keyword(keywords::For) || self.check_path() {
+                let lo = self.span.lo;
+                let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
+                let path = self.parse_path(PathStyle::Type)?;
+                let poly_trait = PolyTraitRef::new(lifetime_defs, path, lo, self.prev_span.hi);
                 let modifier = if question.is_some() {
                     TraitBoundModifier::Maybe
                 } else {
                     TraitBoundModifier::None
                 };
-                bounds.push(TraitTyParamBound(poly_trait_ref, modifier));
+                bounds.push(TraitTyParamBound(poly_trait, modifier));
             } else {
                 break
-            }}
+            }
 
-            if !self.eat(&token::BinOp(token::Plus)) {
+            if !allow_plus || !self.eat(&token::BinOp(token::Plus)) {
                 break
             }
         }
@@ -4100,12 +4064,16 @@ fn parse_ty_param_bounds(&mut self) -> PResult<'a, TyParamBounds>
         return Ok(bounds);
     }
 
+    fn parse_ty_param_bounds(&mut self) -> PResult<'a, TyParamBounds> {
+        self.parse_ty_param_bounds_common(true)
+    }
+
     // Parse bounds of a type parameter `BOUND + BOUND + BOUND` without trailing `+`.
     // BOUND = LT_BOUND (e.g. `'a`)
     fn parse_lt_param_bounds(&mut self) -> Vec<Lifetime> {
         let mut lifetimes = Vec::new();
-        while let Some(lifetime) = self.eat_lifetime() {
-            lifetimes.push(lifetime);
+        while self.check_lifetime() {
+            lifetimes.push(self.expect_lifetime());
 
             if !self.eat(&token::BinOp(token::Plus)) {
                 break
@@ -4150,7 +4118,8 @@ pub fn parse_generic_params(&mut self) -> PResult<'a, (Vec<LifetimeDef>, Vec<TyP
         let mut seen_ty_param = false;
         loop {
             let attrs = self.parse_outer_attributes()?;
-            if let Some(lifetime) = self.eat_lifetime() {
+            if self.check_lifetime() {
+                let lifetime = self.expect_lifetime();
                 // Parse lifetime parameter.
                 let bounds = if self.eat(&token::Colon) {
                     self.parse_lt_param_bounds()
@@ -4166,7 +4135,7 @@ pub fn parse_generic_params(&mut self) -> PResult<'a, (Vec<LifetimeDef>, Vec<TyP
                     self.span_err(self.prev_span,
                         "lifetime parameters must be declared prior to type parameters");
                 }
-            } else {if self.check_ident() {
+            } else if self.check_ident() {
                 // Parse type parameter.
                 ty_params.push(self.parse_ty_param(attrs)?);
                 seen_ty_param = true;
@@ -4178,7 +4147,7 @@ pub fn parse_generic_params(&mut self) -> PResult<'a, (Vec<LifetimeDef>, Vec<TyP
                         &format!("trailing attribute after {} parameters", param_kind));
                 }
                 break
-            }}
+            }
 
             if !self.eat(&token::Comma) {
                 break
@@ -4224,14 +4193,14 @@ fn parse_generic_args(&mut self) -> PResult<'a, (Vec<Lifetime>, Vec<P<Ty>>, Vec<
         let mut seen_type = false;
         let mut seen_binding = false;
         loop {
-            if let Some(lifetime) = self.eat_lifetime() {
+            if self.check_lifetime() && self.look_ahead(1, |t| t != &token::BinOp(token::Plus)) {
                 // Parse lifetime argument.
-                lifetimes.push(lifetime);
+                lifetimes.push(self.expect_lifetime());
                 if seen_type || seen_binding {
                     self.span_err(self.prev_span,
                         "lifetime parameters must be declared prior to type parameters");
                 }
-            } else {if self.check_ident() && self.look_ahead(1, |t| t == &token::Eq) {
+            } else if self.check_ident() && self.look_ahead(1, |t| t == &token::Eq) {
                 // Parse associated type binding.
                 let lo = self.span.lo;
                 let ident = self.parse_ident()?;
@@ -4254,7 +4223,7 @@ fn parse_generic_args(&mut self) -> PResult<'a, (Vec<Lifetime>, Vec<P<Ty>>, Vec<
                 seen_type = true;
             } else {
                 break
-            }}
+            }
 
             if !self.eat(&token::Comma) {
                 break
@@ -4299,7 +4268,8 @@ pub fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
 
         loop {
             let lo = self.span.lo;
-            if let Some(lifetime) = self.eat_lifetime() {
+            if self.check_lifetime() && self.look_ahead(1, |t| t != &token::BinOp(token::Plus)) {
+                let lifetime = self.expect_lifetime();
                 // Bounds starting with a colon are mandatory, but possibly empty.
                 self.expect(&token::Colon)?;
                 let bounds = self.parse_lt_param_bounds();
@@ -4310,7 +4280,7 @@ pub fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
                         bounds: bounds,
                     }
                 ));
-            } else {if self.check_type() {
+            } else if self.check_type() {
                 // Parse optional `for<'a, 'b>`.
                 // This `for` is parsed greedily and applies to the whole predicate,
                 // the bounded type can have its own `for` applying only to it.
@@ -4348,7 +4318,7 @@ pub fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
                 }
             } else {
                 break
-            }}
+            }
 
             if !self.eat(&token::Comma) {
                 break
@@ -4453,13 +4423,13 @@ fn parse_self_arg(&mut self) -> PResult<'a, Option<Arg>> {
                 } else if self.look_ahead(1, |t| t.is_lifetime()) &&
                           isolated_self(self, 2) {
                     self.bump();
-                    let lt = self.eat_lifetime().expect("not a lifetime");
+                    let lt = self.expect_lifetime();
                     (SelfKind::Region(Some(lt), Mutability::Immutable), expect_ident(self))
                 } else if self.look_ahead(1, |t| t.is_lifetime()) &&
                           self.look_ahead(2, |t| t.is_keyword(keywords::Mut)) &&
                           isolated_self(self, 3) {
                     self.bump();
-                    let lt = self.eat_lifetime().expect("not a lifetime");
+                    let lt = self.expect_lifetime();
                     self.bump();
                     (SelfKind::Region(Some(lt), Mutability::Mutable), expect_ident(self))
                 } else {
@@ -4852,14 +4822,6 @@ fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> PResult<'a, ItemInfo>
         }
     }
 
-    /// Parse a::B<String,i32>
-    fn parse_trait_ref(&mut self) -> PResult<'a, TraitRef> {
-        Ok(TraitRef {
-            path: self.parse_path(PathStyle::Type)?,
-            ref_id: ast::DUMMY_NODE_ID,
-        })
-    }
-
     fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<LifetimeDef>> {
         if self.eat_keyword(keywords::For) {
             self.expect_lt()?;
@@ -4875,18 +4837,6 @@ fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<LifetimeDef>> {
         }
     }
 
-    /// Parse for<'l> a::B<String,i32>
-    fn parse_poly_trait_ref(&mut self) -> PResult<'a, PolyTraitRef> {
-        let lo = self.span.lo;
-        let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
-
-        Ok(PolyTraitRef {
-            bound_lifetimes: lifetime_defs,
-            trait_ref: self.parse_trait_ref()?,
-            span: mk_sp(lo, self.prev_span.hi),
-        })
-    }
-
     /// Parse struct Foo { ... }
     fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
         let class_name = self.parse_ident()?;
index 75852629ce131817bfd5e00f5ce3bc3398cabeb2..519d5bd98e47fff701afff2a15a139b905f0b817 100644 (file)
@@ -103,6 +103,21 @@ fn ident_can_begin_expr(ident: ast::Ident) -> bool {
     ].contains(&ident.name)
 }
 
+fn ident_can_begin_type(ident: ast::Ident) -> bool {
+    let ident_token: Token = Ident(ident);
+
+    !ident_token.is_any_keyword() ||
+    ident_token.is_path_segment_keyword() ||
+    [
+        keywords::For.name(),
+        keywords::Impl.name(),
+        keywords::Fn.name(),
+        keywords::Unsafe.name(),
+        keywords::Extern.name(),
+        keywords::Typeof.name(),
+    ].contains(&ident.name)
+}
+
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug)]
 pub enum Token {
     /* Expression-operator symbols. */
@@ -182,23 +197,21 @@ pub fn is_like_gt(&self) -> bool {
     /// Returns `true` if the token can appear at the start of an expression.
     pub fn can_begin_expr(&self) -> bool {
         match *self {
-            OpenDelim(..)               => true,
-            Ident(ident)                => ident_can_begin_expr(ident),
-            Literal(..)                 => true,
-            Not                         => true,
-            BinOp(Minus)                => true,
-            BinOp(Star)                 => true,
-            BinOp(And)                  => true,
-            BinOp(Or)                   => true, // in lambda syntax
-            OrOr                        => true, // in lambda syntax
-            AndAnd                      => true, // double borrow
+            Ident(ident)                => ident_can_begin_expr(ident), // value name or keyword
+            OpenDelim(..)               => true, // tuple, array or block
+            Literal(..)                 => true, // literal
+            Not                         => true, // operator not
+            BinOp(Minus)                => true, // unary minus
+            BinOp(Star)                 => true, // dereference
+            BinOp(Or) | OrOr            => true, // closure
+            BinOp(And)                  => true, // reference
+            AndAnd                      => true, // double reference
             DotDot | DotDotDot          => true, // range notation
             Lt | BinOp(Shl)             => true, // associated path
-            ModSep                      => true,
-            Pound                       => true, // for expression attributes
+            ModSep                      => true, // global path
+            Pound                       => true, // expression attributes
             Interpolated(ref nt) => match **nt {
                 NtExpr(..) => true,
-                NtIdent(..) => true,
                 NtBlock(..) => true,
                 NtPath(..) => true,
                 _ => false,
@@ -210,19 +223,20 @@ pub fn can_begin_expr(&self) -> bool {
     /// Returns `true` if the token can appear at the start of a type.
     pub fn can_begin_type(&self) -> bool {
         match *self {
+            Ident(ident)                => ident_can_begin_type(ident), // type name or keyword
             OpenDelim(Paren)            => true, // tuple
             OpenDelim(Bracket)          => true, // array
-            Ident(..)                   => true, // type name or keyword
             Underscore                  => true, // placeholder
             Not                         => true, // never
             BinOp(Star)                 => true, // raw pointer
             BinOp(And)                  => true, // reference
             AndAnd                      => true, // double reference
+            Question                    => true, // maybe bound in trait object
+            Lifetime(..)                => true, // lifetime bound in trait object
             Lt | BinOp(Shl)             => true, // associated path
             ModSep                      => true, // global path
             Interpolated(ref nt) => match **nt {
                 NtTy(..) => true,
-                NtIdent(..) => true,
                 NtPath(..) => true,
                 _ => false,
             },
index ffc5940c95c98c8bae7412b955d0c06545f08b3d..6527465e0b7f74631c17a159fe5ca41f289b9cbb 100644 (file)
@@ -17,15 +17,12 @@ struct Bar<'a> {
     x: &'a Foo + 'a,
     //~^ ERROR E0178
     //~| NOTE expected a path
-    //~| ERROR at least one non-builtin trait is required for an object type
     y: &'a mut Foo + 'a,
     //~^ ERROR E0178
     //~| NOTE expected a path
-    //~| ERROR at least one non-builtin trait is required for an object type
     z: fn() -> Foo + 'a,
     //~^ ERROR E0178
     //~| NOTE expected a path
-    //~| ERROR at least one non-builtin trait is required for an object type
 }
 
 fn main() {
diff --git a/src/test/compile-fail/duplicate-check-macro-exports.rs b/src/test/compile-fail/duplicate-check-macro-exports.rs
new file mode 100644 (file)
index 0000000..53d7e54
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(use_extern_macros)]
+
+pub use std::panic; //~ NOTE previous macro export here
+
+#[macro_export]
+macro_rules! panic { () => {} } //~ ERROR a macro named `panic` has already been exported
+//~| NOTE `panic` already exported
+
+fn main() {}
index aff908e58153063c82a666a7b4469379dfb5a737..95b5fabc81e4f0e2930023e38f4b2f237d098122 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 fn main () {
-    let sr: Vec<(u32, _, _) = vec![]; //~ ERROR expected one of `+`, `,`, or `>`, found `=`
+    let sr: Vec<(u32, _, _) = vec![]; //~ ERROR expected one of `,` or `>`, found `=`
     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
     //~^ ERROR cannot find value `sr` in this scope
 }
index bb212b3114d11e8a46323d5433931aebe0d6b7e9..208f1a0e2ee259403fd7c75142f2d07eacc82013 100644 (file)
@@ -11,6 +11,6 @@
 mod foo {
     type T = ();
     struct S1(pub(foo) (), pub(T), pub(crate) (), pub(((), T)));
-    struct S2(pub((foo)) ()); //~ ERROR expected one of `+` or `,`, found `(`
-                              //~| ERROR expected one of `+`, `;`, or `where`, found `(`
+    struct S2(pub((foo)) ()); //~ ERROR expected `,`, found `(`
+                              //~| ERROR expected one of `;` or `where`, found `(`
 }
index 2c6e71d7c55e6af64fed081e4eb082de602fcf4c..57769646e3b8f2de2118f7357fc13f9278df75e0 100644 (file)
@@ -12,8 +12,8 @@ macro_rules! define_struct {
     ($t:ty) => {
         struct S1(pub $t);
         struct S2(pub (foo) ());
-        struct S3(pub $t ()); //~ ERROR expected one of `+` or `,`, found `(`
-                              //~| ERROR expected one of `+`, `;`, or `where`, found `(`
+        struct S3(pub $t ()); //~ ERROR expected `,`, found `(`
+                              //~| ERROR expected one of `;` or `where`, found `(`
     }
 }
 
index e15eeae8159a363983790cfdcebc381793e75731..db3358f7d50aec95f39d29f4ff2733c4544cea6c 100644 (file)
@@ -12,8 +12,8 @@ macro_rules! define_struct {
     ($t:ty) => {
         struct S1(pub($t));
         struct S2(pub (foo) ());
-        struct S3(pub($t) ()); //~ ERROR expected one of `+` or `,`, found `(`
-                               //~| ERROR expected one of `+`, `;`, or `where`, found `(`
+        struct S3(pub($t) ()); //~ ERROR expected `,`, found `(`
+                               //~| ERROR expected one of `;` or `where`, found `(`
     }
 }
 
diff --git a/src/test/compile-fail/trait-object-macro-matcher.rs b/src/test/compile-fail/trait-object-macro-matcher.rs
new file mode 100644 (file)
index 0000000..de80b04
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// `ty` matcher accepts trait object types
+
+macro_rules! m {
+    ($t: ty) => ( let _: $t; )
+}
+
+fn main() {
+    m!(Copy + Send + 'static); //~ ERROR the trait `std::marker::Copy` cannot be made into an object
+}
index c009644c5619fe09447ba5067d2934b960ee658e..f9f887b78b0d8d1802aa0e6ac016ca1615714cee 100644 (file)
@@ -13,10 +13,9 @@ fn main() {
     //~^ ERROR expected a path
     //~| HELP try adding parentheses
     //~| SUGGESTION let _: &(Copy + 'static);
-    //~| ERROR at least one non-builtin trait is required for an object type
+    //~| ERROR the trait `std::marker::Copy` cannot be made into an object
     let _: &'static Copy + 'static;
     //~^ ERROR expected a path
     //~| HELP try adding parentheses
     //~| SUGGESTION let _: &'static (Copy + 'static);
-    //~| ERROR at least one non-builtin trait is required for an object type
 }
index cbdffb4a2554ed5e903ead9fda646788334b4403..ad59d4a52d74c44824fb4a3a7ab5d4d1e6639163 100644 (file)
@@ -10,6 +10,6 @@
 
 // compile-flags: -Z parse-only
 
-type A = Box<(Fn(D::Error) -> E) + 'static + Send + Sync>; // OK
+type A = Box<(Fn(D::Error) -> E) + 'static + Send + Sync>; // OK (but see #39318)
 
 FAIL //~ ERROR
index ae28ac76acb9827621a2453983861190cb164d81..a54d89f48c300e7dbc935762c8fb803ae9219ac8 100644 (file)
@@ -13,6 +13,6 @@
 struct Baz<U> where U: Eq(U); //This is parsed as the new Fn* style parenthesis syntax.
 struct Baz<U> where U: Eq(U) -> R; // Notice this parses as well.
 struct Baz<U>(U) where U: Eq; // This rightfully signals no error as well.
-struct Foo<T> where T: Copy, (T); //~ ERROR expected one of `+`, `:`, `==`, or `=`, found `;`
+struct Foo<T> where T: Copy, (T); //~ ERROR expected one of `:`, `==`, or `=`, found `;`
 
 fn main() {}
index ebef0e56e3e2b3862479a24bc9a77bec83ee46ef..b91ab8730b3dccfb83e4be47a47f9ed1d2bac5b3 100644 (file)
@@ -10,4 +10,4 @@
 
 // compile-flags: -Z parse-only
 
-type bptr = &lifetime/isize; //~ ERROR expected one of `!`, `(`, `+`, `::`, `;`, or `<`, found `/`
+type bptr = &lifetime/isize; //~ ERROR expected one of `!`, `(`, `::`, `;`, or `<`, found `/`
index 9bd8dc9b11b216cf9074e55b656095c23988cfd7..8a47376179dfdab0f133b97400062c00026848db 100644 (file)
@@ -10,4 +10,4 @@
 
 // compile-flags: -Z parse-only
 
-type mut_box = Box<mut isize>; //~ ERROR expected type, found keyword `mut`
+type mut_box = Box<mut isize>; //~ ERROR expected one of `>`, lifetime, or type, found `mut`
index 44bb1f930c7bdcb945ae5d6cbd348d20917f7e5e..4a2e6d5bdcd9c14f86f7293c528f39ad305128b3 100644 (file)
@@ -13,7 +13,7 @@
 use std::fmt::Debug;
 
 fn main() {
-    let x: Box<Debug+> = box 3 as Box<Debug+>;
-    //~^ ERROR at least one type parameter bound must be specified
-    //~^^ ERROR at least one type parameter bound must be specified
+    let x: Box<Debug+> = box 3 as Box<Debug+>; // Trailing `+` is OK
 }
+
+FAIL //~ ERROR
diff --git a/src/test/parse-fail/trait-object-macro-matcher.rs b/src/test/parse-fail/trait-object-macro-matcher.rs
new file mode 100644 (file)
index 0000000..3a5bce5
--- /dev/null
@@ -0,0 +1,20 @@
+// 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.
+
+// A single lifetime is not parsed as a type.
+// `ty` matcher in particular doesn't accept a single lifetime
+
+macro_rules! m {
+    ($t: ty) => ( let _: $t; )
+}
+
+fn main() {
+    m!('static); //~ ERROR expected type, found `'static`
+}
diff --git a/src/test/parse-fail/trait-object-polytrait-priority.rs b/src/test/parse-fail/trait-object-polytrait-priority.rs
new file mode 100644 (file)
index 0000000..f0abc67
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Trait<'a> {}
+
+fn main() {
+    let _: &for<'a> Trait<'a> + 'static;
+    //~^ ERROR expected a path on the left-hand side of `+`, not `& for<'a>Trait<'a>`
+    //~| NOTE expected a path
+    //~| HELP try adding parentheses
+    //~| SUGGESTION &( for<'a>Trait<'a> + 'static)
+}
index e46e4fb3766d31420f7ae1bf10bf4390b3b9f796..16856d304174999c74afe55adc2b371104fe5940 100644 (file)
@@ -34,8 +34,14 @@ pub fn plugin_registrar(reg: &mut Registry) {
     reg.register_custom_derive(
         Symbol::intern("derive_TotalSum"),
         MultiDecorator(box expand));
+
+    reg.register_custom_derive(
+        Symbol::intern("derive_Nothing"),
+        MultiDecorator(box noop));
 }
 
+fn noop(_: &mut ExtCtxt, _: Span, _: &ast::MetaItem, _: &Annotatable, _: &mut FnMut(Annotatable)) {}
+
 fn expand(cx: &mut ExtCtxt,
           span: Span,
           mitem: &ast::MetaItem,
diff --git a/src/test/run-pass-fulldeps/issue-40663.rs b/src/test/run-pass-fulldeps/issue-40663.rs
new file mode 100644 (file)
index 0000000..d030eab
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:custom_derive_plugin.rs
+
+#![feature(plugin, custom_derive)]
+#![plugin(custom_derive_plugin)]
+
+#[derive(Nothing, Nothing, Nothing)]
+struct S;
+
+fn main() {}
index ae40ce44d178da9fb8e14c561996f5f35bec7430..3165084b9e90d43795595e35fa150e05601a3c11 100644 (file)
@@ -18,7 +18,7 @@ fn test1() -> Rc<for<'a> Fn(&'a usize) + 'static> {
     }
 }
 
-fn test2() -> *mut for<'a> Fn(&'a usize) + 'static {
+fn test2() -> *mut (for<'a> Fn(&'a usize) + 'static) {
     if let Some(_) = Some(1) {
         loop{}
     } else {
@@ -27,4 +27,3 @@ fn test2() -> *mut for<'a> Fn(&'a usize) + 'static {
 }
 
 fn main() {}
-
diff --git a/src/test/run-pass/macro-nested_definition_issue-31946.rs b/src/test/run-pass/macro-nested_definition_issue-31946.rs
new file mode 100644 (file)
index 0000000..84ff2dc
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+fn main() {
+    println!("{}", {
+        macro_rules! foo {
+            ($name:expr) => { concat!("hello ", $name) }
+        }
+        foo!("rust")
+    });
+}