From 5a97036b6900ee208f90c52ceadcce606d497e93 Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Sat, 20 May 2017 15:40:53 -0400 Subject: Convert Intos to Froms. --- src/liballoc/string.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/liballoc') diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 2cb81029f95..c1ef1c2f96c 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -2009,9 +2009,9 @@ impl From> for String { } #[stable(feature = "box_from_str", since = "1.18.0")] -impl Into> for String { - fn into(self) -> Box { - self.into_boxed_str() +impl From for Box { + fn from(s: String) -> Box { + s.into_boxed_str() } } -- cgit 1.4.1-3-g733a5 From 0d885efe16899c2dbad2918345c9ede7b83caa7f Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Tue, 13 Jun 2017 00:08:37 +0100 Subject: Update version numbers for From impls --- src/liballoc/string.rs | 2 +- src/libstd/ffi/c_str.rs | 2 +- src/libstd/ffi/os_str.rs | 2 +- src/libstd/path.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/liballoc') diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index c1ef1c2f96c..02ecb65fa38 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -2008,7 +2008,7 @@ impl From> for String { } } -#[stable(feature = "box_from_str", since = "1.18.0")] +#[stable(feature = "box_from_str", since = "1.20.0")] impl From for Box { fn from(s: String) -> Box { s.into_boxed_str() diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 1586e0a4ddb..5f0b11a616e 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -585,7 +585,7 @@ impl From> for CString { } } -#[stable(feature = "box_from_c_string", since = "1.18.0")] +#[stable(feature = "box_from_c_string", since = "1.20.0")] impl From for Box { #[inline] fn from(s: CString) -> Box { diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 3815f986681..3232a51546e 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -542,7 +542,7 @@ impl From> for OsString { } } -#[stable(feature = "box_from_os_string", since = "1.18.0")] +#[stable(feature = "box_from_os_string", since = "1.20.0")] impl From for Box { fn from(s: OsString) -> Box { s.into_boxed_os_str() diff --git a/src/libstd/path.rs b/src/libstd/path.rs index e9bf7b33b8e..7a8c8935394 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1348,7 +1348,7 @@ impl From> for PathBuf { } } -#[stable(feature = "box_from_path_buf", since = "1.18.0")] +#[stable(feature = "box_from_path_buf", since = "1.20.0")] impl From for Box { fn from(p: PathBuf) -> Box { p.into_boxed_path() -- cgit 1.4.1-3-g733a5 From c5d078fd8cf554aa1ee6e6b3a0d670ca9afa4054 Mon Sep 17 00:00:00 2001 From: Ryan Thomas Date: Thu, 22 Jun 2017 20:02:57 +0100 Subject: Update docs for std::fmt::format #29355. This rewords and removes the `Arguments` section from the docs for fmt::format. r? @steveklabnik --- src/liballoc/fmt.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src/liballoc') diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index 62a88164621..3afce884b11 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -498,12 +498,10 @@ pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; use string; -/// The format function takes a precompiled format string and a list of -/// arguments, to return the resulting formatted string. +/// The `format` function takes an `Arguments` struct and returns the resulting +/// formatted string. /// -/// # Arguments -/// -/// * args - a structure of arguments generated via the `format_args!` macro. +/// The `Arguments` instance can be created with the `format_args!` macro. /// /// # Examples /// -- cgit 1.4.1-3-g733a5 From 12205f1450f390f10602a19a4e40b6d8f26857e4 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Sat, 24 Jun 2017 16:51:16 +0200 Subject: Improve sort tests and benchmarks --- src/liballoc/benches/lib.rs | 1 + src/liballoc/benches/slice.rs | 54 +++++---- src/liballoc/slice.rs | 4 +- src/liballoc/tests/slice.rs | 50 +++++++-- src/test/run-pass/vector-sort-panic-safe.rs | 167 +++++++++++++++++----------- 5 files changed, 180 insertions(+), 96 deletions(-) (limited to 'src/liballoc') diff --git a/src/liballoc/benches/lib.rs b/src/liballoc/benches/lib.rs index 958020d0b0e..5f274eec87d 100644 --- a/src/liballoc/benches/lib.rs +++ b/src/liballoc/benches/lib.rs @@ -17,6 +17,7 @@ #![feature(sort_unstable)] #![feature(test)] +extern crate rand; extern crate test; mod btree; diff --git a/src/liballoc/benches/slice.rs b/src/liballoc/benches/slice.rs index aa5a438b35e..d99270e7f31 100644 --- a/src/liballoc/benches/slice.rs +++ b/src/liballoc/benches/slice.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::{mem, ptr}; -use std::__rand::{Rng, thread_rng}; +use std::__rand::{thread_rng}; +use std::mem; +use std::ptr; +use rand::{Rng, SeedableRng, XorShiftRng}; use test::{Bencher, black_box}; #[bench] @@ -191,17 +193,17 @@ fn gen_descending(len: usize) -> Vec { } fn gen_random(len: usize) -> Vec { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); rng.gen_iter::().take(len).collect() } fn gen_random_bytes(len: usize) -> Vec { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); rng.gen_iter::().take(len).collect() } fn gen_mostly_ascending(len: usize) -> Vec { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); let mut v = gen_ascending(len); for _ in (0usize..).take_while(|x| x * x <= len) { let x = rng.gen::() % len; @@ -212,7 +214,7 @@ fn gen_mostly_ascending(len: usize) -> Vec { } fn gen_mostly_descending(len: usize) -> Vec { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); let mut v = gen_descending(len); for _ in (0usize..).take_while(|x| x * x <= len) { let x = rng.gen::() % len; @@ -223,7 +225,7 @@ fn gen_mostly_descending(len: usize) -> Vec { } fn gen_strings(len: usize) -> Vec { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); let mut v = vec![]; for _ in 0..len { let n = rng.gen::() % 20 + 1; @@ -233,7 +235,7 @@ fn gen_strings(len: usize) -> Vec { } fn gen_big_random(len: usize) -> Vec<[u64; 16]> { - let mut rng = thread_rng(); + let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); rng.gen_iter().map(|x| [x; 16]).take(len).collect() } @@ -241,18 +243,32 @@ macro_rules! sort { ($f:ident, $name:ident, $gen:expr, $len:expr) => { #[bench] fn $name(b: &mut Bencher) { - b.iter(|| $gen($len).$f()); + let v = $gen($len); + b.iter(|| v.clone().$f()); b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64; } } } +macro_rules! sort_strings { + ($f:ident, $name:ident, $gen:expr, $len:expr) => { + #[bench] + fn $name(b: &mut Bencher) { + let v = $gen($len); + let v = v.iter().map(|s| &**s).collect::>(); + b.iter(|| v.clone().$f()); + b.bytes = $len * mem::size_of::<&str>() as u64; + } + } +} + macro_rules! sort_expensive { ($f:ident, $name:ident, $gen:expr, $len:expr) => { #[bench] fn $name(b: &mut Bencher) { + let v = $gen($len); b.iter(|| { - let mut v = $gen($len); + let mut v = v.clone(); let mut count = 0; v.$f(|a: &u64, b: &u64| { count += 1; @@ -263,7 +279,7 @@ macro_rules! sort_expensive { }); black_box(count); }); - b.bytes = $len as u64 * mem::size_of::() as u64; + b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64; } } } @@ -271,30 +287,30 @@ macro_rules! sort_expensive { 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_small_big, 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, sort_large_big, gen_big_random, 10000); +sort_strings!(sort, sort_large_strings, gen_strings, 10000); +sort_expensive!(sort_by, sort_large_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_small_big, 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); +sort!(sort_unstable, sort_unstable_large_big, gen_big_random, 10000); +sort_strings!(sort_unstable, sort_unstable_large_strings, gen_strings, 10000); +sort_expensive!(sort_unstable_by, sort_unstable_large_expensive, gen_random, 10000); macro_rules! reverse { ($name:ident, $ty:ty, $f:expr) => { diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 88876999d76..fe8893904eb 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -1794,7 +1794,7 @@ unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F) impl Drop for MergeHole { fn drop(&mut self) { - // `T` is not a zero-sized type, so it's okay to divide by it's size. + // `T` is not a zero-sized type, so it's okay to divide by its size. let len = (self.end as usize - self.start as usize) / mem::size_of::(); unsafe { ptr::copy_nonoverlapping(self.start, self.dest, len); } } @@ -1908,7 +1908,7 @@ fn merge_sort(v: &mut [T], mut is_less: F) // if `Some(r)` is returned, that means `runs[r]` and `runs[r + 1]` must be merged next. If the // algorithm should continue building a new run instead, `None` is returned. // - // TimSort is infamous for it's buggy implementations, as described here: + // TimSort is infamous for its buggy implementations, as described here: // http://envisage-project.eu/timsort-specification-and-verification/ // // The gist of the story is: we must enforce the invariants on the top four runs on the stack. diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs index 7fa65a2144e..c53bf15f1bf 100644 --- a/src/liballoc/tests/slice.rs +++ b/src/liballoc/tests/slice.rs @@ -396,18 +396,44 @@ fn test_sort() { let mut rng = thread_rng(); for len in (2..25).chain(500..510) { - for _ in 0..100 { - let mut v: Vec<_> = rng.gen_iter::().take(len).collect(); - let mut v1 = v.clone(); - - v.sort(); - assert!(v.windows(2).all(|w| w[0] <= w[1])); - - v1.sort_by(|a, b| a.cmp(b)); - assert!(v1.windows(2).all(|w| w[0] <= w[1])); - - v1.sort_by(|a, b| b.cmp(a)); - assert!(v1.windows(2).all(|w| w[0] >= w[1])); + for &modulus in &[5, 10, 100, 1000] { + for _ in 0..10 { + let orig: Vec<_> = rng.gen_iter::() + .map(|x| x % modulus) + .take(len) + .collect(); + + // Sort in default order. + let mut v = orig.clone(); + v.sort(); + assert!(v.windows(2).all(|w| w[0] <= w[1])); + + // Sort in ascending order. + let mut v = orig.clone(); + v.sort_by(|a, b| a.cmp(b)); + assert!(v.windows(2).all(|w| w[0] <= w[1])); + + // Sort in descending order. + let mut v = orig.clone(); + v.sort_by(|a, b| b.cmp(a)); + assert!(v.windows(2).all(|w| w[0] >= w[1])); + + // Sort with many pre-sorted runs. + let mut v = orig.clone(); + v.sort(); + v.reverse(); + for _ in 0..5 { + let a = rng.gen::() % len; + let b = rng.gen::() % len; + if a < b { + v[a..b].reverse(); + } else { + v.swap(a, b); + } + } + v.sort(); + assert!(v.windows(2).all(|w| w[0] <= w[1])); + } } } diff --git a/src/test/run-pass/vector-sort-panic-safe.rs b/src/test/run-pass/vector-sort-panic-safe.rs index 8ad6ca0abb0..3458199bdaf 100644 --- a/src/test/run-pass/vector-sort-panic-safe.rs +++ b/src/test/run-pass/vector-sort-panic-safe.rs @@ -10,14 +10,17 @@ // ignore-emscripten no threads support -#![feature(rand)] #![feature(const_fn)] +#![feature(rand)] +#![feature(sort_unstable)] use std::__rand::{thread_rng, Rng}; +use std::cell::Cell; +use std::cmp::Ordering; use std::panic; -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize}; +use std::sync::atomic::Ordering::Relaxed; use std::thread; -use std::cell::Cell; const MAX_LEN: usize = 80; @@ -45,54 +48,85 @@ static DROP_COUNTS: [AtomicUsize; MAX_LEN] = [ AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), ]; -#[derive(Clone, PartialEq, PartialOrd, Eq, Ord)] +static VERSIONS: AtomicUsize = ATOMIC_USIZE_INIT; + +#[derive(Clone, Eq)] struct DropCounter { x: u32, id: usize, + version: Cell, +} + +impl PartialEq for DropCounter { + fn eq(&self, other: &Self) -> bool { + self.partial_cmp(other) == Some(Ordering::Equal) + } +} + +impl PartialOrd for DropCounter { + fn partial_cmp(&self, other: &Self) -> Option { + self.version.set(self.version.get() + 1); + other.version.set(other.version.get() + 1); + VERSIONS.fetch_add(2, Relaxed); + self.x.partial_cmp(&other.x) + } +} + +impl Ord for DropCounter { + fn cmp(&self, other: &Self) -> Ordering { + self.partial_cmp(other).unwrap() + } } impl Drop for DropCounter { fn drop(&mut self) { - DROP_COUNTS[self.id].fetch_add(1, Ordering::Relaxed); + DROP_COUNTS[self.id].fetch_add(1, Relaxed); + VERSIONS.fetch_sub(self.version.get(), Relaxed); } } -fn test(input: &[DropCounter]) { - let len = input.len(); +macro_rules! test { + ($input:ident, $func:ident) => { + let len = $input.len(); + + // Work out the total number of comparisons required to sort + // this array... + let mut count = 0usize; + $input.to_owned().$func(|a, b| { count += 1; a.cmp(b) }); + + // ... and then panic on each and every single one. + for panic_countdown in 0..count { + // Refresh the counters. + VERSIONS.store(0, Relaxed); + for i in 0..len { + DROP_COUNTS[i].store(0, Relaxed); + } - // Work out the total number of comparisons required to sort - // this array... - let mut count = 0usize; - input.to_owned().sort_by(|a, b| { count += 1; a.cmp(b) }); + let v = $input.to_owned(); + let _ = thread::spawn(move || { + let mut v = v; + let mut panic_countdown = panic_countdown; + v.$func(|a, b| { + if panic_countdown == 0 { + SILENCE_PANIC.with(|s| s.set(true)); + panic!(); + } + panic_countdown -= 1; + a.cmp(b) + }) + }).join(); + + // Check that the number of things dropped is exactly + // what we expect (i.e. the contents of `v`). + for (i, c) in DROP_COUNTS.iter().enumerate().take(len) { + let count = c.load(Relaxed); + assert!(count == 1, + "found drop count == {} for i == {}, len == {}", + count, i, len); + } - // ... and then panic on each and every single one. - for panic_countdown in 0..count { - // Refresh the counters. - for i in 0..len { - DROP_COUNTS[i].store(0, Ordering::Relaxed); - } - - let v = input.to_owned(); - let _ = thread::spawn(move || { - let mut v = v; - let mut panic_countdown = panic_countdown; - v.sort_by(|a, b| { - if panic_countdown == 0 { - SILENCE_PANIC.with(|s| s.set(true)); - panic!(); - } - panic_countdown -= 1; - a.cmp(b) - }) - }).join(); - - // Check that the number of things dropped is exactly - // what we expect (i.e. the contents of `v`). - for (i, c) in DROP_COUNTS.iter().enumerate().take(len) { - let count = c.load(Ordering::Relaxed); - assert!(count == 1, - "found drop count == {} for i == {}, len == {}", - count, i, len); + // Check that the most recent versions of values were dropped. + assert_eq!(VERSIONS.load(Relaxed), 0); } } } @@ -106,33 +140,40 @@ fn main() { prev(info); } })); + for len in (1..20).chain(70..MAX_LEN) { - // Test on a random array. - let mut rng = thread_rng(); - let input = (0..len).map(|id| { - DropCounter { - x: rng.next_u32(), - id: id, - } - }).collect::>(); - test(&input); - - // Test on a sorted array with two elements randomly swapped, creating several natural - // runs of random lengths. Such arrays have very high chances of hitting all code paths in - // the merge procedure. - for _ in 0..5 { - let mut input = (0..len).map(|i| - DropCounter { - x: i as u32, - id: i, + for &modulus in &[5, 20, 50] { + for &has_runs in &[false, true] { + let mut rng = thread_rng(); + let mut input = (0..len) + .map(|id| { + DropCounter { + x: rng.next_u32() % modulus, + id: id, + version: Cell::new(0), + } + }) + .collect::>(); + + if has_runs { + for c in &mut input { + c.x = c.id as u32; + } + + for _ in 0..5 { + let a = rng.gen::() % len; + let b = rng.gen::() % len; + if a < b { + input[a..b].reverse(); + } else { + input.swap(a, b); + } + } } - ).collect::>(); - let a = rng.gen::() % len; - let b = rng.gen::() % len; - input.swap(a, b); - - test(&input); + test!(input, sort_by); + test!(input, sort_unstable_by); + } } } } -- cgit 1.4.1-3-g733a5 From 143206d54d7558c2326212df99efc98110904fdb Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 18 Jun 2017 22:01:29 -0700 Subject: Stabilize RangeArgument Move it and Bound to core::ops while we're at it. Closes #30877 --- src/liballoc/btree/map.rs | 5 +- src/liballoc/btree/set.rs | 3 +- src/liballoc/lib.rs | 51 +------- src/liballoc/range.rs | 138 +------------------- src/liballoc/string.rs | 5 +- src/liballoc/vec.rs | 5 +- src/liballoc/vec_deque.rs | 5 +- src/libcollections/lib.rs | 1 + src/libcore/ops/mod.rs | 3 + src/libcore/ops/range.rs | 174 +++++++++++++++++++++++-- src/librustc_data_structures/accumulate_vec.rs | 3 +- src/librustc_data_structures/array_vec.rs | 5 +- src/librustc_data_structures/indexed_vec.rs | 3 +- src/librustc_data_structures/lib.rs | 1 - src/libstd/collections/mod.rs | 2 + 15 files changed, 187 insertions(+), 217 deletions(-) (limited to 'src/liballoc') diff --git a/src/liballoc/btree/map.rs b/src/liballoc/btree/map.rs index a51c70159db..5243fb6ae0e 100644 --- a/src/liballoc/btree/map.rs +++ b/src/liballoc/btree/map.rs @@ -13,12 +13,11 @@ use core::fmt::Debug; use core::hash::{Hash, Hasher}; use core::iter::{FromIterator, Peekable, FusedIterator}; use core::marker::PhantomData; -use core::ops::Index; +use core::ops::{Index, RangeArgument}; +use core::ops::Bound::{Excluded, Included, Unbounded}; use core::{fmt, intrinsics, mem, ptr}; use borrow::Borrow; -use Bound::{Excluded, Included, Unbounded}; -use range::RangeArgument; use super::node::{self, Handle, NodeRef, marker}; use super::search; diff --git a/src/liballoc/btree/set.rs b/src/liballoc/btree/set.rs index d32460da939..c755d2d8b85 100644 --- a/src/liballoc/btree/set.rs +++ b/src/liballoc/btree/set.rs @@ -16,12 +16,11 @@ use core::cmp::{min, max}; use core::fmt::Debug; use core::fmt; use core::iter::{Peekable, FromIterator, FusedIterator}; -use core::ops::{BitOr, BitAnd, BitXor, Sub}; +use core::ops::{BitOr, BitAnd, BitXor, Sub, RangeArgument}; use borrow::Borrow; use btree_map::{BTreeMap, Keys}; use super::Recover; -use range::RangeArgument; // FIXME(conventions): implement bounded iterators diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index ca52943ea97..6f4e300fd3c 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -203,56 +203,7 @@ mod std { pub use core::ops; // RangeFull } -/// An endpoint of a range of keys. -/// -/// # Examples -/// -/// `Bound`s are range endpoints: -/// -/// ``` -/// #![feature(collections_range)] -/// -/// use std::collections::range::RangeArgument; -/// use std::collections::Bound::*; -/// -/// assert_eq!((..100).start(), Unbounded); -/// assert_eq!((1..12).start(), Included(&1)); -/// assert_eq!((1..12).end(), Excluded(&12)); -/// ``` -/// -/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`]. -/// Note that in most cases, it's better to use range syntax (`1..5`) instead. -/// -/// ``` -/// use std::collections::BTreeMap; -/// use std::collections::Bound::{Excluded, Included, Unbounded}; -/// -/// let mut map = BTreeMap::new(); -/// map.insert(3, "a"); -/// map.insert(5, "b"); -/// map.insert(8, "c"); -/// -/// for (key, value) in map.range((Excluded(3), Included(8))) { -/// println!("{}: {}", key, value); -/// } -/// -/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next()); -/// ``` -/// -/// [`BTreeMap::range`]: btree_map/struct.BTreeMap.html#method.range -#[stable(feature = "collections_bound", since = "1.17.0")] -#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] -pub enum Bound { - /// An inclusive bound. - #[stable(feature = "collections_bound", since = "1.17.0")] - Included(T), - /// An exclusive bound. - #[stable(feature = "collections_bound", since = "1.17.0")] - Excluded(T), - /// An infinite endpoint. Indicates that there is no bound in this direction. - #[stable(feature = "collections_bound", since = "1.17.0")] - Unbounded, -} +pub use core::ops::Bound; /// An intermediate trait for specialization of `Extend`. #[doc(hidden)] diff --git a/src/liballoc/range.rs b/src/liballoc/range.rs index f862da0d61e..0a058c47a50 100644 --- a/src/liballoc/range.rs +++ b/src/liballoc/range.rs @@ -11,142 +11,8 @@ #![unstable(feature = "collections_range", reason = "waiting for dust to settle on inclusive ranges", issue = "30877")] +#![rustc_deprecated(reason = "moved to core::ops", since = "1.19.0")] //! Range syntax. -use core::ops::{RangeFull, Range, RangeTo, RangeFrom, RangeInclusive, RangeToInclusive}; -use Bound::{self, Excluded, Included, Unbounded}; - -/// `RangeArgument` is implemented by Rust's built-in range types, produced -/// by range syntax like `..`, `a..`, `..b` or `c..d`. -pub trait RangeArgument { - /// Start index bound. - /// - /// Returns the start value as a `Bound`. - /// - /// # Examples - /// - /// ``` - /// #![feature(alloc)] - /// #![feature(collections_range)] - /// - /// extern crate alloc; - /// - /// # fn main() { - /// use alloc::range::RangeArgument; - /// use alloc::Bound::*; - /// - /// assert_eq!((..10).start(), Unbounded); - /// assert_eq!((3..10).start(), Included(&3)); - /// # } - /// ``` - fn start(&self) -> Bound<&T>; - - /// End index bound. - /// - /// Returns the end value as a `Bound`. - /// - /// # Examples - /// - /// ``` - /// #![feature(alloc)] - /// #![feature(collections_range)] - /// - /// extern crate alloc; - /// - /// # fn main() { - /// use alloc::range::RangeArgument; - /// use alloc::Bound::*; - /// - /// assert_eq!((3..).end(), Unbounded); - /// assert_eq!((3..10).end(), Excluded(&10)); - /// # } - /// ``` - fn end(&self) -> Bound<&T>; -} - -// FIXME add inclusive ranges to RangeArgument - -impl RangeArgument for RangeFull { - fn start(&self) -> Bound<&T> { - Unbounded - } - fn end(&self) -> Bound<&T> { - Unbounded - } -} - -impl RangeArgument for RangeFrom { - fn start(&self) -> Bound<&T> { - Included(&self.start) - } - fn end(&self) -> Bound<&T> { - Unbounded - } -} - -impl RangeArgument for RangeTo { - fn start(&self) -> Bound<&T> { - Unbounded - } - fn end(&self) -> Bound<&T> { - Excluded(&self.end) - } -} - -impl RangeArgument for Range { - fn start(&self) -> Bound<&T> { - Included(&self.start) - } - fn end(&self) -> Bound<&T> { - Excluded(&self.end) - } -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl RangeArgument for RangeInclusive { - fn start(&self) -> Bound<&T> { - Included(&self.start) - } - fn end(&self) -> Bound<&T> { - Included(&self.end) - } -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl RangeArgument for RangeToInclusive { - fn start(&self) -> Bound<&T> { - Unbounded - } - fn end(&self) -> Bound<&T> { - Included(&self.end) - } -} - -impl RangeArgument for (Bound, Bound) { - fn start(&self) -> Bound<&T> { - match *self { - (Included(ref start), _) => Included(start), - (Excluded(ref start), _) => Excluded(start), - (Unbounded, _) => Unbounded, - } - } - - fn end(&self) -> Bound<&T> { - match *self { - (_, Included(ref end)) => Included(end), - (_, Excluded(ref end)) => Excluded(end), - (_, Unbounded) => Unbounded, - } - } -} - -impl<'a, T: ?Sized + 'a> RangeArgument for (Bound<&'a T>, Bound<&'a T>) { - fn start(&self) -> Bound<&T> { - self.0 - } - - fn end(&self) -> Bound<&T> { - self.1 - } -} +pub use core::ops::RangeArgument; diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 79d1ccf637d..1f0894d39d4 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -59,15 +59,14 @@ use core::fmt; use core::hash; use core::iter::{FromIterator, FusedIterator}; -use core::ops::{self, Add, AddAssign, Index, IndexMut}; +use core::ops::{self, Add, AddAssign, Index, IndexMut, RangeArgument}; +use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ptr; use core::str::pattern::Pattern; use std_unicode::lossy; use std_unicode::char::{decode_utf16, REPLACEMENT_CHARACTER}; use borrow::{Cow, ToOwned}; -use range::RangeArgument; -use Bound::{Excluded, Included, Unbounded}; use str::{self, from_boxed_utf8_unchecked, FromStr, Utf8Error, Chars}; use vec::Vec; use boxed::Box; diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 5d1999a4262..e118d406ecf 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -74,7 +74,8 @@ use core::iter::{FromIterator, FusedIterator, TrustedLen}; use core::mem; #[cfg(not(test))] use core::num::Float; -use core::ops::{InPlace, Index, IndexMut, Place, Placer}; +use core::ops::{InPlace, Index, IndexMut, Place, Placer, RangeArgument}; +use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ops; use core::ptr; use core::ptr::Shared; @@ -84,8 +85,6 @@ use borrow::ToOwned; use borrow::Cow; use boxed::Box; use raw_vec::RawVec; -use super::range::RangeArgument; -use Bound::{Excluded, Included, Unbounded}; /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs index 18175a5d01b..d1d334267bc 100644 --- a/src/liballoc/vec_deque.rs +++ b/src/liballoc/vec_deque.rs @@ -21,7 +21,8 @@ use core::cmp::Ordering; use core::fmt; use core::iter::{repeat, FromIterator, FusedIterator}; use core::mem; -use core::ops::{Index, IndexMut, Place, Placer, InPlace}; +use core::ops::{Index, IndexMut, Place, Placer, InPlace, RangeArgument}; +use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ptr; use core::ptr::Shared; use core::slice; @@ -31,8 +32,6 @@ use core::cmp; use raw_vec::RawVec; -use super::range::RangeArgument; -use Bound::{Excluded, Included, Unbounded}; use super::vec::Vec; const INITIAL_CAPACITY: usize = 7; // 2^3 - 1 diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index de5d6df328c..0a939831622 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -46,6 +46,7 @@ pub use alloc::binary_heap; pub use alloc::borrow; pub use alloc::fmt; pub use alloc::linked_list; +#[allow(deprecated)] pub use alloc::range; pub use alloc::slice; pub use alloc::str; diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index a78f4fe28a6..34f00850579 100644 --- a/src/libcore/ops/mod.rs +++ b/src/libcore/ops/mod.rs @@ -183,6 +183,9 @@ pub use self::index::{Index, IndexMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; +#[stable(feature = "range_argument", since = "1.19.0")] +pub use self::range::{RangeArgument, Bound}; + #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub use self::range::{RangeInclusive, RangeToInclusive}; diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 33258b7a875..65e09da4fff 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -9,6 +9,7 @@ // except according to those terms. use fmt; +use ops::Bound::{Included, Excluded, Unbounded}; /// An unbounded range. Use `..` (two dots) for its shorthand. /// @@ -71,7 +72,8 @@ impl fmt::Debug for RangeFull { /// assert_eq!(arr[1..3], [ 1,2 ]); // Range /// } /// ``` -#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[derive(Clone, PartialEq, Eq, Hash)] +// not Copy -- see #27186 #[stable(feature = "rust1", since = "1.0.0")] pub struct Range { /// The lower bound of the range (inclusive). @@ -134,7 +136,8 @@ impl> Range { /// assert_eq!(arr[1..3], [ 1,2 ]); /// } /// ``` -#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[derive(Clone, PartialEq, Eq, Hash)] +// not Copy -- see #27186 #[stable(feature = "rust1", since = "1.0.0")] pub struct RangeFrom { /// The lower bound of the range (inclusive). @@ -250,17 +253,16 @@ impl> RangeTo { /// assert_eq!(arr[1...2], [ 1,2 ]); // RangeInclusive /// } /// ``` -#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[derive(Clone, PartialEq, Eq, Hash)] +// not Copy -- see #27186 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub struct RangeInclusive { /// The lower bound of the range (inclusive). - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", + #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub start: Idx, /// The upper bound of the range (inclusive). - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", + #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub end: Idx, } @@ -333,8 +335,7 @@ impl> RangeInclusive { #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub struct RangeToInclusive { /// The upper bound of the range (inclusive) - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", + #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub end: Idx, } @@ -365,3 +366,158 @@ impl> RangeToInclusive { // RangeToInclusive cannot impl From> // because underflow would be possible with (..0).into() + +/// `RangeArgument` is implemented by Rust's built-in range types, produced +/// by range syntax like `..`, `a..`, `..b` or `c..d`. +#[stable(feature = "range_argument", since = "1.19.0")] +pub trait RangeArgument { + /// Start index bound. + /// + /// Returns the start value as a `Bound`. + /// + /// # Examples + /// + /// ``` + /// use std::ops::RangeArgument; + /// use std::ops::Bound::*; + /// + /// assert_eq!((..10).start(), Unbounded); + /// assert_eq!((3..10).start(), Included(&3)); + /// ``` + #[stable(feature = "range_argument", since = "1.19.0")] + fn start(&self) -> Bound<&T>; + + /// End index bound. + /// + /// Returns the end value as a `Bound`. + /// + /// # Examples + /// + /// ``` + /// use std::ops::RangeArgument; + /// use std::ops::Bound::*; + /// + /// assert_eq!((3..).end(), Unbounded); + /// assert_eq!((3..10).end(), Excluded(&10)); + /// ``` + #[stable(feature = "range_argument", since = "1.19.0")] + fn end(&self) -> Bound<&T>; +} + +#[stable(feature = "range_argument", since = "1.19.0")] +impl RangeArgument for RangeFull { + fn start(&self) -> Bound<&T> { + Unbounded + } + fn end(&self) -> Bound<&T> { + Unbounded + } +} + +#[stable(feature = "range_argument", since = "1.19.0")] +impl RangeArgument for RangeFrom { + fn start(&self) -> Bound<&T> { + Included(&self.start) + } + fn end(&self) -> Bound<&T> { + Unbounded + } +} + +#[stable(feature = "range_argument", since = "1.19.0")] +impl RangeArgument for RangeTo { + fn start(&self) -> Bound<&T> { + Unbounded + } + fn end(&self) -> Bound<&T> { + Excluded(&self.end) + } +} + +#[stable(feature = "range_argument", since = "1.19.0")] +impl RangeArgument for Range { + fn start(&self) -> Bound<&T> { + Included(&self.start) + } + fn end(&self) -> Bound<&T> { + Excluded(&self.end) + } +} + +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +impl RangeArgument for RangeInclusive { + fn start(&self) -> Bound<&T> { + Included(&self.start) + } + fn end(&self) -> Bound<&T> { + Included(&self.end) + } +} + +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +impl RangeArgument for RangeToInclusive { + fn start(&self) -> Bound<&T> { + Unbounded + } + fn end(&self) -> Bound<&T> { + Included(&self.end) + } +} + +#[stable(feature = "range_argument", since = "1.19.0")] +impl RangeArgument for (Bound, Bound) { + fn start(&self) -> Bound<&T> { + match *self { + (Included(ref start), _) => Included(start), + (Excluded(ref start), _) => Excluded(start), + (Unbounded, _) => Unbounded, + } + } + + fn end(&self) -> Bound<&T> { + match *self { + (_, Included(ref end)) => Included(end), + (_, Excluded(ref end)) => Excluded(end), + (_, Unbounded) => Unbounded, + } + } +} + +#[stable(feature = "range_argument", since = "1.19.0")] +impl<'a, T: ?Sized + 'a> RangeArgument for (Bound<&'a T>, Bound<&'a T>) { + fn start(&self) -> Bound<&T> { + self.0 + } + + fn end(&self) -> Bound<&T> { + self.1 + } +} + +/// An endpoint of a range of keys. +/// +/// # Examples +/// +/// `Bound`s are range endpoints: +/// +/// ``` +/// use std::ops::RangeArgument; +/// use std::ops::Bound::*; +/// +/// assert_eq!((..100).start(), Unbounded); +/// assert_eq!((1..12).start(), Included(&1)); +/// assert_eq!((1..12).end(), Excluded(&12)); +/// ``` +#[stable(feature = "collections_bound", since = "1.17.0")] +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub enum Bound { + /// An inclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Included(T), + /// An exclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Excluded(T), + /// An infinite endpoint. Indicates that there is no bound in this direction. + #[stable(feature = "collections_bound", since = "1.17.0")] + Unbounded, +} diff --git a/src/librustc_data_structures/accumulate_vec.rs b/src/librustc_data_structures/accumulate_vec.rs index c03c2890ba3..eacd394ad5e 100644 --- a/src/librustc_data_structures/accumulate_vec.rs +++ b/src/librustc_data_structures/accumulate_vec.rs @@ -15,11 +15,10 @@ //! //! The N above is determined by Array's implementor, by way of an associatated constant. -use std::ops::{Deref, DerefMut}; +use std::ops::{Deref, DerefMut, RangeArgument}; use std::iter::{self, IntoIterator, FromIterator}; use std::slice; use std::vec; -use std::collections::range::RangeArgument; use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; diff --git a/src/librustc_data_structures/array_vec.rs b/src/librustc_data_structures/array_vec.rs index 078bb801751..a9abdf1377e 100644 --- a/src/librustc_data_structures/array_vec.rs +++ b/src/librustc_data_structures/array_vec.rs @@ -13,13 +13,12 @@ use std::marker::Unsize; use std::iter::Extend; use std::ptr::{self, drop_in_place, Shared}; -use std::ops::{Deref, DerefMut, Range}; +use std::ops::{Deref, DerefMut, Range, RangeArgument}; +use std::ops::Bound::{Excluded, Included, Unbounded}; use std::hash::{Hash, Hasher}; use std::slice; use std::fmt; use std::mem; -use std::collections::range::RangeArgument; -use std::collections::Bound::{Excluded, Included, Unbounded}; use std::mem::ManuallyDrop; pub unsafe trait Array { diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 29ac650aa70..3bf926fa8bf 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -8,12 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::collections::range::RangeArgument; use std::fmt::Debug; use std::iter::{self, FromIterator}; use std::slice; use std::marker::PhantomData; -use std::ops::{Index, IndexMut, Range}; +use std::ops::{Index, IndexMut, Range, RangeArgument}; use std::fmt; use std::vec; use std::u32; diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index d63b4c9c31b..0bbda547761 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -25,7 +25,6 @@ #![deny(warnings)] #![feature(shared)] -#![feature(collections_range)] #![feature(nonzero)] #![feature(unboxed_closures)] #![feature(fn_traits)] diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index b8a6a66eaa6..2ed6724b07d 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -436,6 +436,8 @@ pub use self::hash_map::HashMap; pub use self::hash_set::HashSet; #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_deprecated(reason = "moved to std::ops", since = "1.19.0")] +#[allow(deprecated)] pub use alloc::range; mod hash; -- cgit 1.4.1-3-g733a5 From d24d408af387e99e7237f21e9a8d13a35552e01a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 25 Jun 2017 11:33:47 -0700 Subject: std: Fix implementation of `Alloc::alloc_one` This had an accidental `u8 as *mut T` where it was intended to have just a normal pointer-to-pointer cast. Closes #42827 --- src/liballoc/allocator.rs | 2 +- src/test/run-pass/allocator-alloc-one.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/allocator-alloc-one.rs (limited to 'src/liballoc') diff --git a/src/liballoc/allocator.rs b/src/liballoc/allocator.rs index 9bddce29957..bf38629ed38 100644 --- a/src/liballoc/allocator.rs +++ b/src/liballoc/allocator.rs @@ -873,7 +873,7 @@ pub unsafe trait Alloc { { let k = Layout::new::(); if k.size() > 0 { - unsafe { self.alloc(k).map(|p|Unique::new(*p as *mut T)) } + unsafe { self.alloc(k).map(|p| Unique::new(p as *mut T)) } } else { Err(AllocErr::invalid_input("zero-sized type invalid for alloc_one")) } diff --git a/src/test/run-pass/allocator-alloc-one.rs b/src/test/run-pass/allocator-alloc-one.rs new file mode 100644 index 00000000000..7cc547dcc04 --- /dev/null +++ b/src/test/run-pass/allocator-alloc-one.rs @@ -0,0 +1,27 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(alloc, allocator_api, heap_api, unique)] + +extern crate alloc; + +use alloc::heap::HeapAlloc; +use alloc::allocator::Alloc; + +fn main() { + unsafe { + let ptr = HeapAlloc.alloc_one::().unwrap_or_else(|e| { + HeapAlloc.oom(e) + }); + *ptr.as_ptr() = 4; + assert_eq!(*ptr.as_ptr(), 4); + HeapAlloc.dealloc_one(ptr); + } +} -- cgit 1.4.1-3-g733a5 From 0a9c13624d2fede5c6ce8e5aa7f486403098bde6 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 30 Jun 2017 08:34:53 -1000 Subject: Revert "Stabilize RangeArgument" This reverts commit 143206d54d7558c2326212df99efc98110904fdb. --- src/liballoc/btree/map.rs | 5 +- src/liballoc/btree/set.rs | 3 +- src/liballoc/lib.rs | 51 +++++++- src/liballoc/range.rs | 138 +++++++++++++++++++- src/liballoc/string.rs | 5 +- src/liballoc/vec.rs | 5 +- src/liballoc/vec_deque.rs | 5 +- src/libcollections/lib.rs | 1 - src/libcore/ops/mod.rs | 3 - src/libcore/ops/range.rs | 174 ++----------------------- src/librustc_data_structures/accumulate_vec.rs | 3 +- src/librustc_data_structures/array_vec.rs | 5 +- src/librustc_data_structures/indexed_vec.rs | 3 +- src/librustc_data_structures/lib.rs | 1 + src/libstd/collections/mod.rs | 2 - 15 files changed, 217 insertions(+), 187 deletions(-) (limited to 'src/liballoc') diff --git a/src/liballoc/btree/map.rs b/src/liballoc/btree/map.rs index 5243fb6ae0e..a51c70159db 100644 --- a/src/liballoc/btree/map.rs +++ b/src/liballoc/btree/map.rs @@ -13,11 +13,12 @@ use core::fmt::Debug; use core::hash::{Hash, Hasher}; use core::iter::{FromIterator, Peekable, FusedIterator}; use core::marker::PhantomData; -use core::ops::{Index, RangeArgument}; -use core::ops::Bound::{Excluded, Included, Unbounded}; +use core::ops::Index; use core::{fmt, intrinsics, mem, ptr}; use borrow::Borrow; +use Bound::{Excluded, Included, Unbounded}; +use range::RangeArgument; use super::node::{self, Handle, NodeRef, marker}; use super::search; diff --git a/src/liballoc/btree/set.rs b/src/liballoc/btree/set.rs index c755d2d8b85..d32460da939 100644 --- a/src/liballoc/btree/set.rs +++ b/src/liballoc/btree/set.rs @@ -16,11 +16,12 @@ use core::cmp::{min, max}; use core::fmt::Debug; use core::fmt; use core::iter::{Peekable, FromIterator, FusedIterator}; -use core::ops::{BitOr, BitAnd, BitXor, Sub, RangeArgument}; +use core::ops::{BitOr, BitAnd, BitXor, Sub}; use borrow::Borrow; use btree_map::{BTreeMap, Keys}; use super::Recover; +use range::RangeArgument; // FIXME(conventions): implement bounded iterators diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 6f4e300fd3c..ca52943ea97 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -203,7 +203,56 @@ mod std { pub use core::ops; // RangeFull } -pub use core::ops::Bound; +/// An endpoint of a range of keys. +/// +/// # Examples +/// +/// `Bound`s are range endpoints: +/// +/// ``` +/// #![feature(collections_range)] +/// +/// use std::collections::range::RangeArgument; +/// use std::collections::Bound::*; +/// +/// assert_eq!((..100).start(), Unbounded); +/// assert_eq!((1..12).start(), Included(&1)); +/// assert_eq!((1..12).end(), Excluded(&12)); +/// ``` +/// +/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`]. +/// Note that in most cases, it's better to use range syntax (`1..5`) instead. +/// +/// ``` +/// use std::collections::BTreeMap; +/// use std::collections::Bound::{Excluded, Included, Unbounded}; +/// +/// let mut map = BTreeMap::new(); +/// map.insert(3, "a"); +/// map.insert(5, "b"); +/// map.insert(8, "c"); +/// +/// for (key, value) in map.range((Excluded(3), Included(8))) { +/// println!("{}: {}", key, value); +/// } +/// +/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next()); +/// ``` +/// +/// [`BTreeMap::range`]: btree_map/struct.BTreeMap.html#method.range +#[stable(feature = "collections_bound", since = "1.17.0")] +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub enum Bound { + /// An inclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Included(T), + /// An exclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Excluded(T), + /// An infinite endpoint. Indicates that there is no bound in this direction. + #[stable(feature = "collections_bound", since = "1.17.0")] + Unbounded, +} /// An intermediate trait for specialization of `Extend`. #[doc(hidden)] diff --git a/src/liballoc/range.rs b/src/liballoc/range.rs index 0a058c47a50..f862da0d61e 100644 --- a/src/liballoc/range.rs +++ b/src/liballoc/range.rs @@ -11,8 +11,142 @@ #![unstable(feature = "collections_range", reason = "waiting for dust to settle on inclusive ranges", issue = "30877")] -#![rustc_deprecated(reason = "moved to core::ops", since = "1.19.0")] //! Range syntax. -pub use core::ops::RangeArgument; +use core::ops::{RangeFull, Range, RangeTo, RangeFrom, RangeInclusive, RangeToInclusive}; +use Bound::{self, Excluded, Included, Unbounded}; + +/// `RangeArgument` is implemented by Rust's built-in range types, produced +/// by range syntax like `..`, `a..`, `..b` or `c..d`. +pub trait RangeArgument { + /// Start index bound. + /// + /// Returns the start value as a `Bound`. + /// + /// # Examples + /// + /// ``` + /// #![feature(alloc)] + /// #![feature(collections_range)] + /// + /// extern crate alloc; + /// + /// # fn main() { + /// use alloc::range::RangeArgument; + /// use alloc::Bound::*; + /// + /// assert_eq!((..10).start(), Unbounded); + /// assert_eq!((3..10).start(), Included(&3)); + /// # } + /// ``` + fn start(&self) -> Bound<&T>; + + /// End index bound. + /// + /// Returns the end value as a `Bound`. + /// + /// # Examples + /// + /// ``` + /// #![feature(alloc)] + /// #![feature(collections_range)] + /// + /// extern crate alloc; + /// + /// # fn main() { + /// use alloc::range::RangeArgument; + /// use alloc::Bound::*; + /// + /// assert_eq!((3..).end(), Unbounded); + /// assert_eq!((3..10).end(), Excluded(&10)); + /// # } + /// ``` + fn end(&self) -> Bound<&T>; +} + +// FIXME add inclusive ranges to RangeArgument + +impl RangeArgument for RangeFull { + fn start(&self) -> Bound<&T> { + Unbounded + } + fn end(&self) -> Bound<&T> { + Unbounded + } +} + +impl RangeArgument for RangeFrom { + fn start(&self) -> Bound<&T> { + Included(&self.start) + } + fn end(&self) -> Bound<&T> { + Unbounded + } +} + +impl RangeArgument for RangeTo { + fn start(&self) -> Bound<&T> { + Unbounded + } + fn end(&self) -> Bound<&T> { + Excluded(&self.end) + } +} + +impl RangeArgument for Range { + fn start(&self) -> Bound<&T> { + Included(&self.start) + } + fn end(&self) -> Bound<&T> { + Excluded(&self.end) + } +} + +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +impl RangeArgument for RangeInclusive { + fn start(&self) -> Bound<&T> { + Included(&self.start) + } + fn end(&self) -> Bound<&T> { + Included(&self.end) + } +} + +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +impl RangeArgument for RangeToInclusive { + fn start(&self) -> Bound<&T> { + Unbounded + } + fn end(&self) -> Bound<&T> { + Included(&self.end) + } +} + +impl RangeArgument for (Bound, Bound) { + fn start(&self) -> Bound<&T> { + match *self { + (Included(ref start), _) => Included(start), + (Excluded(ref start), _) => Excluded(start), + (Unbounded, _) => Unbounded, + } + } + + fn end(&self) -> Bound<&T> { + match *self { + (_, Included(ref end)) => Included(end), + (_, Excluded(ref end)) => Excluded(end), + (_, Unbounded) => Unbounded, + } + } +} + +impl<'a, T: ?Sized + 'a> RangeArgument for (Bound<&'a T>, Bound<&'a T>) { + fn start(&self) -> Bound<&T> { + self.0 + } + + fn end(&self) -> Bound<&T> { + self.1 + } +} diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 1f0894d39d4..79d1ccf637d 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -59,14 +59,15 @@ use core::fmt; use core::hash; use core::iter::{FromIterator, FusedIterator}; -use core::ops::{self, Add, AddAssign, Index, IndexMut, RangeArgument}; -use core::ops::Bound::{Excluded, Included, Unbounded}; +use core::ops::{self, Add, AddAssign, Index, IndexMut}; use core::ptr; use core::str::pattern::Pattern; use std_unicode::lossy; use std_unicode::char::{decode_utf16, REPLACEMENT_CHARACTER}; use borrow::{Cow, ToOwned}; +use range::RangeArgument; +use Bound::{Excluded, Included, Unbounded}; use str::{self, from_boxed_utf8_unchecked, FromStr, Utf8Error, Chars}; use vec::Vec; use boxed::Box; diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index e118d406ecf..5d1999a4262 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -74,8 +74,7 @@ use core::iter::{FromIterator, FusedIterator, TrustedLen}; use core::mem; #[cfg(not(test))] use core::num::Float; -use core::ops::{InPlace, Index, IndexMut, Place, Placer, RangeArgument}; -use core::ops::Bound::{Excluded, Included, Unbounded}; +use core::ops::{InPlace, Index, IndexMut, Place, Placer}; use core::ops; use core::ptr; use core::ptr::Shared; @@ -85,6 +84,8 @@ use borrow::ToOwned; use borrow::Cow; use boxed::Box; use raw_vec::RawVec; +use super::range::RangeArgument; +use Bound::{Excluded, Included, Unbounded}; /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs index d1d334267bc..18175a5d01b 100644 --- a/src/liballoc/vec_deque.rs +++ b/src/liballoc/vec_deque.rs @@ -21,8 +21,7 @@ use core::cmp::Ordering; use core::fmt; use core::iter::{repeat, FromIterator, FusedIterator}; use core::mem; -use core::ops::{Index, IndexMut, Place, Placer, InPlace, RangeArgument}; -use core::ops::Bound::{Excluded, Included, Unbounded}; +use core::ops::{Index, IndexMut, Place, Placer, InPlace}; use core::ptr; use core::ptr::Shared; use core::slice; @@ -32,6 +31,8 @@ use core::cmp; use raw_vec::RawVec; +use super::range::RangeArgument; +use Bound::{Excluded, Included, Unbounded}; use super::vec::Vec; const INITIAL_CAPACITY: usize = 7; // 2^3 - 1 diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 0a939831622..de5d6df328c 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -46,7 +46,6 @@ pub use alloc::binary_heap; pub use alloc::borrow; pub use alloc::fmt; pub use alloc::linked_list; -#[allow(deprecated)] pub use alloc::range; pub use alloc::slice; pub use alloc::str; diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index 34f00850579..a78f4fe28a6 100644 --- a/src/libcore/ops/mod.rs +++ b/src/libcore/ops/mod.rs @@ -183,9 +183,6 @@ pub use self::index::{Index, IndexMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; -#[stable(feature = "range_argument", since = "1.19.0")] -pub use self::range::{RangeArgument, Bound}; - #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub use self::range::{RangeInclusive, RangeToInclusive}; diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 65e09da4fff..33258b7a875 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -9,7 +9,6 @@ // except according to those terms. use fmt; -use ops::Bound::{Included, Excluded, Unbounded}; /// An unbounded range. Use `..` (two dots) for its shorthand. /// @@ -72,8 +71,7 @@ impl fmt::Debug for RangeFull { /// assert_eq!(arr[1..3], [ 1,2 ]); // Range /// } /// ``` -#[derive(Clone, PartialEq, Eq, Hash)] -// not Copy -- see #27186 +#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 #[stable(feature = "rust1", since = "1.0.0")] pub struct Range { /// The lower bound of the range (inclusive). @@ -136,8 +134,7 @@ impl> Range { /// assert_eq!(arr[1..3], [ 1,2 ]); /// } /// ``` -#[derive(Clone, PartialEq, Eq, Hash)] -// not Copy -- see #27186 +#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 #[stable(feature = "rust1", since = "1.0.0")] pub struct RangeFrom { /// The lower bound of the range (inclusive). @@ -253,16 +250,17 @@ impl> RangeTo { /// assert_eq!(arr[1...2], [ 1,2 ]); // RangeInclusive /// } /// ``` -#[derive(Clone, PartialEq, Eq, Hash)] -// not Copy -- see #27186 +#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub struct RangeInclusive { /// The lower bound of the range (inclusive). - #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", + #[unstable(feature = "inclusive_range", + reason = "recently added, follows RFC", issue = "28237")] pub start: Idx, /// The upper bound of the range (inclusive). - #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", + #[unstable(feature = "inclusive_range", + reason = "recently added, follows RFC", issue = "28237")] pub end: Idx, } @@ -335,7 +333,8 @@ impl> RangeInclusive { #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub struct RangeToInclusive { /// The upper bound of the range (inclusive) - #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", + #[unstable(feature = "inclusive_range", + reason = "recently added, follows RFC", issue = "28237")] pub end: Idx, } @@ -366,158 +365,3 @@ impl> RangeToInclusive { // RangeToInclusive cannot impl From> // because underflow would be possible with (..0).into() - -/// `RangeArgument` is implemented by Rust's built-in range types, produced -/// by range syntax like `..`, `a..`, `..b` or `c..d`. -#[stable(feature = "range_argument", since = "1.19.0")] -pub trait RangeArgument { - /// Start index bound. - /// - /// Returns the start value as a `Bound`. - /// - /// # Examples - /// - /// ``` - /// use std::ops::RangeArgument; - /// use std::ops::Bound::*; - /// - /// assert_eq!((..10).start(), Unbounded); - /// assert_eq!((3..10).start(), Included(&3)); - /// ``` - #[stable(feature = "range_argument", since = "1.19.0")] - fn start(&self) -> Bound<&T>; - - /// End index bound. - /// - /// Returns the end value as a `Bound`. - /// - /// # Examples - /// - /// ``` - /// use std::ops::RangeArgument; - /// use std::ops::Bound::*; - /// - /// assert_eq!((3..).end(), Unbounded); - /// assert_eq!((3..10).end(), Excluded(&10)); - /// ``` - #[stable(feature = "range_argument", since = "1.19.0")] - fn end(&self) -> Bound<&T>; -} - -#[stable(feature = "range_argument", since = "1.19.0")] -impl RangeArgument for RangeFull { - fn start(&self) -> Bound<&T> { - Unbounded - } - fn end(&self) -> Bound<&T> { - Unbounded - } -} - -#[stable(feature = "range_argument", since = "1.19.0")] -impl RangeArgument for RangeFrom { - fn start(&self) -> Bound<&T> { - Included(&self.start) - } - fn end(&self) -> Bound<&T> { - Unbounded - } -} - -#[stable(feature = "range_argument", since = "1.19.0")] -impl RangeArgument for RangeTo { - fn start(&self) -> Bound<&T> { - Unbounded - } - fn end(&self) -> Bound<&T> { - Excluded(&self.end) - } -} - -#[stable(feature = "range_argument", since = "1.19.0")] -impl RangeArgument for Range { - fn start(&self) -> Bound<&T> { - Included(&self.start) - } - fn end(&self) -> Bound<&T> { - Excluded(&self.end) - } -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl RangeArgument for RangeInclusive { - fn start(&self) -> Bound<&T> { - Included(&self.start) - } - fn end(&self) -> Bound<&T> { - Included(&self.end) - } -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl RangeArgument for RangeToInclusive { - fn start(&self) -> Bound<&T> { - Unbounded - } - fn end(&self) -> Bound<&T> { - Included(&self.end) - } -} - -#[stable(feature = "range_argument", since = "1.19.0")] -impl RangeArgument for (Bound, Bound) { - fn start(&self) -> Bound<&T> { - match *self { - (Included(ref start), _) => Included(start), - (Excluded(ref start), _) => Excluded(start), - (Unbounded, _) => Unbounded, - } - } - - fn end(&self) -> Bound<&T> { - match *self { - (_, Included(ref end)) => Included(end), - (_, Excluded(ref end)) => Excluded(end), - (_, Unbounded) => Unbounded, - } - } -} - -#[stable(feature = "range_argument", since = "1.19.0")] -impl<'a, T: ?Sized + 'a> RangeArgument for (Bound<&'a T>, Bound<&'a T>) { - fn start(&self) -> Bound<&T> { - self.0 - } - - fn end(&self) -> Bound<&T> { - self.1 - } -} - -/// An endpoint of a range of keys. -/// -/// # Examples -/// -/// `Bound`s are range endpoints: -/// -/// ``` -/// use std::ops::RangeArgument; -/// use std::ops::Bound::*; -/// -/// assert_eq!((..100).start(), Unbounded); -/// assert_eq!((1..12).start(), Included(&1)); -/// assert_eq!((1..12).end(), Excluded(&12)); -/// ``` -#[stable(feature = "collections_bound", since = "1.17.0")] -#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] -pub enum Bound { - /// An inclusive bound. - #[stable(feature = "collections_bound", since = "1.17.0")] - Included(T), - /// An exclusive bound. - #[stable(feature = "collections_bound", since = "1.17.0")] - Excluded(T), - /// An infinite endpoint. Indicates that there is no bound in this direction. - #[stable(feature = "collections_bound", since = "1.17.0")] - Unbounded, -} diff --git a/src/librustc_data_structures/accumulate_vec.rs b/src/librustc_data_structures/accumulate_vec.rs index eacd394ad5e..c03c2890ba3 100644 --- a/src/librustc_data_structures/accumulate_vec.rs +++ b/src/librustc_data_structures/accumulate_vec.rs @@ -15,10 +15,11 @@ //! //! The N above is determined by Array's implementor, by way of an associatated constant. -use std::ops::{Deref, DerefMut, RangeArgument}; +use std::ops::{Deref, DerefMut}; use std::iter::{self, IntoIterator, FromIterator}; use std::slice; use std::vec; +use std::collections::range::RangeArgument; use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; diff --git a/src/librustc_data_structures/array_vec.rs b/src/librustc_data_structures/array_vec.rs index a9abdf1377e..078bb801751 100644 --- a/src/librustc_data_structures/array_vec.rs +++ b/src/librustc_data_structures/array_vec.rs @@ -13,12 +13,13 @@ use std::marker::Unsize; use std::iter::Extend; use std::ptr::{self, drop_in_place, Shared}; -use std::ops::{Deref, DerefMut, Range, RangeArgument}; -use std::ops::Bound::{Excluded, Included, Unbounded}; +use std::ops::{Deref, DerefMut, Range}; use std::hash::{Hash, Hasher}; use std::slice; use std::fmt; use std::mem; +use std::collections::range::RangeArgument; +use std::collections::Bound::{Excluded, Included, Unbounded}; use std::mem::ManuallyDrop; pub unsafe trait Array { diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 3bf926fa8bf..29ac650aa70 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -8,11 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::collections::range::RangeArgument; use std::fmt::Debug; use std::iter::{self, FromIterator}; use std::slice; use std::marker::PhantomData; -use std::ops::{Index, IndexMut, Range, RangeArgument}; +use std::ops::{Index, IndexMut, Range}; use std::fmt; use std::vec; use std::u32; diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 0bbda547761..d63b4c9c31b 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -25,6 +25,7 @@ #![deny(warnings)] #![feature(shared)] +#![feature(collections_range)] #![feature(nonzero)] #![feature(unboxed_closures)] #![feature(fn_traits)] diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index 2ed6724b07d..b8a6a66eaa6 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -436,8 +436,6 @@ pub use self::hash_map::HashMap; pub use self::hash_set::HashSet; #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_deprecated(reason = "moved to std::ops", since = "1.19.0")] -#[allow(deprecated)] pub use alloc::range; mod hash; -- cgit 1.4.1-3-g733a5 From 5350e22366e059f2099af91d23350be1073ee165 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Sun, 2 Jul 2017 02:09:21 +0200 Subject: Stabilize feature sort_unstable --- .../src/library-features/sort-unstable.md | 40 ---------------------- src/liballoc/slice.rs | 27 ++++++++------- src/libcore/slice/sort.rs | 4 +-- 3 files changed, 17 insertions(+), 54 deletions(-) delete mode 100644 src/doc/unstable-book/src/library-features/sort-unstable.md (limited to 'src/liballoc') diff --git a/src/doc/unstable-book/src/library-features/sort-unstable.md b/src/doc/unstable-book/src/library-features/sort-unstable.md deleted file mode 100644 index 9effcfc774c..00000000000 --- a/src/doc/unstable-book/src/library-features/sort-unstable.md +++ /dev/null @@ -1,40 +0,0 @@ -# `sort_unstable` - -The tracking issue for this feature is: [#40585] - -[#40585]: https://github.com/rust-lang/rust/issues/40585 - ------------------------- - -The default `sort` method on slices is stable. In other words, it guarantees -that the original order of equal elements is preserved after sorting. The -method has several undesirable characteristics: - -1. It allocates a sizable chunk of memory. -2. If you don't need stability, it is not as performant as it could be. - -An alternative is the new `sort_unstable` feature, which includes these -methods for sorting slices: - -1. `sort_unstable` -2. `sort_unstable_by` -3. `sort_unstable_by_key` - -Unstable sorting is generally faster and makes no allocations. The majority -of real-world sorting needs doesn't require stability, so these methods can -very often come in handy. - -Another important difference is that `sort` lives in `libstd` and -`sort_unstable` lives in `libcore`. The reason is that the former makes -allocations and the latter doesn't. - -A simple example: - -```rust -#![feature(sort_unstable)] - -let mut v = [-5, 4, 1, -3, 2]; - -v.sort_unstable(); -assert!(v == [-5, -3, 1, 2, 4]); -``` diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 88876999d76..b0e872aeb69 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -1144,6 +1144,10 @@ impl [T] { /// /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case. /// + /// When applicable, unstable sorting is preferred because it is generally faster than stable + /// sorting and it doesn't allocate auxiliary memory. + /// See [`sort_unstable`](#method.sort_unstable). + /// /// # Current implementation /// /// The current algorithm is an adaptive, iterative merge sort inspired by @@ -1174,6 +1178,10 @@ impl [T] { /// /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case. /// + /// When applicable, unstable sorting is preferred because it is generally faster than stable + /// sorting and it doesn't allocate auxiliary memory. + /// See [`sort_unstable_by`](#method.sort_unstable_by). + /// /// # Current implementation /// /// The current algorithm is an adaptive, iterative merge sort inspired by @@ -1207,6 +1215,10 @@ impl [T] { /// /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case. /// + /// When applicable, unstable sorting is preferred because it is generally faster than stable + /// sorting and it doesn't allocate auxiliary memory. + /// See [`sort_unstable_by_key`](#method.sort_unstable_by_key). + /// /// # Current implementation /// /// The current algorithm is an adaptive, iterative merge sort inspired by @@ -1251,8 +1263,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(sort_unstable)] - /// /// let mut v = [-5, 4, 1, -3, 2]; /// /// v.sort_unstable(); @@ -1260,8 +1270,7 @@ impl [T] { /// ``` /// /// [pdqsort]: https://github.com/orlp/pdqsort - // FIXME #40585: Mention `sort_unstable` in the documentation for `sort`. - #[unstable(feature = "sort_unstable", issue = "40585")] + #[stable(feature = "sort_unstable", since = "1.20.0")] #[inline] pub fn sort_unstable(&mut self) where T: Ord @@ -1288,8 +1297,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(sort_unstable)] - /// /// let mut v = [5, 4, 1, 3, 2]; /// v.sort_unstable_by(|a, b| a.cmp(b)); /// assert!(v == [1, 2, 3, 4, 5]); @@ -1300,8 +1307,7 @@ impl [T] { /// ``` /// /// [pdqsort]: https://github.com/orlp/pdqsort - // FIXME #40585: Mention `sort_unstable_by` in the documentation for `sort_by`. - #[unstable(feature = "sort_unstable", issue = "40585")] + #[stable(feature = "sort_unstable", since = "1.20.0")] #[inline] pub fn sort_unstable_by(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering @@ -1328,8 +1334,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(sort_unstable)] - /// /// let mut v = [-5i32, 4, 1, -3, 2]; /// /// v.sort_unstable_by_key(|k| k.abs()); @@ -1337,8 +1341,7 @@ impl [T] { /// ``` /// /// [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")] + #[stable(feature = "sort_unstable", since = "1.20.0")] #[inline] pub fn sort_unstable_by_key(&mut self, f: F) where F: FnMut(&T) -> B, diff --git a/src/libcore/slice/sort.rs b/src/libcore/slice/sort.rs index 6f9f2915dfe..518d56095d6 100644 --- a/src/libcore/slice/sort.rs +++ b/src/libcore/slice/sort.rs @@ -351,7 +351,7 @@ fn partition_in_blocks(v: &mut [T], pivot: &T, is_less: &mut F) -> usize if start_l < end_l { // The left block remains. - // Move it's remaining out-of-order elements to the far right. + // Move its remaining out-of-order elements to the far right. debug_assert_eq!(width(l, r), block_l); while start_l < end_l { unsafe { @@ -363,7 +363,7 @@ fn partition_in_blocks(v: &mut [T], pivot: &T, is_less: &mut F) -> usize 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. + // Move its remaining out-of-order elements to the far left. debug_assert_eq!(width(l, r), block_r); while start_r < end_r { unsafe { -- cgit 1.4.1-3-g733a5 From dcd332ed94fb3dd6bf2f5789c8dd42f509337992 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 1 Jul 2017 19:18:02 -0700 Subject: Delete deprecated & unstable range-specific `step_by` Replacement: 41439 Deprecation: 42310 for 1.19 Fixes 41477 --- src/liballoc/tests/vec_deque.rs | 3 +- src/libcore/iter/mod.rs | 6 - src/libcore/iter/range.rs | 213 --------------------- src/libcore/tests/iter.rs | 42 ++-- src/libcore/tests/lib.rs | 1 - src/librand/lib.rs | 2 +- src/test/run-pass/range_inclusive.rs | 2 +- .../run-pass/sync-send-iterators-in-libcore.rs | 2 +- 8 files changed, 20 insertions(+), 251 deletions(-) (limited to 'src/liballoc') diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs index a992351653d..f2935c05d4f 100644 --- a/src/liballoc/tests/vec_deque.rs +++ b/src/liballoc/tests/vec_deque.rs @@ -510,8 +510,7 @@ fn test_from_iter() { let u: Vec<_> = deq.iter().cloned().collect(); assert_eq!(u, v); - // FIXME #27741: Remove `.skip(0)` when Range::step_by is fully removed - let seq = (0..).skip(0).step_by(2).take(256); + let seq = (0..).step_by(2).take(256); let deq: VecDeque<_> = seq.collect(); for (i, &x) in deq.iter().enumerate() { assert_eq!(2 * i, x); diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index d6a9be4437d..decd718d65e 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -314,12 +314,6 @@ pub use self::iterator::Iterator; reason = "likely to be replaced by finer-grained traits", issue = "42168")] pub use self::range::Step; -#[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] -#[rustc_deprecated(since = "1.19.0", - reason = "replaced by `iter::StepBy`")] -#[allow(deprecated)] -pub use self::range::StepBy as DeprecatedStepBy; #[stable(feature = "rust1", since = "1.0.0")] pub use self::sources::{Repeat, repeat}; diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 9aea4477fb7..1dad8157948 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -244,219 +244,6 @@ step_impl_signed!(i64); step_impl_no_between!(u64 i64); step_impl_no_between!(u128 i128); -/// An adapter for stepping range iterators by a custom amount. -/// -/// The resulting iterator handles overflow by stopping. The `A` -/// parameter is the type being iterated over, while `R` is the range -/// type (usually one of `std::ops::{Range, RangeFrom, RangeInclusive}`. -#[derive(Clone, Debug)] -#[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] -#[rustc_deprecated(since = "1.19.0", - reason = "replaced by `iter::StepBy`")] -#[allow(deprecated)] -pub struct StepBy { - step_by: A, - range: R, -} - -impl ops::RangeFrom { - /// Creates an iterator starting at the same point, but stepping by - /// the given amount at each iteration. - /// - /// # Examples - /// - /// ``` - /// #![feature(step_by)] - /// fn main() { - /// let result: Vec<_> = (0..).step_by(2).take(5).collect(); - /// assert_eq!(result, vec![0, 2, 4, 6, 8]); - /// } - /// ``` - #[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] - #[rustc_deprecated(since = "1.19.0", - reason = "replaced by `Iterator::step_by`")] - #[allow(deprecated)] - pub fn step_by(self, by: A) -> StepBy { - StepBy { - step_by: by, - range: self - } - } -} - -impl ops::Range { - /// Creates an iterator with the same range, but stepping by the - /// given amount at each iteration. - /// - /// The resulting iterator handles overflow by stopping. - /// - /// # Examples - /// - /// ``` - /// #![feature(step_by)] - /// fn main() { - /// let result: Vec<_> = (0..10).step_by(2).collect(); - /// assert_eq!(result, vec![0, 2, 4, 6, 8]); - /// } - /// ``` - #[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] - #[rustc_deprecated(since = "1.19.0", - reason = "replaced by `Iterator::step_by`")] - #[allow(deprecated)] - pub fn step_by(self, by: A) -> StepBy { - StepBy { - step_by: by, - range: self - } - } -} - -impl ops::RangeInclusive { - /// Creates an iterator with the same range, but stepping by the - /// given amount at each iteration. - /// - /// The resulting iterator handles overflow by stopping. - /// - /// # Examples - /// - /// ``` - /// #![feature(step_by, inclusive_range_syntax)] - /// - /// let result: Vec<_> = (0...10).step_by(2).collect(); - /// assert_eq!(result, vec![0, 2, 4, 6, 8, 10]); - /// ``` - #[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] - #[rustc_deprecated(since = "1.19.0", - reason = "replaced by `Iterator::step_by`")] - #[allow(deprecated)] - pub fn step_by(self, by: A) -> StepBy { - StepBy { - step_by: by, - range: self - } - } -} - -#[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] -#[allow(deprecated)] -impl Iterator for StepBy> where - A: Clone, - for<'a> &'a A: Add<&'a A, Output = A> -{ - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - let mut n = &self.range.start + &self.step_by; - mem::swap(&mut n, &mut self.range.start); - Some(n) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - (usize::MAX, None) // Too bad we can't specify an infinite lower bound - } -} - -#[unstable(feature = "fused", issue = "35602")] -#[allow(deprecated)] -impl FusedIterator for StepBy> - where A: Clone, for<'a> &'a A: Add<&'a A, Output = A> {} - -#[unstable(feature = "step_by", reason = "recent addition", - issue = "27741")] -#[allow(deprecated)] -impl Iterator for StepBy> { - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - let rev = self.step_by.is_negative(); - if (rev && self.range.start > self.range.end) || - (!rev && self.range.start < self.range.end) - { - match self.range.start.step(&self.step_by) { - Some(mut n) => { - mem::swap(&mut self.range.start, &mut n); - Some(n) - }, - None => { - let mut n = self.range.end.clone(); - mem::swap(&mut self.range.start, &mut n); - Some(n) - } - } - } else { - None - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - match Step::steps_between(&self.range.start, - &self.range.end, - &self.step_by) { - Some(hint) => (hint, Some(hint)), - None => (0, None) - } - } -} - -#[unstable(feature = "fused", issue = "35602")] -#[allow(deprecated)] -impl FusedIterator for StepBy> {} - -#[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", - issue = "28237")] -#[allow(deprecated)] -impl Iterator for StepBy> { - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - let rev = self.step_by.is_negative(); - - if (rev && self.range.start >= self.range.end) || - (!rev && self.range.start <= self.range.end) - { - match self.range.start.step(&self.step_by) { - Some(n) => { - Some(mem::replace(&mut self.range.start, n)) - }, - None => { - let last = self.range.start.replace_one(); - self.range.end.replace_zero(); - self.step_by.replace_one(); - Some(last) - }, - } - } - else { - None - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - match Step::steps_between(&self.range.start, - &self.range.end, - &self.step_by) { - Some(hint) => (hint.saturating_add(1), hint.checked_add(1)), - None => (0, None) - } - } -} - -#[unstable(feature = "fused", issue = "35602")] -#[allow(deprecated)] -impl FusedIterator for StepBy> {} - macro_rules! range_exact_iter_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 4f9951cd153..14f0260f571 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -12,15 +12,6 @@ use core::iter::*; use core::{i8, i16, isize}; use core::usize; -// FIXME #27741: This is here to simplify calling Iterator::step_by. Remove -// once Range::step_by is completely gone (not just deprecated). -trait IterEx: Sized { - fn iter_step_by(self, n: usize) -> StepBy; -} -impl IterEx for I { - fn iter_step_by(self, n: usize) -> StepBy { self.step_by(n) } -} - #[test] fn test_lt() { let empty: [isize; 0] = []; @@ -76,7 +67,7 @@ fn test_multi_iter() { #[test] fn test_counter_from_iter() { - let it = (0..).iter_step_by(5).take(10); + let it = (0..).step_by(5).take(10); let xs: Vec = FromIterator::from_iter(it); assert_eq!(xs, [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]); } @@ -94,7 +85,7 @@ fn test_iterator_chain() { } assert_eq!(i, expected.len()); - let ys = (30..).iter_step_by(10).take(4); + let ys = (30..).step_by(10).take(4); let it = xs.iter().cloned().chain(ys); let mut i = 0; for x in it { @@ -156,13 +147,13 @@ fn test_iterator_chain_find() { #[test] fn test_iterator_step_by() { // Identity - let mut it = (0..).iter_step_by(1).take(3); + let mut it = (0..).step_by(1).take(3); assert_eq!(it.next(), Some(0)); assert_eq!(it.next(), Some(1)); assert_eq!(it.next(), Some(2)); assert_eq!(it.next(), None); - let mut it = (0..).iter_step_by(3).take(4); + let mut it = (0..).step_by(3).take(4); assert_eq!(it.next(), Some(0)); assert_eq!(it.next(), Some(3)); assert_eq!(it.next(), Some(6)); @@ -173,7 +164,7 @@ fn test_iterator_step_by() { #[test] #[should_panic] fn test_iterator_step_by_zero() { - let mut it = (0..).iter_step_by(0); + let mut it = (0..).step_by(0); it.next(); } @@ -252,7 +243,7 @@ fn test_iterator_step_by_size_hint() { #[test] fn test_filter_map() { - let it = (0..).iter_step_by(1).take(10) + let it = (0..).step_by(1).take(10) .filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None }); assert_eq!(it.collect::>(), [0*0, 2*2, 4*4, 6*6, 8*8]); } @@ -654,7 +645,7 @@ fn test_iterator_scan() { fn test_iterator_flat_map() { let xs = [0, 3, 6]; let ys = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let it = xs.iter().flat_map(|&x| (x..).iter_step_by(1).take(3)); + let it = xs.iter().flat_map(|&x| (x..).step_by(1).take(3)); let mut i = 0; for x in it { assert_eq!(x, ys[i]); @@ -680,13 +671,13 @@ fn test_inspect() { #[test] fn test_cycle() { let cycle_len = 3; - let it = (0..).iter_step_by(1).take(cycle_len).cycle(); + let it = (0..).step_by(1).take(cycle_len).cycle(); assert_eq!(it.size_hint(), (usize::MAX, None)); for (i, x) in it.take(100).enumerate() { assert_eq!(i % cycle_len, x); } - let mut it = (0..).iter_step_by(1).take(0).cycle(); + let mut it = (0..).step_by(1).take(0).cycle(); assert_eq!(it.size_hint(), (0, Some(0))); assert_eq!(it.next(), None); } @@ -765,7 +756,7 @@ fn test_iterator_min() { #[test] fn test_iterator_size_hint() { - let c = (0..).iter_step_by(1); + let c = (0..).step_by(1); let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; let v2 = &[10, 11, 12]; let vi = v.iter(); @@ -1090,8 +1081,8 @@ fn test_range_step() { #![allow(deprecated)] assert_eq!((0..20).step_by(5).collect::>(), [0, 5, 10, 15]); - assert_eq!((20..0).step_by(-5).collect::>(), [20, 15, 10, 5]); - assert_eq!((20..0).step_by(-6).collect::>(), [20, 14, 8, 2]); + assert_eq!((1..21).rev().step_by(5).collect::>(), [20, 15, 10, 5]); + assert_eq!((1..21).rev().step_by(6).collect::>(), [20, 14, 8, 2]); assert_eq!((200..255).step_by(50).collect::>(), [200, 250]); assert_eq!((200..-5).step_by(1).collect::>(), []); assert_eq!((200..200).step_by(1).collect::>(), []); @@ -1099,13 +1090,12 @@ fn test_range_step() { assert_eq!((0..20).step_by(1).size_hint(), (20, Some(20))); assert_eq!((0..20).step_by(21).size_hint(), (1, Some(1))); assert_eq!((0..20).step_by(5).size_hint(), (4, Some(4))); - assert_eq!((20..0).step_by(-5).size_hint(), (4, Some(4))); - assert_eq!((20..0).step_by(-6).size_hint(), (4, Some(4))); + assert_eq!((1..21).rev().step_by(5).size_hint(), (4, Some(4))); + assert_eq!((1..21).rev().step_by(6).size_hint(), (4, Some(4))); assert_eq!((20..-5).step_by(1).size_hint(), (0, Some(0))); assert_eq!((20..20).step_by(1).size_hint(), (0, Some(0))); - assert_eq!((0..1).step_by(0).size_hint(), (0, None)); - assert_eq!((i8::MAX..i8::MIN).step_by(i8::MIN).size_hint(), (2, Some(2))); - assert_eq!((i16::MIN..i16::MAX).step_by(i16::MAX).size_hint(), (3, Some(3))); + assert_eq!((i8::MIN..i8::MAX).step_by(-(i8::MIN as i32) as usize).size_hint(), (2, Some(2))); + assert_eq!((i16::MIN..i16::MAX).step_by(i16::MAX as usize).size_hint(), (3, Some(3))); assert_eq!((isize::MIN..isize::MAX).step_by(1).size_hint(), (usize::MAX, Some(usize::MAX))); } diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 337f8aa31dc..3b86e8e9744 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -36,7 +36,6 @@ #![feature(sort_internals)] #![feature(sort_unstable)] #![feature(specialization)] -#![feature(step_by)] #![feature(step_trait)] #![feature(test)] #![feature(trusted_len)] diff --git a/src/librand/lib.rs b/src/librand/lib.rs index ca05db15ffe..5e56b0d8ab1 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -31,7 +31,7 @@ issue = "27703")] #![feature(core_intrinsics)] #![feature(staged_api)] -#![feature(step_by)] +#![feature(iterator_step_by)] #![feature(custom_attribute)] #![feature(specialization)] #![allow(unused_attributes)] diff --git a/src/test/run-pass/range_inclusive.rs b/src/test/run-pass/range_inclusive.rs index 372d4a8b732..f6119e70999 100644 --- a/src/test/run-pass/range_inclusive.rs +++ b/src/test/run-pass/range_inclusive.rs @@ -10,7 +10,7 @@ // Test inclusive range syntax. -#![feature(inclusive_range_syntax, inclusive_range, step_by)] +#![feature(inclusive_range_syntax, inclusive_range, iterator_step_by)] use std::ops::{RangeInclusive, RangeToInclusive}; diff --git a/src/test/run-pass/sync-send-iterators-in-libcore.rs b/src/test/run-pass/sync-send-iterators-in-libcore.rs index d12bdf182fa..c11a0d391a4 100644 --- a/src/test/run-pass/sync-send-iterators-in-libcore.rs +++ b/src/test/run-pass/sync-send-iterators-in-libcore.rs @@ -14,7 +14,7 @@ #![feature(iter_empty)] #![feature(iter_once)] #![feature(iter_unfold)] -#![feature(step_by)] +#![feature(iterator_step_by)] #![feature(str_escape)] use std::iter::{empty, once, repeat}; -- cgit 1.4.1-3-g733a5 From 21149bcd530e3dcd817a9cc2053f3a6b82b7a379 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Sun, 2 Jul 2017 19:14:16 +0200 Subject: Fix lint errors --- src/liballoc/lib.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'src/liballoc') diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 6f4e300fd3c..8bdf93fd2ed 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -83,7 +83,6 @@ #![cfg_attr(not(test), feature(core_float))] #![cfg_attr(not(test), feature(exact_size_is_empty))] #![cfg_attr(not(test), feature(slice_rotate))] -#![cfg_attr(not(test), feature(sort_unstable))] #![cfg_attr(not(test), feature(str_checked_slicing))] #![cfg_attr(test, feature(rand, test))] #![feature(allocator)] -- cgit 1.4.1-3-g733a5 From 66f8cddae55ae3699932b424823dc21cfa566e6b Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Sun, 2 Jul 2017 21:29:39 +0200 Subject: Remove the remaining feature gates --- src/liballoc/benches/lib.rs | 1 - src/libcore/tests/lib.rs | 1 - src/librustc/lib.rs | 1 - src/librustc_incremental/lib.rs | 1 - src/librustc_metadata/lib.rs | 1 - 5 files changed, 5 deletions(-) (limited to 'src/liballoc') diff --git a/src/liballoc/benches/lib.rs b/src/liballoc/benches/lib.rs index 958020d0b0e..5a5eb846b73 100644 --- a/src/liballoc/benches/lib.rs +++ b/src/liballoc/benches/lib.rs @@ -14,7 +14,6 @@ #![feature(rand)] #![feature(repr_simd)] #![feature(slice_rotate)] -#![feature(sort_unstable)] #![feature(test)] extern crate test; diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 337f8aa31dc..b0a57d97d5e 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -34,7 +34,6 @@ #![feature(slice_patterns)] #![feature(slice_rotate)] #![feature(sort_internals)] -#![feature(sort_unstable)] #![feature(specialization)] #![feature(step_by)] #![feature(step_trait)] diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index b81c56e5ee8..e4cf893375c 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -39,7 +39,6 @@ #![feature(specialization)] #![feature(unboxed_closures)] #![feature(discriminant_value)] -#![feature(sort_unstable)] #![feature(trace_macros)] #![feature(test)] diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs index 5bd7a24bdaf..ac3149b90b8 100644 --- a/src/librustc_incremental/lib.rs +++ b/src/librustc_incremental/lib.rs @@ -20,7 +20,6 @@ #![feature(rand)] #![feature(conservative_impl_trait)] -#![feature(sort_unstable)] extern crate graphviz; #[macro_use] extern crate rustc; diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 12997f24c74..99b718ea07b 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -26,7 +26,6 @@ #![feature(specialization)] #![feature(discriminant_value)] #![feature(rustc_private)] -#![feature(sort_unstable)] #[macro_use] extern crate log; -- cgit 1.4.1-3-g733a5 From d68c3ab17b6f6c3b71d0531063aec8e64098f59c Mon Sep 17 00:00:00 2001 From: Anders Kaseorg Date: Mon, 3 Jul 2017 17:18:01 -0400 Subject: Document unintuitive argument order for Vec::dedup_by relation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When trying to use dedup_by to merge some auxiliary information from removed elements into kept elements, I was surprised to observe that vec.dedup_by(same_bucket) calls same_bucket(a, b) where b appears before a in the vector, and discards a when true is returned. This argument order is probably a bug, but since it has already been stabilized, I guess we should document it as a feature and move on. (Vec::dedup also uses == with this unexpected argument order, but I figure that’s not important since == is expected to be symmetric with no side effects.) Signed-off-by: Anders Kaseorg --- src/liballoc/tests/vec.rs | 5 +++++ src/liballoc/vec.rs | 11 +++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'src/liballoc') diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index fdf453b39cf..17f1229c206 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -274,6 +274,11 @@ fn test_dedup_by() { vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b)); assert_eq!(vec, ["foo", "bar", "baz", "bar"]); + + let mut vec = vec![("foo", 1), ("foo", 2), ("bar", 3), ("bar", 4), ("bar", 5)]; + vec.dedup_by(|a, b| a.0 == b.0 && { b.1 += a.1; true }); + + assert_eq!(vec, [("foo", 3), ("bar", 12)]); } #[test] diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 5d1999a4262..1a5975686df 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -823,7 +823,8 @@ impl Vec { } } - /// Removes consecutive elements in the vector that resolve to the same key. + /// Removes all but the first of consecutive elements in the vector that resolve to the same + /// key. /// /// If the vector is sorted, this removes all duplicates. /// @@ -842,11 +843,13 @@ impl Vec { self.dedup_by(|a, b| key(a) == key(b)) } - /// Removes consecutive elements in the vector according to a predicate. + /// Removes all but the first of consecutive elements in the vector satisfying a given equality + /// relation. /// /// The `same_bucket` function is passed references to two elements from the vector, and - /// returns `true` if the elements compare equal, or `false` if they do not. Only the first - /// of adjacent equal items is kept. + /// returns `true` if the elements compare equal, or `false` if they do not. The elements are + /// passed in opposite order from their order in the vector, so if `same_bucket(a, b)` returns + /// `true`, `a` is removed. /// /// If the vector is sorted, this removes all duplicates. /// -- cgit 1.4.1-3-g733a5 From 558ce91e09226abb12b70cf03df133224c467376 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Tue, 4 Jul 2017 15:14:08 +0200 Subject: Minor fix in docs for Vec --- src/liballoc/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/liballoc') diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index e118d406ecf..6918e057ab1 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -221,7 +221,7 @@ use raw_vec::RawVec; /// on an empty Vec, it will not allocate memory. Similarly, if you store zero-sized /// types inside a `Vec`, it will not allocate space for them. *Note that in this case /// the `Vec` may not report a [`capacity`] of 0*. `Vec` will allocate if and only -/// if [`mem::size_of::`]` * capacity() > 0`. In general, `Vec`'s allocation +/// if [`mem::size_of::`]`() * capacity() > 0`. In general, `Vec`'s allocation /// details are subtle enough that it is strongly recommended that you only /// free memory allocated by a `Vec` by creating a new `Vec` and dropping it. /// -- cgit 1.4.1-3-g733a5