Skip to content

Commit b087a99

Browse files
committed
Auto merge of #46312 - kennytm:rollup, r=kennytm
Rollup of 10 pull requests - Successful merges: #45506, #46174, #46231, #46240, #46249, #46258, #46262, #46275, #46282, #46285 - Failed merges:
2 parents 560a5da + 83a6f38 commit b087a99

File tree

20 files changed

+628
-61
lines changed

20 files changed

+628
-61
lines changed

src/doc/unstable-book/src/library-features/hint-core-should-pause.md

-41
This file was deleted.

src/liballoc/linked_list.rs

+139
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,28 @@ impl<T> LinkedList<T> {
220220
node
221221
})
222222
}
223+
224+
/// Unlinks the specified node from the current list.
225+
///
226+
/// Warning: this will not check that the provided node belongs to the current list.
227+
#[inline]
228+
unsafe fn unlink_node(&mut self, mut node: Shared<Node<T>>) {
229+
let node = node.as_mut();
230+
231+
match node.prev {
232+
Some(mut prev) => prev.as_mut().next = node.next.clone(),
233+
// this node is the head node
234+
None => self.head = node.next.clone(),
235+
};
236+
237+
match node.next {
238+
Some(mut next) => next.as_mut().prev = node.prev.clone(),
239+
// this node is the tail node
240+
None => self.tail = node.prev.clone(),
241+
};
242+
243+
self.len -= 1;
244+
}
223245
}
224246

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

747+
/// Creates an iterator which uses a closure to determine if an element should be removed.
748+
///
749+
/// If the closure returns true, then the element is removed and yielded.
750+
/// If the closure returns false, it will try again, and call the closure on the next element,
751+
/// seeing if it passes the test.
752+
///
753+
/// Note that `drain_filter` lets you mutate every element in the filter closure, regardless of
754+
/// whether you choose to keep or remove it.
755+
///
756+
/// # Examples
757+
///
758+
/// Splitting a list into evens and odds, reusing the original list:
759+
///
760+
/// ```
761+
/// #![feature(drain_filter)]
762+
/// use std::collections::LinkedList;
763+
///
764+
/// let mut numbers: LinkedList<u32> = LinkedList::new();
765+
/// numbers.extend(&[1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]);
766+
///
767+
/// let evens = numbers.drain_filter(|x| *x % 2 == 0).collect::<LinkedList<_>>();
768+
/// let odds = numbers;
769+
///
770+
/// assert_eq!(evens.into_iter().collect::<Vec<_>>(), vec![2, 4, 6, 8, 14]);
771+
/// assert_eq!(odds.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 9, 11, 13, 15]);
772+
/// ```
773+
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
774+
pub fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<T, F>
775+
where F: FnMut(&mut T) -> bool
776+
{
777+
// avoid borrow issues.
778+
let it = self.head;
779+
let old_len = self.len;
780+
781+
DrainFilter {
782+
list: self,
783+
it: it,
784+
pred: filter,
785+
idx: 0,
786+
old_len: old_len,
787+
}
788+
}
789+
725790
/// Returns a place for insertion at the front of the list.
726791
///
727792
/// Using this method with placement syntax is equivalent to
@@ -967,6 +1032,56 @@ impl<'a, T> IterMut<'a, T> {
9671032
}
9681033
}
9691034

1035+
/// An iterator produced by calling `drain_filter` on LinkedList.
1036+
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
1037+
pub struct DrainFilter<'a, T: 'a, F: 'a>
1038+
where F: FnMut(&mut T) -> bool,
1039+
{
1040+
list: &'a mut LinkedList<T>,
1041+
it: Option<Shared<Node<T>>>,
1042+
pred: F,
1043+
idx: usize,
1044+
old_len: usize,
1045+
}
1046+
1047+
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
1048+
impl<'a, T, F> Iterator for DrainFilter<'a, T, F>
1049+
where F: FnMut(&mut T) -> bool,
1050+
{
1051+
type Item = T;
1052+
1053+
fn next(&mut self) -> Option<T> {
1054+
while let Some(mut node) = self.it {
1055+
unsafe {
1056+
self.it = node.as_ref().next;
1057+
self.idx += 1;
1058+
1059+
if (self.pred)(&mut node.as_mut().element) {
1060+
self.list.unlink_node(node);
1061+
return Some(Box::from_raw(node.as_ptr()).element);
1062+
}
1063+
}
1064+
}
1065+
1066+
None
1067+
}
1068+
1069+
fn size_hint(&self) -> (usize, Option<usize>) {
1070+
(0, Some(self.old_len - self.idx))
1071+
}
1072+
}
1073+
1074+
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
1075+
impl<'a, T: 'a + fmt::Debug, F> fmt::Debug for DrainFilter<'a, T, F>
1076+
where F: FnMut(&mut T) -> bool
1077+
{
1078+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1079+
f.debug_tuple("DrainFilter")
1080+
.field(&self.list)
1081+
.finish()
1082+
}
1083+
}
1084+
9701085
#[stable(feature = "rust1", since = "1.0.0")]
9711086
impl<T> Iterator for IntoIter<T> {
9721087
type Item = T;
@@ -1509,4 +1624,28 @@ mod tests {
15091624
}
15101625
assert_eq!(i, v.len());
15111626
}
1627+
1628+
#[test]
1629+
fn drain_filter_test() {
1630+
let mut m: LinkedList<u32> = LinkedList::new();
1631+
m.extend(&[1, 2, 3, 4, 5, 6]);
1632+
let deleted = m.drain_filter(|v| *v < 4).collect::<Vec<_>>();
1633+
1634+
check_links(&m);
1635+
1636+
assert_eq!(deleted, &[1, 2, 3]);
1637+
assert_eq!(m.into_iter().collect::<Vec<_>>(), &[4, 5, 6]);
1638+
}
1639+
1640+
#[test]
1641+
fn drain_to_empty_test() {
1642+
let mut m: LinkedList<u32> = LinkedList::new();
1643+
m.extend(&[1, 2, 3, 4, 5, 6]);
1644+
let deleted = m.drain_filter(|_| true).collect::<Vec<_>>();
1645+
1646+
check_links(&m);
1647+
1648+
assert_eq!(deleted, &[1, 2, 3, 4, 5, 6]);
1649+
assert_eq!(m.into_iter().collect::<Vec<_>>(), &[]);
1650+
}
15121651
}

src/liballoc/tests/linked_list.rs

+188
Original file line numberDiff line numberDiff line change
@@ -366,3 +366,191 @@ fn test_contains() {
366366

367367
assert!(!l.contains(&3));
368368
}
369+
370+
#[test]
371+
fn drain_filter_empty() {
372+
let mut list: LinkedList<i32> = LinkedList::new();
373+
374+
{
375+
let mut iter = list.drain_filter(|_| true);
376+
assert_eq!(iter.size_hint(), (0, Some(0)));
377+
assert_eq!(iter.next(), None);
378+
assert_eq!(iter.size_hint(), (0, Some(0)));
379+
assert_eq!(iter.next(), None);
380+
assert_eq!(iter.size_hint(), (0, Some(0)));
381+
}
382+
383+
assert_eq!(list.len(), 0);
384+
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![]);
385+
}
386+
387+
#[test]
388+
fn drain_filter_zst() {
389+
let mut list: LinkedList<_> = vec![(), (), (), (), ()].into_iter().collect();
390+
let initial_len = list.len();
391+
let mut count = 0;
392+
393+
{
394+
let mut iter = list.drain_filter(|_| true);
395+
assert_eq!(iter.size_hint(), (0, Some(initial_len)));
396+
while let Some(_) = iter.next() {
397+
count += 1;
398+
assert_eq!(iter.size_hint(), (0, Some(initial_len - count)));
399+
}
400+
assert_eq!(iter.size_hint(), (0, Some(0)));
401+
assert_eq!(iter.next(), None);
402+
assert_eq!(iter.size_hint(), (0, Some(0)));
403+
}
404+
405+
assert_eq!(count, initial_len);
406+
assert_eq!(list.len(), 0);
407+
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![]);
408+
}
409+
410+
#[test]
411+
fn drain_filter_false() {
412+
let mut list: LinkedList<_> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect();
413+
414+
let initial_len = list.len();
415+
let mut count = 0;
416+
417+
{
418+
let mut iter = list.drain_filter(|_| false);
419+
assert_eq!(iter.size_hint(), (0, Some(initial_len)));
420+
for _ in iter.by_ref() {
421+
count += 1;
422+
}
423+
assert_eq!(iter.size_hint(), (0, Some(0)));
424+
assert_eq!(iter.next(), None);
425+
assert_eq!(iter.size_hint(), (0, Some(0)));
426+
}
427+
428+
assert_eq!(count, 0);
429+
assert_eq!(list.len(), initial_len);
430+
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
431+
}
432+
433+
#[test]
434+
fn drain_filter_true() {
435+
let mut list: LinkedList<_> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect();
436+
437+
let initial_len = list.len();
438+
let mut count = 0;
439+
440+
{
441+
let mut iter = list.drain_filter(|_| true);
442+
assert_eq!(iter.size_hint(), (0, Some(initial_len)));
443+
while let Some(_) = iter.next() {
444+
count += 1;
445+
assert_eq!(iter.size_hint(), (0, Some(initial_len - count)));
446+
}
447+
assert_eq!(iter.size_hint(), (0, Some(0)));
448+
assert_eq!(iter.next(), None);
449+
assert_eq!(iter.size_hint(), (0, Some(0)));
450+
}
451+
452+
assert_eq!(count, initial_len);
453+
assert_eq!(list.len(), 0);
454+
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![]);
455+
}
456+
457+
#[test]
458+
fn drain_filter_complex() {
459+
460+
{ // [+xxx++++++xxxxx++++x+x++]
461+
let mut list = vec![
462+
1,
463+
2, 4, 6,
464+
7, 9, 11, 13, 15, 17,
465+
18, 20, 22, 24, 26,
466+
27, 29, 31, 33,
467+
34,
468+
35,
469+
36,
470+
37, 39
471+
].into_iter().collect::<LinkedList<_>>();
472+
473+
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
474+
assert_eq!(removed.len(), 10);
475+
assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
476+
477+
assert_eq!(list.len(), 14);
478+
assert_eq!(
479+
list.into_iter().collect::<Vec<_>>(),
480+
vec![1, 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]
481+
);
482+
}
483+
484+
{ // [xxx++++++xxxxx++++x+x++]
485+
let mut list = vec![
486+
2, 4, 6,
487+
7, 9, 11, 13, 15, 17,
488+
18, 20, 22, 24, 26,
489+
27, 29, 31, 33,
490+
34,
491+
35,
492+
36,
493+
37, 39
494+
].into_iter().collect::<LinkedList<_>>();
495+
496+
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
497+
assert_eq!(removed.len(), 10);
498+
assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
499+
500+
assert_eq!(list.len(), 13);
501+
assert_eq!(
502+
list.into_iter().collect::<Vec<_>>(),
503+
vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]
504+
);
505+
}
506+
507+
{ // [xxx++++++xxxxx++++x+x]
508+
let mut list = vec![
509+
2, 4, 6,
510+
7, 9, 11, 13, 15, 17,
511+
18, 20, 22, 24, 26,
512+
27, 29, 31, 33,
513+
34,
514+
35,
515+
36
516+
].into_iter().collect::<LinkedList<_>>();
517+
518+
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
519+
assert_eq!(removed.len(), 10);
520+
assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
521+
522+
assert_eq!(list.len(), 11);
523+
assert_eq!(
524+
list.into_iter().collect::<Vec<_>>(),
525+
vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35]
526+
);
527+
}
528+
529+
{ // [xxxxxxxxxx+++++++++++]
530+
let mut list = vec![
531+
2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
532+
1, 3, 5, 7, 9, 11, 13, 15, 17, 19
533+
].into_iter().collect::<LinkedList<_>>();
534+
535+
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
536+
assert_eq!(removed.len(), 10);
537+
assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);
538+
539+
assert_eq!(list.len(), 10);
540+
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
541+
}
542+
543+
{ // [+++++++++++xxxxxxxxxx]
544+
let mut list = vec![
545+
1, 3, 5, 7, 9, 11, 13, 15, 17, 19,
546+
2, 4, 6, 8, 10, 12, 14, 16, 18, 20
547+
].into_iter().collect::<LinkedList<_>>();
548+
549+
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
550+
assert_eq!(removed.len(), 10);
551+
assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);
552+
553+
assert_eq!(list.len(), 10);
554+
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
555+
}
556+
}

0 commit comments

Comments
 (0)