Skip to content
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

Rollup of 10 pull requests #46312

Merged
merged 39 commits into from
Nov 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
73ed6cf
Implement From<RecvError> for TryRecvError and RecvTimeoutError
ia0 Oct 23, 2017
448215d
Implement From<SendError<T>> for TrySendError<T>
ia0 Oct 30, 2017
6ceb5f4
Stabilize spin_loop_hint
Nov 21, 2017
a115fcd
Remove spin-loop-hint from the unstable book
Nov 22, 2017
5962d7e
Expand docs of <$Int>::from_str_radix, based on that of char::to_digit
SimonSapin Nov 24, 2017
fa6ae4c
Suggest using slice when encountering `let x = ""[..];`
estebank Nov 24, 2017
cde0023
Add `compile-fail` style comments to tests
estebank Nov 25, 2017
aabacf7
Remove semicolon note
colinmarsh19 Nov 25, 2017
ba40f5c
Test for issue #46186
colinmarsh19 Nov 25, 2017
306f4da
Fixed Err by passing "err"
colinmarsh19 Nov 25, 2017
97d8d04
Remove index type check (review comment)
estebank Nov 25, 2017
8e60f72
Added ;
colinmarsh19 Nov 25, 2017
de41d84
Introduce LinkedList::remove_if
udoprog Nov 25, 2017
60aa834
Implement LinkedList::drain_filter
udoprog Nov 25, 2017
3e8883e
Changed from note to span_suggestion_short
colinmarsh19 Nov 26, 2017
4779899
UI test 46186
colinmarsh19 Nov 26, 2017
bbe4c85
Added 46186 stderr
colinmarsh19 Nov 26, 2017
50537e3
Delete bad test file
colinmarsh19 Nov 26, 2017
5d8d04a
Compiletest libc dependency can be unix-only
dtolnay Nov 26, 2017
1be38e0
MIR: Fix value moved diagnose messages
ritiek Nov 23, 2017
f6b80d4
Added .rs extension
colinmarsh19 Nov 26, 2017
096e698
Changed to correct quotes ` `
colinmarsh19 Nov 26, 2017
aabb604
Move "auto trait leak" impl-trait cycle dependency test to ui
estebank Nov 26, 2017
0b2d21e
Make impl-trait ciclical reference error point to def_span
estebank Nov 26, 2017
a326d8d
Document non-obvious behavior of fmt::UpperHex & co for negative inte…
SimonSapin Nov 26, 2017
8a93dec
Make main span in impl-trait ciclic reference point to def_span
estebank Nov 26, 2017
487daab
Fix test
estebank Nov 27, 2017
fa44927
reword to "consider borrowing here: `{suggestion}`"
estebank Nov 26, 2017
d5e8b61
Change the stabilization version to 1.24.0
Nov 27, 2017
2f012e4
Rollup merge of #45506 - ia0:mpsc_recv_error_from, r=alexcrichton
kennytm Nov 27, 2017
aa99bd9
Rollup merge of #46174 - stjepang:stabilize-spinloophint, r=sfackler
kennytm Nov 27, 2017
26330b1
Rollup merge of #46231 - ritiek:verbs, r=arielb1
kennytm Nov 27, 2017
840e6c1
Rollup merge of #46240 - SimonSapin:from_str_radix-docs, r=estebank
kennytm Nov 27, 2017
a60ffa0
Rollup merge of #46249 - estebank:suggest-slice, r=arielb1
kennytm Nov 27, 2017
f33edd2
Rollup merge of #46258 - colinmarsh19:master, r=estebank
kennytm Nov 27, 2017
7707b18
Rollup merge of #46262 - udoprog:linked-list-remove-if, r=dtolnay
kennytm Nov 27, 2017
81ba352
Rollup merge of #46275 - dtolnay:compiletest-libc, r=Mark-Simulacrum
kennytm Nov 27, 2017
8dd10e6
Rollup merge of #46282 - estebank:impl-trait-cicle-span, r=arielb1
kennytm Nov 27, 2017
83a6f38
Rollup merge of #46285 - SimonSapin:twos-complement, r=GuillaumeGomez
kennytm Nov 27, 2017
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

This file was deleted.

139 changes: 139 additions & 0 deletions src/liballoc/linked_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,28 @@ impl<T> LinkedList<T> {
node
})
}

/// Unlinks the specified node from the current list.
///
/// Warning: this will not check that the provided node belongs to the current list.
#[inline]
unsafe fn unlink_node(&mut self, mut node: Shared<Node<T>>) {
let node = node.as_mut();

match node.prev {
Some(mut prev) => prev.as_mut().next = node.next.clone(),
// this node is the head node
None => self.head = node.next.clone(),
};

match node.next {
Some(mut next) => next.as_mut().prev = node.prev.clone(),
// this node is the tail node
None => self.tail = node.prev.clone(),
};

self.len -= 1;
}
}

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -722,6 +744,49 @@ impl<T> LinkedList<T> {
second_part
}

/// Creates an iterator which uses a closure to determine if an element should be removed.
///
/// If the closure returns true, then the element is removed and yielded.
/// If the closure returns false, it will try again, and call the closure on the next element,
/// seeing if it passes the test.
///
/// Note that `drain_filter` lets you mutate every element in the filter closure, regardless of
/// whether you choose to keep or remove it.
///
/// # Examples
///
/// Splitting a list into evens and odds, reusing the original list:
///
/// ```
/// #![feature(drain_filter)]
/// use std::collections::LinkedList;
///
/// let mut numbers: LinkedList<u32> = LinkedList::new();
/// numbers.extend(&[1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]);
///
/// let evens = numbers.drain_filter(|x| *x % 2 == 0).collect::<LinkedList<_>>();
/// let odds = numbers;
///
/// assert_eq!(evens.into_iter().collect::<Vec<_>>(), vec![2, 4, 6, 8, 14]);
/// assert_eq!(odds.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 9, 11, 13, 15]);
/// ```
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
pub fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<T, F>
where F: FnMut(&mut T) -> bool
{
// avoid borrow issues.
let it = self.head;
let old_len = self.len;

DrainFilter {
list: self,
it: it,
pred: filter,
idx: 0,
old_len: old_len,
}
}

/// Returns a place for insertion at the front of the list.
///
/// Using this method with placement syntax is equivalent to
Expand Down Expand Up @@ -967,6 +1032,56 @@ impl<'a, T> IterMut<'a, T> {
}
}

/// An iterator produced by calling `drain_filter` on LinkedList.
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
pub struct DrainFilter<'a, T: 'a, F: 'a>
where F: FnMut(&mut T) -> bool,
{
list: &'a mut LinkedList<T>,
it: Option<Shared<Node<T>>>,
pred: F,
idx: usize,
old_len: usize,
}

#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
impl<'a, T, F> Iterator for DrainFilter<'a, T, F>
where F: FnMut(&mut T) -> bool,
{
type Item = T;

fn next(&mut self) -> Option<T> {
while let Some(mut node) = self.it {
unsafe {
self.it = node.as_ref().next;
self.idx += 1;

if (self.pred)(&mut node.as_mut().element) {
self.list.unlink_node(node);
return Some(Box::from_raw(node.as_ptr()).element);
}
}
}

None
}

fn size_hint(&self) -> (usize, Option<usize>) {
(0, Some(self.old_len - self.idx))
}
}

#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
impl<'a, T: 'a + fmt::Debug, F> fmt::Debug for DrainFilter<'a, T, F>
where F: FnMut(&mut T) -> bool
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("DrainFilter")
.field(&self.list)
.finish()
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Iterator for IntoIter<T> {
type Item = T;
Expand Down Expand Up @@ -1509,4 +1624,28 @@ mod tests {
}
assert_eq!(i, v.len());
}

#[test]
fn drain_filter_test() {
let mut m: LinkedList<u32> = LinkedList::new();
m.extend(&[1, 2, 3, 4, 5, 6]);
let deleted = m.drain_filter(|v| *v < 4).collect::<Vec<_>>();

check_links(&m);

assert_eq!(deleted, &[1, 2, 3]);
assert_eq!(m.into_iter().collect::<Vec<_>>(), &[4, 5, 6]);
}

#[test]
fn drain_to_empty_test() {
let mut m: LinkedList<u32> = LinkedList::new();
m.extend(&[1, 2, 3, 4, 5, 6]);
let deleted = m.drain_filter(|_| true).collect::<Vec<_>>();

check_links(&m);

assert_eq!(deleted, &[1, 2, 3, 4, 5, 6]);
assert_eq!(m.into_iter().collect::<Vec<_>>(), &[]);
}
}
188 changes: 188 additions & 0 deletions src/liballoc/tests/linked_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,3 +366,191 @@ fn test_contains() {

assert!(!l.contains(&3));
}

#[test]
fn drain_filter_empty() {
let mut list: LinkedList<i32> = LinkedList::new();

{
let mut iter = list.drain_filter(|_| true);
assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next(), None);
assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next(), None);
assert_eq!(iter.size_hint(), (0, Some(0)));
}

assert_eq!(list.len(), 0);
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![]);
}

#[test]
fn drain_filter_zst() {
let mut list: LinkedList<_> = vec![(), (), (), (), ()].into_iter().collect();
let initial_len = list.len();
let mut count = 0;

{
let mut iter = list.drain_filter(|_| true);
assert_eq!(iter.size_hint(), (0, Some(initial_len)));
while let Some(_) = iter.next() {
count += 1;
assert_eq!(iter.size_hint(), (0, Some(initial_len - count)));
}
assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next(), None);
assert_eq!(iter.size_hint(), (0, Some(0)));
}

assert_eq!(count, initial_len);
assert_eq!(list.len(), 0);
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![]);
}

#[test]
fn drain_filter_false() {
let mut list: LinkedList<_> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect();

let initial_len = list.len();
let mut count = 0;

{
let mut iter = list.drain_filter(|_| false);
assert_eq!(iter.size_hint(), (0, Some(initial_len)));
for _ in iter.by_ref() {
count += 1;
}
assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next(), None);
assert_eq!(iter.size_hint(), (0, Some(0)));
}

assert_eq!(count, 0);
assert_eq!(list.len(), initial_len);
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
}

#[test]
fn drain_filter_true() {
let mut list: LinkedList<_> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect();

let initial_len = list.len();
let mut count = 0;

{
let mut iter = list.drain_filter(|_| true);
assert_eq!(iter.size_hint(), (0, Some(initial_len)));
while let Some(_) = iter.next() {
count += 1;
assert_eq!(iter.size_hint(), (0, Some(initial_len - count)));
}
assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next(), None);
assert_eq!(iter.size_hint(), (0, Some(0)));
}

assert_eq!(count, initial_len);
assert_eq!(list.len(), 0);
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![]);
}

#[test]
fn drain_filter_complex() {

{ // [+xxx++++++xxxxx++++x+x++]
let mut list = vec![
1,
2, 4, 6,
7, 9, 11, 13, 15, 17,
18, 20, 22, 24, 26,
27, 29, 31, 33,
34,
35,
36,
37, 39
].into_iter().collect::<LinkedList<_>>();

let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
assert_eq!(removed.len(), 10);
assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);

assert_eq!(list.len(), 14);
assert_eq!(
list.into_iter().collect::<Vec<_>>(),
vec![1, 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]
);
}

{ // [xxx++++++xxxxx++++x+x++]
let mut list = vec![
2, 4, 6,
7, 9, 11, 13, 15, 17,
18, 20, 22, 24, 26,
27, 29, 31, 33,
34,
35,
36,
37, 39
].into_iter().collect::<LinkedList<_>>();

let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
assert_eq!(removed.len(), 10);
assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);

assert_eq!(list.len(), 13);
assert_eq!(
list.into_iter().collect::<Vec<_>>(),
vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]
);
}

{ // [xxx++++++xxxxx++++x+x]
let mut list = vec![
2, 4, 6,
7, 9, 11, 13, 15, 17,
18, 20, 22, 24, 26,
27, 29, 31, 33,
34,
35,
36
].into_iter().collect::<LinkedList<_>>();

let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
assert_eq!(removed.len(), 10);
assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);

assert_eq!(list.len(), 11);
assert_eq!(
list.into_iter().collect::<Vec<_>>(),
vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35]
);
}

{ // [xxxxxxxxxx+++++++++++]
let mut list = vec![
2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
1, 3, 5, 7, 9, 11, 13, 15, 17, 19
].into_iter().collect::<LinkedList<_>>();

let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
assert_eq!(removed.len(), 10);
assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);

assert_eq!(list.len(), 10);
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
}

{ // [+++++++++++xxxxxxxxxx]
let mut list = vec![
1, 3, 5, 7, 9, 11, 13, 15, 17, 19,
2, 4, 6, 8, 10, 12, 14, 16, 18, 20
].into_iter().collect::<LinkedList<_>>();

let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
assert_eq!(removed.len(), 10);
assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);

assert_eq!(list.len(), 10);
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
}
}
Loading