Skip to content

Rollup of 10 pull requests #37093

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 29 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
dc97341
Remove duplicate test.
SimonSapin Sep 26, 2016
f14f4db
Move Vec::dedup tests from slice.rs to vec.rs
SimonSapin Sep 26, 2016
d9e6430
Add two functions to check type of SockAddr
achanda Sep 27, 2016
dd19bf0
Support importing inaccessible `extern crate`s with a warning again.
jseyfried Oct 7, 2016
4080efd
Add regression test.
jseyfried Oct 7, 2016
fd073cf
Don't construct `PathBuf` ownership if we don't need it.
frewsxcv Oct 8, 2016
f410da5
Add doc comments describing fields on `externalfiles::ExternalHtml`.
frewsxcv Oct 8, 2016
7be14ee
Refactor away `load_or_return` macro.
frewsxcv Oct 9, 2016
ba20da1
Make `ExternalHtml::load` short-circuited.
frewsxcv Oct 9, 2016
e4f066f
Remove unnecessary `pub` function classifier.
frewsxcv Oct 9, 2016
b043e11
Avoid allocations in `Decoder::read_str`.
nnethercote Oct 9, 2016
4df0f3f
Error monitor should emit error to stderr instead of stdout
nrc Oct 10, 2016
f9c73ad
Add comparison operators to boolean const eval.
Mark-Simulacrum Oct 9, 2016
60a4b69
Expand `#[derive]` attribute macro invocations last.
jseyfried Oct 10, 2016
448d6ad
Test derive expansion ordering.
jseyfried Oct 10, 2016
5e91c07
Move IdxSetBuf and BitSlice to rustc_data_structures
wesleywiser Oct 6, 2016
be34bac
Add Vec::dedup_by and Vec::dedup_by_key
SimonSapin Sep 26, 2016
401f1c4
Merge two `impl<T> Vec<T>` blocks.
SimonSapin Sep 26, 2016
c5068a4
Cache conscious hashmap table
arthurprs Sep 24, 2016
298c313
Rollup merge of #36692 - arthurprs:hashmap-layout, r=alexcrichton
Oct 11, 2016
10d7e12
Rollup merge of #36743 - SimonSapin:dedup-by, r=alexcrichton
Oct 11, 2016
6f81f2f
Rollup merge of #36762 - achanda:sockaddr_type, r=alexcrichton
Oct 11, 2016
3983b87
Rollup merge of #36991 - wesleywiser:fixme_1, r=arielb1
Oct 11, 2016
fa1140b
Rollup merge of #37023 - jseyfried:fix_extern_crate_back_compat, r=nrc
Oct 11, 2016
9289e41
Rollup merge of #37050 - frewsxcv:librustdoc, r=alexcrichton
Oct 11, 2016
0a9174a
Rollup merge of #37056 - Mark-Simulacrum:fix-bool-comparison, r=bluss
Oct 11, 2016
57f664f
Rollup merge of #37064 - nnethercote:read_str, r=eddyb
Oct 11, 2016
a44bb87
Rollup merge of #37066 - nrc:stderr, r=alexcrichton
Oct 11, 2016
3cf07a8
Rollup merge of #37067 - jseyfried:expand_derives_last, r=alexcrichton
Oct 11, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
209 changes: 126 additions & 83 deletions src/libcollections/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,130 @@ impl<T> Vec<T> {
}
}

/// Removes consecutive elements in the vector that resolve to the same key.
///
/// If the vector is sorted, this removes all duplicates.
///
/// # Examples
///
/// ```
/// #![feature(dedup_by)]
///
/// let mut vec = vec![10, 20, 21, 30, 20];
///
/// vec.dedup_by_key(|i| *i / 10);
///
/// assert_eq!(vec, [10, 20, 30, 20]);
/// ```
#[unstable(feature = "dedup_by", reason = "recently added", issue = "37087")]
#[inline]
pub fn dedup_by_key<F, K>(&mut self, mut key: F) where F: FnMut(&mut T) -> K, K: PartialEq {
self.dedup_by(|a, b| key(a) == key(b))
}

/// Removes consecutive elements in the vector that resolve to the same key.
///
/// If the vector is sorted, this removes all duplicates.
///
/// # Examples
///
/// ```
/// #![feature(dedup_by)]
/// use std::ascii::AsciiExt;
///
/// let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"];
///
/// vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
///
/// assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
/// ```
#[unstable(feature = "dedup_by", reason = "recently added", issue = "37087")]
pub fn dedup_by<F>(&mut self, mut same_bucket: F) where F: FnMut(&mut T, &mut T) -> bool {
unsafe {
// Although we have a mutable reference to `self`, we cannot make
// *arbitrary* changes. The `PartialEq` comparisons could panic, so we
// must ensure that the vector is in a valid state at all time.
//
// The way that we handle this is by using swaps; we iterate
// over all the elements, swapping as we go so that at the end
// the elements we wish to keep are in the front, and those we
// wish to reject are at the back. We can then truncate the
// vector. This operation is still O(n).
//
// Example: We start in this state, where `r` represents "next
// read" and `w` represents "next_write`.
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 1 | 2 | 3 | 3 |
// +---+---+---+---+---+---+
// w
//
// Comparing self[r] against self[w-1], this is not a duplicate, so
// we swap self[r] and self[w] (no effect as r==w) and then increment both
// r and w, leaving us with:
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 1 | 2 | 3 | 3 |
// +---+---+---+---+---+---+
// w
//
// Comparing self[r] against self[w-1], this value is a duplicate,
// so we increment `r` but leave everything else unchanged:
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 1 | 2 | 3 | 3 |
// +---+---+---+---+---+---+
// w
//
// Comparing self[r] against self[w-1], this is not a duplicate,
// so swap self[r] and self[w] and advance r and w:
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 2 | 1 | 3 | 3 |
// +---+---+---+---+---+---+
// w
//
// Not a duplicate, repeat:
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 2 | 3 | 1 | 3 |
// +---+---+---+---+---+---+
// w
//
// Duplicate, advance r. End of vec. Truncate to w.

let ln = self.len();
if ln <= 1 {
return;
}

// Avoid bounds checks by using raw pointers.
let p = self.as_mut_ptr();
let mut r: usize = 1;
let mut w: usize = 1;

while r < ln {
let p_r = p.offset(r as isize);
let p_wm1 = p.offset((w - 1) as isize);
if !same_bucket(&mut *p_r, &mut *p_wm1) {
if r != w {
let p_w = p_wm1.offset(1);
mem::swap(&mut *p_r, &mut *p_w);
}
w += 1;
}
r += 1;
}

self.truncate(w);
}
}

/// Appends an element to the back of a collection.
///
/// # Panics
Expand Down Expand Up @@ -1155,90 +1279,9 @@ impl<T: PartialEq> Vec<T> {
/// assert_eq!(vec, [1, 2, 3, 2]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn dedup(&mut self) {
unsafe {
// Although we have a mutable reference to `self`, we cannot make
// *arbitrary* changes. The `PartialEq` comparisons could panic, so we
// must ensure that the vector is in a valid state at all time.
//
// The way that we handle this is by using swaps; we iterate
// over all the elements, swapping as we go so that at the end
// the elements we wish to keep are in the front, and those we
// wish to reject are at the back. We can then truncate the
// vector. This operation is still O(n).
//
// Example: We start in this state, where `r` represents "next
// read" and `w` represents "next_write`.
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 1 | 2 | 3 | 3 |
// +---+---+---+---+---+---+
// w
//
// Comparing self[r] against self[w-1], this is not a duplicate, so
// we swap self[r] and self[w] (no effect as r==w) and then increment both
// r and w, leaving us with:
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 1 | 2 | 3 | 3 |
// +---+---+---+---+---+---+
// w
//
// Comparing self[r] against self[w-1], this value is a duplicate,
// so we increment `r` but leave everything else unchanged:
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 1 | 2 | 3 | 3 |
// +---+---+---+---+---+---+
// w
//
// Comparing self[r] against self[w-1], this is not a duplicate,
// so swap self[r] and self[w] and advance r and w:
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 2 | 1 | 3 | 3 |
// +---+---+---+---+---+---+
// w
//
// Not a duplicate, repeat:
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 2 | 3 | 1 | 3 |
// +---+---+---+---+---+---+
// w
//
// Duplicate, advance r. End of vec. Truncate to w.

let ln = self.len();
if ln <= 1 {
return;
}

// Avoid bounds checks by using raw pointers.
let p = self.as_mut_ptr();
let mut r: usize = 1;
let mut w: usize = 1;

while r < ln {
let p_r = p.offset(r as isize);
let p_wm1 = p.offset((w - 1) as isize);
if *p_r != *p_wm1 {
if r != w {
let p_w = p_wm1.offset(1);
mem::swap(&mut *p_r, &mut *p_w);
}
w += 1;
}
r += 1;
}

self.truncate(w);
}
self.dedup_by(|a, b| a == b)
}
}

Expand Down
1 change: 1 addition & 0 deletions src/libcollectionstest/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#![feature(collections)]
#![feature(collections_bound)]
#![feature(const_fn)]
#![feature(dedup_by)]
#![feature(enumset)]
#![feature(pattern)]
#![feature(rand)]
Expand Down
41 changes: 0 additions & 41 deletions src/libcollectionstest/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,47 +315,6 @@ fn test_clear() {
// If the unsafe block didn't drop things properly, we blow up here.
}

#[test]
fn test_dedup() {
fn case(a: Vec<i32>, b: Vec<i32>) {
let mut v = a;
v.dedup();
assert_eq!(v, b);
}
case(vec![], vec![]);
case(vec![1], vec![1]);
case(vec![1, 1], vec![1]);
case(vec![1, 2, 3], vec![1, 2, 3]);
case(vec![1, 1, 2, 3], vec![1, 2, 3]);
case(vec![1, 2, 2, 3], vec![1, 2, 3]);
case(vec![1, 2, 3, 3], vec![1, 2, 3]);
case(vec![1, 1, 2, 2, 2, 3, 3], vec![1, 2, 3]);
}

#[test]
fn test_dedup_unique() {
let mut v0: Vec<Box<_>> = vec![box 1, box 1, box 2, box 3];
v0.dedup();
let mut v1: Vec<Box<_>> = vec![box 1, box 2, box 2, box 3];
v1.dedup();
let mut v2: Vec<Box<_>> = vec![box 1, box 2, box 3, box 3];
v2.dedup();
// If the boxed pointers were leaked or otherwise misused, valgrind
// and/or rt should raise errors.
}

#[test]
fn test_dedup_shared() {
let mut v0: Vec<Box<_>> = vec![box 1, box 1, box 2, box 3];
v0.dedup();
let mut v1: Vec<Box<_>> = vec![box 1, box 2, box 2, box 3];
v1.dedup();
let mut v2: Vec<Box<_>> = vec![box 1, box 2, box 3, box 3];
v2.dedup();
// If the pointers were leaked or otherwise misused, valgrind and/or
// rt should raise errors.
}

#[test]
fn test_retain() {
let mut v = vec![1, 2, 3, 4, 5];
Expand Down
55 changes: 55 additions & 0 deletions src/libcollectionstest/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::ascii::AsciiExt;
use std::borrow::Cow;
use std::iter::{FromIterator, repeat};
use std::mem::size_of;
Expand Down Expand Up @@ -213,6 +214,60 @@ fn test_retain() {
assert_eq!(vec, [2, 4]);
}

#[test]
fn test_dedup() {
fn case(a: Vec<i32>, b: Vec<i32>) {
let mut v = a;
v.dedup();
assert_eq!(v, b);
}
case(vec![], vec![]);
case(vec![1], vec![1]);
case(vec![1, 1], vec![1]);
case(vec![1, 2, 3], vec![1, 2, 3]);
case(vec![1, 1, 2, 3], vec![1, 2, 3]);
case(vec![1, 2, 2, 3], vec![1, 2, 3]);
case(vec![1, 2, 3, 3], vec![1, 2, 3]);
case(vec![1, 1, 2, 2, 2, 3, 3], vec![1, 2, 3]);
}

#[test]
fn test_dedup_by_key() {
fn case(a: Vec<i32>, b: Vec<i32>) {
let mut v = a;
v.dedup_by_key(|i| *i / 10);
assert_eq!(v, b);
}
case(vec![], vec![]);
case(vec![10], vec![10]);
case(vec![10, 11], vec![10]);
case(vec![10, 20, 30], vec![10, 20, 30]);
case(vec![10, 11, 20, 30], vec![10, 20, 30]);
case(vec![10, 20, 21, 30], vec![10, 20, 30]);
case(vec![10, 20, 30, 31], vec![10, 20, 30]);
case(vec![10, 11, 20, 21, 22, 30, 31], vec![10, 20, 30]);
}

#[test]
fn test_dedup_by() {
let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"];
vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));

assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
}

#[test]
fn test_dedup_unique() {
let mut v0: Vec<Box<_>> = vec![box 1, box 1, box 2, box 3];
v0.dedup();
let mut v1: Vec<Box<_>> = vec![box 1, box 2, box 2, box 3];
v1.dedup();
let mut v2: Vec<Box<_>> = vec![box 1, box 2, box 3, box 3];
v2.dedup();
// If the boxed pointers were leaked or otherwise misused, valgrind
// and/or rt should raise errors.
}

#[test]
fn zero_sized_values() {
let mut v = Vec::new();
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

use syntax::ast::NodeId;
use rustc::mir::repr::{BasicBlock, Mir};
use rustc_data_structures::bitslice::bits_to_string;
use rustc_data_structures::indexed_set::{IdxSet};
use rustc_data_structures::indexed_vec::Idx;

use dot;
Expand All @@ -27,8 +29,6 @@ use std::path::Path;

use super::super::MoveDataParamEnv;
use super::super::MirBorrowckCtxtPreDataflow;
use bitslice::bits_to_string;
use indexed_set::{IdxSet};
use super::{BitDenotation, DataflowState};

impl<O: BitDenotation> DataflowState<O> {
Expand Down
7 changes: 3 additions & 4 deletions src/librustc_borrowck/borrowck/mir/dataflow/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@

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

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

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

use bitslice::BitSlice; // adds set_bit/get_bit to &[usize] bitvector rep.
use bitslice::{BitwiseOperator};
use indexed_set::{IdxSet};

// Dataflow analyses are built upon some interpretation of the
// bitvectors attached to each basic block, represented via a
// zero-sized structure.
Expand Down
Loading