# *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
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
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
# 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%
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.
///
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()
#![deny(warnings)]
#![feature(rand)]
+#![feature(sort_unstable)]
#![feature(test)]
extern crate test;
}
})
}
+
#[bench]
fn random_removes(b: &mut Bencher) {
let mut rng = thread_rng();
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);
#![feature(shared)]
#![feature(slice_get_slice)]
#![feature(slice_patterns)]
+#![cfg_attr(not(test), feature(sort_unstable))]
#![feature(specialization)]
#![feature(staged_api)]
#![feature(str_internals)]
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.
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`.
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);
// 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);
}
}
}
- // 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();
}
}
-#[test]
-fn test_sort_zero_sized_type() {
- // Should not panic.
- [(); 10].sort();
- [(); 100].sort();
-}
-
#[test]
fn test_concat() {
let v: [Vec<i32>; 0] = [];
#![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)]
+++ /dev/null
-// 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 }
-}
--- /dev/null
+// 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 }
+}
--- /dev/null
+// 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);
+}
#![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;
// 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() {
assert_eq!(c2.last().unwrap()[0], 4);
}
-
-
-
#[test]
fn test_windows_count() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
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]);
+}
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)]
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 {
},
ext.kind()
);
- callback(def::Export { name: name, def: def });
+ callback(def::Export { name: name, def: def, span: DUMMY_SP });
}
}
return
callback(def::Export {
def: def,
name: self.item_name(child_index),
+ span: self.entry(child_index).span.decode(self),
});
}
}
}
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 {
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) => {
// 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 });
}
_ => {}
}
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");
}
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);
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 });
}
}
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};
*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);
}
}
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 });
}
}
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;
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,
}
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()?),
})
}
}
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> {
},
"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) => {
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;
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> {
}
}
- /// 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.
/// `+` 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) {
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 }));
}
}
}
- /// 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
}
}
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();
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();
} 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();
}
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;
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)));
}
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
// 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
}
}
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
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()
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;
&format!("trailing attribute after {} parameters", param_kind));
}
break
- }}
+ }
if !self.eat(&token::Comma) {
break
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()?;
seen_type = true;
} else {
break
- }}
+ }
if !self.eat(&token::Comma) {
break
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();
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.
}
} else {
break
- }}
+ }
if !self.eat(&token::Comma) {
break
} 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 {
}
}
- /// 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()?;
}
}
- /// 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()?;
].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. */
/// 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,
/// 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,
},
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() {
--- /dev/null
+// 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() {}
// 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
}
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 `(`
}
($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 `(`
}
}
($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 `(`
}
}
--- /dev/null
+// 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
+}
//~^ 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
}
// 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
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() {}
// 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 `/`
// 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`
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
--- /dev/null
+// 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`
+}
--- /dev/null
+// 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)
+}
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,
--- /dev/null
+// 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() {}
}
}
-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 {
}
fn main() {}
-
--- /dev/null
+// 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")
+ });
+}