Skip to content

Commit d560292

Browse files
committed
Make the Vec::dedup method use slice::partition_dedup internally
1 parent 78bccb3 commit d560292

File tree

2 files changed

+7
-84
lines changed

2 files changed

+7
-84
lines changed

src/liballoc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@
119119
#![feature(exact_chunks)]
120120
#![feature(rustc_const_unstable)]
121121
#![feature(const_vec_new)]
122+
#![feature(slice_partition_dedup)]
122123
#![feature(maybe_uninit)]
123124

124125
// Allow testing this library

src/liballoc/vec.rs

+6-84
Original file line numberDiff line numberDiff line change
@@ -963,90 +963,12 @@ impl<T> Vec<T> {
963963
/// assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
964964
/// ```
965965
#[stable(feature = "dedup_by", since = "1.16.0")]
966-
pub fn dedup_by<F>(&mut self, mut same_bucket: F) where F: FnMut(&mut T, &mut T) -> bool {
967-
unsafe {
968-
// Although we have a mutable reference to `self`, we cannot make
969-
// *arbitrary* changes. The `same_bucket` calls could panic, so we
970-
// must ensure that the vector is in a valid state at all time.
971-
//
972-
// The way that we handle this is by using swaps; we iterate
973-
// over all the elements, swapping as we go so that at the end
974-
// the elements we wish to keep are in the front, and those we
975-
// wish to reject are at the back. We can then truncate the
976-
// vector. This operation is still O(n).
977-
//
978-
// Example: We start in this state, where `r` represents "next
979-
// read" and `w` represents "next_write`.
980-
//
981-
// r
982-
// +---+---+---+---+---+---+
983-
// | 0 | 1 | 1 | 2 | 3 | 3 |
984-
// +---+---+---+---+---+---+
985-
// w
986-
//
987-
// Comparing self[r] against self[w-1], this is not a duplicate, so
988-
// we swap self[r] and self[w] (no effect as r==w) and then increment both
989-
// r and w, leaving us with:
990-
//
991-
// r
992-
// +---+---+---+---+---+---+
993-
// | 0 | 1 | 1 | 2 | 3 | 3 |
994-
// +---+---+---+---+---+---+
995-
// w
996-
//
997-
// Comparing self[r] against self[w-1], this value is a duplicate,
998-
// so we increment `r` but leave everything else unchanged:
999-
//
1000-
// r
1001-
// +---+---+---+---+---+---+
1002-
// | 0 | 1 | 1 | 2 | 3 | 3 |
1003-
// +---+---+---+---+---+---+
1004-
// w
1005-
//
1006-
// Comparing self[r] against self[w-1], this is not a duplicate,
1007-
// so swap self[r] and self[w] and advance r and w:
1008-
//
1009-
// r
1010-
// +---+---+---+---+---+---+
1011-
// | 0 | 1 | 2 | 1 | 3 | 3 |
1012-
// +---+---+---+---+---+---+
1013-
// w
1014-
//
1015-
// Not a duplicate, repeat:
1016-
//
1017-
// r
1018-
// +---+---+---+---+---+---+
1019-
// | 0 | 1 | 2 | 3 | 1 | 3 |
1020-
// +---+---+---+---+---+---+
1021-
// w
1022-
//
1023-
// Duplicate, advance r. End of vec. Truncate to w.
1024-
1025-
let ln = self.len();
1026-
if ln <= 1 {
1027-
return;
1028-
}
1029-
1030-
// Avoid bounds checks by using raw pointers.
1031-
let p = self.as_mut_ptr();
1032-
let mut r: usize = 1;
1033-
let mut w: usize = 1;
1034-
1035-
while r < ln {
1036-
let p_r = p.add(r);
1037-
let p_wm1 = p.add(w - 1);
1038-
if !same_bucket(&mut *p_r, &mut *p_wm1) {
1039-
if r != w {
1040-
let p_w = p_wm1.offset(1);
1041-
mem::swap(&mut *p_r, &mut *p_w);
1042-
}
1043-
w += 1;
1044-
}
1045-
r += 1;
1046-
}
1047-
1048-
self.truncate(w);
1049-
}
966+
pub fn dedup_by<F>(&mut self, same_bucket: F) where F: FnMut(&mut T, &mut T) -> bool {
967+
let len = {
968+
let (dedup, _) = self.as_mut_slice().partition_dedup_by(same_bucket);
969+
dedup.len()
970+
};
971+
self.truncate(len);
1050972
}
1051973

1052974
/// Appends an element to the back of a collection.

0 commit comments

Comments
 (0)