Skip to content

Commit ccb8b3e

Browse files
authored
Auto merge of #37093 - jonathandturner:rollup, r=jonathandturner
Rollup of 10 pull requests - Successful merges: #36692, #36743, #36762, #36991, #37023, #37050, #37056, #37064, #37066, #37067 - Failed merges:
2 parents 0b2c356 + 3cf07a8 commit ccb8b3e

File tree

31 files changed

+436
-283
lines changed

31 files changed

+436
-283
lines changed

src/libcollections/vec.rs

+126-83
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,130 @@ impl<T> Vec<T> {
781781
}
782782
}
783783

784+
/// Removes consecutive elements in the vector that resolve to the same key.
785+
///
786+
/// If the vector is sorted, this removes all duplicates.
787+
///
788+
/// # Examples
789+
///
790+
/// ```
791+
/// #![feature(dedup_by)]
792+
///
793+
/// let mut vec = vec![10, 20, 21, 30, 20];
794+
///
795+
/// vec.dedup_by_key(|i| *i / 10);
796+
///
797+
/// assert_eq!(vec, [10, 20, 30, 20]);
798+
/// ```
799+
#[unstable(feature = "dedup_by", reason = "recently added", issue = "37087")]
800+
#[inline]
801+
pub fn dedup_by_key<F, K>(&mut self, mut key: F) where F: FnMut(&mut T) -> K, K: PartialEq {
802+
self.dedup_by(|a, b| key(a) == key(b))
803+
}
804+
805+
/// Removes consecutive elements in the vector that resolve to the same key.
806+
///
807+
/// If the vector is sorted, this removes all duplicates.
808+
///
809+
/// # Examples
810+
///
811+
/// ```
812+
/// #![feature(dedup_by)]
813+
/// use std::ascii::AsciiExt;
814+
///
815+
/// let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"];
816+
///
817+
/// vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
818+
///
819+
/// assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
820+
/// ```
821+
#[unstable(feature = "dedup_by", reason = "recently added", issue = "37087")]
822+
pub fn dedup_by<F>(&mut self, mut same_bucket: F) where F: FnMut(&mut T, &mut T) -> bool {
823+
unsafe {
824+
// Although we have a mutable reference to `self`, we cannot make
825+
// *arbitrary* changes. The `PartialEq` comparisons could panic, so we
826+
// must ensure that the vector is in a valid state at all time.
827+
//
828+
// The way that we handle this is by using swaps; we iterate
829+
// over all the elements, swapping as we go so that at the end
830+
// the elements we wish to keep are in the front, and those we
831+
// wish to reject are at the back. We can then truncate the
832+
// vector. This operation is still O(n).
833+
//
834+
// Example: We start in this state, where `r` represents "next
835+
// read" and `w` represents "next_write`.
836+
//
837+
// r
838+
// +---+---+---+---+---+---+
839+
// | 0 | 1 | 1 | 2 | 3 | 3 |
840+
// +---+---+---+---+---+---+
841+
// w
842+
//
843+
// Comparing self[r] against self[w-1], this is not a duplicate, so
844+
// we swap self[r] and self[w] (no effect as r==w) and then increment both
845+
// r and w, leaving us with:
846+
//
847+
// r
848+
// +---+---+---+---+---+---+
849+
// | 0 | 1 | 1 | 2 | 3 | 3 |
850+
// +---+---+---+---+---+---+
851+
// w
852+
//
853+
// Comparing self[r] against self[w-1], this value is a duplicate,
854+
// so we increment `r` but leave everything else unchanged:
855+
//
856+
// r
857+
// +---+---+---+---+---+---+
858+
// | 0 | 1 | 1 | 2 | 3 | 3 |
859+
// +---+---+---+---+---+---+
860+
// w
861+
//
862+
// Comparing self[r] against self[w-1], this is not a duplicate,
863+
// so swap self[r] and self[w] and advance r and w:
864+
//
865+
// r
866+
// +---+---+---+---+---+---+
867+
// | 0 | 1 | 2 | 1 | 3 | 3 |
868+
// +---+---+---+---+---+---+
869+
// w
870+
//
871+
// Not a duplicate, repeat:
872+
//
873+
// r
874+
// +---+---+---+---+---+---+
875+
// | 0 | 1 | 2 | 3 | 1 | 3 |
876+
// +---+---+---+---+---+---+
877+
// w
878+
//
879+
// Duplicate, advance r. End of vec. Truncate to w.
880+
881+
let ln = self.len();
882+
if ln <= 1 {
883+
return;
884+
}
885+
886+
// Avoid bounds checks by using raw pointers.
887+
let p = self.as_mut_ptr();
888+
let mut r: usize = 1;
889+
let mut w: usize = 1;
890+
891+
while r < ln {
892+
let p_r = p.offset(r as isize);
893+
let p_wm1 = p.offset((w - 1) as isize);
894+
if !same_bucket(&mut *p_r, &mut *p_wm1) {
895+
if r != w {
896+
let p_w = p_wm1.offset(1);
897+
mem::swap(&mut *p_r, &mut *p_w);
898+
}
899+
w += 1;
900+
}
901+
r += 1;
902+
}
903+
904+
self.truncate(w);
905+
}
906+
}
907+
784908
/// Appends an element to the back of a collection.
785909
///
786910
/// # Panics
@@ -1155,90 +1279,9 @@ impl<T: PartialEq> Vec<T> {
11551279
/// assert_eq!(vec, [1, 2, 3, 2]);
11561280
/// ```
11571281
#[stable(feature = "rust1", since = "1.0.0")]
1282+
#[inline]
11581283
pub fn dedup(&mut self) {
1159-
unsafe {
1160-
// Although we have a mutable reference to `self`, we cannot make
1161-
// *arbitrary* changes. The `PartialEq` comparisons could panic, so we
1162-
// must ensure that the vector is in a valid state at all time.
1163-
//
1164-
// The way that we handle this is by using swaps; we iterate
1165-
// over all the elements, swapping as we go so that at the end
1166-
// the elements we wish to keep are in the front, and those we
1167-
// wish to reject are at the back. We can then truncate the
1168-
// vector. This operation is still O(n).
1169-
//
1170-
// Example: We start in this state, where `r` represents "next
1171-
// read" and `w` represents "next_write`.
1172-
//
1173-
// r
1174-
// +---+---+---+---+---+---+
1175-
// | 0 | 1 | 1 | 2 | 3 | 3 |
1176-
// +---+---+---+---+---+---+
1177-
// w
1178-
//
1179-
// Comparing self[r] against self[w-1], this is not a duplicate, so
1180-
// we swap self[r] and self[w] (no effect as r==w) and then increment both
1181-
// r and w, leaving us with:
1182-
//
1183-
// r
1184-
// +---+---+---+---+---+---+
1185-
// | 0 | 1 | 1 | 2 | 3 | 3 |
1186-
// +---+---+---+---+---+---+
1187-
// w
1188-
//
1189-
// Comparing self[r] against self[w-1], this value is a duplicate,
1190-
// so we increment `r` but leave everything else unchanged:
1191-
//
1192-
// r
1193-
// +---+---+---+---+---+---+
1194-
// | 0 | 1 | 1 | 2 | 3 | 3 |
1195-
// +---+---+---+---+---+---+
1196-
// w
1197-
//
1198-
// Comparing self[r] against self[w-1], this is not a duplicate,
1199-
// so swap self[r] and self[w] and advance r and w:
1200-
//
1201-
// r
1202-
// +---+---+---+---+---+---+
1203-
// | 0 | 1 | 2 | 1 | 3 | 3 |
1204-
// +---+---+---+---+---+---+
1205-
// w
1206-
//
1207-
// Not a duplicate, repeat:
1208-
//
1209-
// r
1210-
// +---+---+---+---+---+---+
1211-
// | 0 | 1 | 2 | 3 | 1 | 3 |
1212-
// +---+---+---+---+---+---+
1213-
// w
1214-
//
1215-
// Duplicate, advance r. End of vec. Truncate to w.
1216-
1217-
let ln = self.len();
1218-
if ln <= 1 {
1219-
return;
1220-
}
1221-
1222-
// Avoid bounds checks by using raw pointers.
1223-
let p = self.as_mut_ptr();
1224-
let mut r: usize = 1;
1225-
let mut w: usize = 1;
1226-
1227-
while r < ln {
1228-
let p_r = p.offset(r as isize);
1229-
let p_wm1 = p.offset((w - 1) as isize);
1230-
if *p_r != *p_wm1 {
1231-
if r != w {
1232-
let p_w = p_wm1.offset(1);
1233-
mem::swap(&mut *p_r, &mut *p_w);
1234-
}
1235-
w += 1;
1236-
}
1237-
r += 1;
1238-
}
1239-
1240-
self.truncate(w);
1241-
}
1284+
self.dedup_by(|a, b| a == b)
12421285
}
12431286
}
12441287

src/libcollectionstest/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#![feature(collections)]
1717
#![feature(collections_bound)]
1818
#![feature(const_fn)]
19+
#![feature(dedup_by)]
1920
#![feature(enumset)]
2021
#![feature(pattern)]
2122
#![feature(rand)]

src/libcollectionstest/slice.rs

-41
Original file line numberDiff line numberDiff line change
@@ -315,47 +315,6 @@ fn test_clear() {
315315
// If the unsafe block didn't drop things properly, we blow up here.
316316
}
317317

318-
#[test]
319-
fn test_dedup() {
320-
fn case(a: Vec<i32>, b: Vec<i32>) {
321-
let mut v = a;
322-
v.dedup();
323-
assert_eq!(v, b);
324-
}
325-
case(vec![], vec![]);
326-
case(vec![1], vec![1]);
327-
case(vec![1, 1], vec![1]);
328-
case(vec![1, 2, 3], vec![1, 2, 3]);
329-
case(vec![1, 1, 2, 3], vec![1, 2, 3]);
330-
case(vec![1, 2, 2, 3], vec![1, 2, 3]);
331-
case(vec![1, 2, 3, 3], vec![1, 2, 3]);
332-
case(vec![1, 1, 2, 2, 2, 3, 3], vec![1, 2, 3]);
333-
}
334-
335-
#[test]
336-
fn test_dedup_unique() {
337-
let mut v0: Vec<Box<_>> = vec![box 1, box 1, box 2, box 3];
338-
v0.dedup();
339-
let mut v1: Vec<Box<_>> = vec![box 1, box 2, box 2, box 3];
340-
v1.dedup();
341-
let mut v2: Vec<Box<_>> = vec![box 1, box 2, box 3, box 3];
342-
v2.dedup();
343-
// If the boxed pointers were leaked or otherwise misused, valgrind
344-
// and/or rt should raise errors.
345-
}
346-
347-
#[test]
348-
fn test_dedup_shared() {
349-
let mut v0: Vec<Box<_>> = vec![box 1, box 1, box 2, box 3];
350-
v0.dedup();
351-
let mut v1: Vec<Box<_>> = vec![box 1, box 2, box 2, box 3];
352-
v1.dedup();
353-
let mut v2: Vec<Box<_>> = vec![box 1, box 2, box 3, box 3];
354-
v2.dedup();
355-
// If the pointers were leaked or otherwise misused, valgrind and/or
356-
// rt should raise errors.
357-
}
358-
359318
#[test]
360319
fn test_retain() {
361320
let mut v = vec![1, 2, 3, 4, 5];

src/libcollectionstest/vec.rs

+55
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use std::ascii::AsciiExt;
1112
use std::borrow::Cow;
1213
use std::iter::{FromIterator, repeat};
1314
use std::mem::size_of;
@@ -213,6 +214,60 @@ fn test_retain() {
213214
assert_eq!(vec, [2, 4]);
214215
}
215216

217+
#[test]
218+
fn test_dedup() {
219+
fn case(a: Vec<i32>, b: Vec<i32>) {
220+
let mut v = a;
221+
v.dedup();
222+
assert_eq!(v, b);
223+
}
224+
case(vec![], vec![]);
225+
case(vec![1], vec![1]);
226+
case(vec![1, 1], vec![1]);
227+
case(vec![1, 2, 3], vec![1, 2, 3]);
228+
case(vec![1, 1, 2, 3], vec![1, 2, 3]);
229+
case(vec![1, 2, 2, 3], vec![1, 2, 3]);
230+
case(vec![1, 2, 3, 3], vec![1, 2, 3]);
231+
case(vec![1, 1, 2, 2, 2, 3, 3], vec![1, 2, 3]);
232+
}
233+
234+
#[test]
235+
fn test_dedup_by_key() {
236+
fn case(a: Vec<i32>, b: Vec<i32>) {
237+
let mut v = a;
238+
v.dedup_by_key(|i| *i / 10);
239+
assert_eq!(v, b);
240+
}
241+
case(vec![], vec![]);
242+
case(vec![10], vec![10]);
243+
case(vec![10, 11], vec![10]);
244+
case(vec![10, 20, 30], vec![10, 20, 30]);
245+
case(vec![10, 11, 20, 30], vec![10, 20, 30]);
246+
case(vec![10, 20, 21, 30], vec![10, 20, 30]);
247+
case(vec![10, 20, 30, 31], vec![10, 20, 30]);
248+
case(vec![10, 11, 20, 21, 22, 30, 31], vec![10, 20, 30]);
249+
}
250+
251+
#[test]
252+
fn test_dedup_by() {
253+
let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"];
254+
vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
255+
256+
assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
257+
}
258+
259+
#[test]
260+
fn test_dedup_unique() {
261+
let mut v0: Vec<Box<_>> = vec![box 1, box 1, box 2, box 3];
262+
v0.dedup();
263+
let mut v1: Vec<Box<_>> = vec![box 1, box 2, box 2, box 3];
264+
v1.dedup();
265+
let mut v2: Vec<Box<_>> = vec![box 1, box 2, box 3, box 3];
266+
v2.dedup();
267+
// If the boxed pointers were leaked or otherwise misused, valgrind
268+
// and/or rt should raise errors.
269+
}
270+
216271
#[test]
217272
fn zero_sized_values() {
218273
let mut v = Vec::new();

src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
1313
use syntax::ast::NodeId;
1414
use rustc::mir::repr::{BasicBlock, Mir};
15+
use rustc_data_structures::bitslice::bits_to_string;
16+
use rustc_data_structures::indexed_set::{IdxSet};
1517
use rustc_data_structures::indexed_vec::Idx;
1618

1719
use dot;
@@ -27,8 +29,6 @@ use std::path::Path;
2729

2830
use super::super::MoveDataParamEnv;
2931
use super::super::MirBorrowckCtxtPreDataflow;
30-
use bitslice::bits_to_string;
31-
use indexed_set::{IdxSet};
3232
use super::{BitDenotation, DataflowState};
3333

3434
impl<O: BitDenotation> DataflowState<O> {

src/librustc_borrowck/borrowck/mir/dataflow/impls.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010

1111
use rustc::ty::TyCtxt;
1212
use rustc::mir::repr::{self, Mir, Location};
13+
use rustc_data_structures::bitslice::BitSlice; // adds set_bit/get_bit to &[usize] bitvector rep.
14+
use rustc_data_structures::bitslice::{BitwiseOperator};
15+
use rustc_data_structures::indexed_set::{IdxSet};
1316
use rustc_data_structures::indexed_vec::Idx;
1417

1518
use super::super::gather_moves::{MoveOutIndex, MovePathIndex};
@@ -21,10 +24,6 @@ use super::super::on_lookup_result_bits;
2124

2225
use super::{BitDenotation, BlockSets, DataflowOperator};
2326

24-
use bitslice::BitSlice; // adds set_bit/get_bit to &[usize] bitvector rep.
25-
use bitslice::{BitwiseOperator};
26-
use indexed_set::{IdxSet};
27-
2827
// Dataflow analyses are built upon some interpretation of the
2928
// bitvectors attached to each basic block, represented via a
3029
// zero-sized structure.

0 commit comments

Comments
 (0)