From 69031cf2926b0dbbc9e905a784c72596e3541945 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Tue, 24 Mar 2026 10:48:56 -0400 Subject: [PATCH 1/4] Implement extract_if for BinaryHeap - Implement using the sort and rebuild on drop method as maintaining the heap invariant during each extraction would cost more on average --- .../src/collections/binary_heap/extract_if.rs | 124 ++++++++++++++++++ .../alloc/src/collections/binary_heap/mod.rs | 25 +++- .../tests/collections/binary_heap.rs | 62 +++++++++ library/alloctests/tests/lib.rs | 1 + 4 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 library/alloc/src/collections/binary_heap/extract_if.rs diff --git a/library/alloc/src/collections/binary_heap/extract_if.rs b/library/alloc/src/collections/binary_heap/extract_if.rs new file mode 100644 index 0000000000000..f05a251b8b21b --- /dev/null +++ b/library/alloc/src/collections/binary_heap/extract_if.rs @@ -0,0 +1,124 @@ +use core::iter::FusedIterator; +use core::{fmt, ptr}; + +use super::BinaryHeap; +use crate::alloc::{Allocator, Global}; + +/// An iterator which uses a closure to determine if an element should be removed. +/// +/// This struct is created by [`BinaryHeap::extract_if`]. +/// See its documentation for more. +/// +/// # Example +/// +/// ``` +/// #![feature(binary_heap_extract_if)] +/// use crate::alloc::collections::BinaryHeap; +/// +/// let mut heap: BinaryHeap = (0..128).collect(); +/// let iter: Vec = heap.extract_if(|x| *x % 2 == 0).collect(); +#[unstable(feature = "binary_heap_extract_if", issue = "42849")] +#[must_use = "iterators are lazy and do nothing unless consumed; \ + use `retain_mut` or `extract_if().for_each(drop)` to remove and discard elements"] +pub struct ExtractIf< + 'a, + T: Ord, + F, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + heap: &'a mut BinaryHeap, + old_len: usize, + del: usize, + index: usize, + predicate: F, +} + +impl ExtractIf<'_, T, F, A> { + pub(super) fn new<'a>(heap: &'a mut BinaryHeap, predicate: F) -> ExtractIf<'a, T, F, A> { + // This breaks the heap invariant but we artificially change the length to 0 below and don't change it back until we have fixed this invariant + heap.sort_inner_vec(); + + let old_len = heap.len(); + // SAFETY: leak enlargement + unsafe { heap.data.set_len(0) }; + + ExtractIf { heap, predicate, index: 0, old_len, del: 0 } + } +} + +#[unstable(feature = "binary_heap_extract_if", issue = "42849")] +impl Iterator for ExtractIf<'_, T, F, A> +where + F: FnMut(&T) -> bool, +{ + type Item = T; + + fn next(&mut self) -> Option { + while self.index < self.old_len { + let i = self.index; + // SAFETY: + // We know that `i < self.end` from the if guard and that `self.end <= self.old_len` from + // the validity of `Self`. Therefore `i` points to an element within `vec`. + // + // Additionally, the i-th element is valid because each element is visited at most once + // and it is the first time we access vec[i]. + // + // Note: we can't use `vec.get_unchecked_mut(i)` here since the precondition for that + // function is that i < vec.len(), but we've set vec's length to zero. + let cur = unsafe { &mut *self.heap.data.as_mut_ptr().add(i) }; + let extract = (self.predicate)(cur); + // Update the index *after* the predicate is called. If the index + // is updated prior and the predicate panics, the element at this + // index would be leaked. + self.index += 1; + if extract { + self.del += 1; + // SAFETY: We never touch this element again after returning it. + return Some(unsafe { ptr::read(cur) }); + } else if self.del > 0 { + // SAFETY: `self.del` > 0, so the hole slot must not overlap with current element. + // We use copy for move, and never touch this element again. + unsafe { + let hole_slot = self.heap.data.as_mut_ptr().add(i - self.del); + ptr::copy_nonoverlapping(cur, hole_slot, 1); + } + } + } + None + } +} + +#[unstable(feature = "binary_heap_extract_if", issue = "42849")] +impl Drop for ExtractIf<'_, T, F, A> { + fn drop(&mut self) { + if self.del > 0 { + // SAFETY: Trailing unchecked items must be valid since we never touch them. + unsafe { + ptr::copy( + self.heap.data.as_ptr().add(self.index), + self.heap.data.as_mut_ptr().add(self.index - self.del), + self.old_len - self.index, + ); + } + } + // SAFETY: After filling holes, all items are in contiguous memory. + unsafe { + self.heap.data.set_len(self.old_len - self.del); + } + self.heap.rebuild(); + } +} + +#[unstable(feature = "binary_heap_extract_if", issue = "42849")] +impl FusedIterator for ExtractIf<'_, T, F, A> where F: FnMut(&T) -> bool {} + +#[unstable(feature = "binary_heap_extract_if", issue = "42849")] +impl fmt::Debug for ExtractIf<'_, T, F, A> +where + T: fmt::Debug, + A: Allocator, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ExtractIf").finish_non_exhaustive() + } +} diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 4ddfcde57280e..b93ac84004a12 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -150,6 +150,11 @@ use core::num::NonZero; use core::ops::{Deref, DerefMut}; use core::{fmt, ptr}; +#[unstable(feature = "binary_heap_extract_if", issue = "42849")] +pub use self::extract_if::ExtractIf; + +mod extract_if; + use crate::alloc::Global; use crate::collections::TryReserveError; use crate::slice; @@ -772,6 +777,12 @@ impl BinaryHeap { #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "binary_heap_extras_15", since = "1.5.0")] pub fn into_sorted_vec(mut self) -> Vec { + self.sort_inner_vec(); + self.into_vec() + } + + /// Sorts the inner data inplace -> producing an invalid heap. Used for implementing ExtractIf + fn sort_inner_vec(&mut self) { let mut end = self.len(); while end > 1 { end -= 1; @@ -788,7 +799,6 @@ impl BinaryHeap { // Which means 0 < end and end < self.len(). unsafe { self.sift_down_range(0, end) }; } - self.into_vec() } // The implementations of sift_up and sift_down use unsafe blocks in @@ -1039,6 +1049,19 @@ impl BinaryHeap { DrainSorted { inner: self } } + /// Creates an iterator which uses a closure to determine if an element should be removed. + /// The items are checked in sorted order + /// + /// If the closure returns `true`, the element is marked to be removed and yielded + #[unstable(feature = "binary_heap_extract_if", issue = "42849")] + #[must_use] + pub fn extract_if(&mut self, predicate: F) -> ExtractIf<'_, T, F, A> + where + F: FnMut(&T) -> bool, + { + ExtractIf::new(self, predicate) + } + /// Retains only the elements specified by the predicate. /// /// In other words, remove all elements `e` for which `f(&e)` returns diff --git a/library/alloctests/tests/collections/binary_heap.rs b/library/alloctests/tests/collections/binary_heap.rs index e1484c32a4f8a..fb86f1195a2f7 100644 --- a/library/alloctests/tests/collections/binary_heap.rs +++ b/library/alloctests/tests/collections/binary_heap.rs @@ -590,3 +590,65 @@ fn panic_safe() { } } } + +#[test] +fn given_a_binary_heap_can_create_an_extract_if_iterator() { + let mut heap = BinaryHeap::new(); + let iter = heap.extract_if(|_: &usize| unreachable!("there's nothing to decide on")); + + iter.for_each(drop); + assert!(heap.is_empty()) +} + +#[test] +fn given_some_binary_heap_with_one_item_when_extracting_if_true_extracts_all_items() { + let mut heap = BinaryHeap::new(); + heap.push(10); + let v: Vec = heap.extract_if(|_: &usize| true).collect(); + + assert!(heap.is_empty()); + assert_eq!(v, vec![10]); +} + +#[test] +fn given_some_binary_heap_with_three_items_when_extracting_if_true_extracts_all_items_in_sorted_order() + { + let mut heap = BinaryHeap::new(); + heap.push(10); + heap.push(15); + heap.push(11); + let v: Vec<_> = heap.extract_if(|_| true).collect(); + + assert!(heap.is_empty()); + assert_eq!(v, vec![10, 11, 15]); +} + +#[test] +fn given_some_binary_heap_with_some_items_when_extracting_if_even_extracts_just_even_items() { + let mut heap = BinaryHeap::new(); + heap.push(10); + heap.push(15); + heap.push(11); + let v: Vec<_> = heap.extract_if(|&x| x % 2 == 0).collect(); + + assert_eq!(v, vec![10]); + assert_eq!(heap.pop(), Some(15)); + assert_eq!(heap.pop(), Some(11)); + assert_eq!(heap.pop(), None); +} + +#[test] +fn given_some_binary_heap_with_some_items_when_extracting_if_when_dropping_without_iterating_leaves_heap_in_valid_state() + { + let mut heap = BinaryHeap::new(); + heap.push(10); + heap.push(15); + heap.push(11); + + drop(heap.extract_if(|&x| x % 2 == 0)); + + assert_eq!(heap.pop(), Some(15)); + assert_eq!(heap.pop(), Some(11)); + assert_eq!(heap.pop(), Some(10)); + assert_eq!(heap.pop(), None); +} diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index 699a5010282b0..61d696b33020a 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -1,4 +1,5 @@ #![feature(allocator_api)] +#![feature(binary_heap_extract_if)] #![feature(binary_heap_pop_if)] #![feature(const_heap)] #![feature(deque_extend_front)] From ce86444bc58e1370f5d5acbc11c2e9d53cc1e5f0 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 2 Apr 2026 12:49:35 -0400 Subject: [PATCH 2/4] Update BinaryHeap::extract_if to reuse Vec::extract_if --- .../src/collections/binary_heap/extract_if.rs | 87 ++++++------------- .../alloc/src/collections/binary_heap/mod.rs | 9 +- .../tests/collections/binary_heap.rs | 16 ++-- 3 files changed, 36 insertions(+), 76 deletions(-) diff --git a/library/alloc/src/collections/binary_heap/extract_if.rs b/library/alloc/src/collections/binary_heap/extract_if.rs index f05a251b8b21b..6d630647c2576 100644 --- a/library/alloc/src/collections/binary_heap/extract_if.rs +++ b/library/alloc/src/collections/binary_heap/extract_if.rs @@ -1,5 +1,6 @@ +use core::fmt; use core::iter::FusedIterator; -use core::{fmt, ptr}; +use core::mem::ManuallyDrop; use super::BinaryHeap; use crate::alloc::{Allocator, Global}; @@ -26,91 +27,55 @@ pub struct ExtractIf< F, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, > { - heap: &'a mut BinaryHeap, - old_len: usize, - del: usize, - index: usize, - predicate: F, + heap_ptr: *mut BinaryHeap, + extract_if: ManuallyDrop>, } -impl ExtractIf<'_, T, F, A> { +impl ExtractIf<'_, T, F, A> +where + F: FnMut(&mut T) -> bool, +{ pub(super) fn new<'a>(heap: &'a mut BinaryHeap, predicate: F) -> ExtractIf<'a, T, F, A> { - // This breaks the heap invariant but we artificially change the length to 0 below and don't change it back until we have fixed this invariant - heap.sort_inner_vec(); + // We need to keep a reference around to the heap so that we can + let heap_ptr: *mut BinaryHeap = heap; + let extract_if = ManuallyDrop::new(heap.data.extract_if(.., predicate)); - let old_len = heap.len(); - // SAFETY: leak enlargement - unsafe { heap.data.set_len(0) }; - - ExtractIf { heap, predicate, index: 0, old_len, del: 0 } + ExtractIf { heap_ptr, extract_if } } } #[unstable(feature = "binary_heap_extract_if", issue = "42849")] impl Iterator for ExtractIf<'_, T, F, A> where - F: FnMut(&T) -> bool, + F: FnMut(&mut T) -> bool, { type Item = T; fn next(&mut self) -> Option { - while self.index < self.old_len { - let i = self.index; - // SAFETY: - // We know that `i < self.end` from the if guard and that `self.end <= self.old_len` from - // the validity of `Self`. Therefore `i` points to an element within `vec`. - // - // Additionally, the i-th element is valid because each element is visited at most once - // and it is the first time we access vec[i]. - // - // Note: we can't use `vec.get_unchecked_mut(i)` here since the precondition for that - // function is that i < vec.len(), but we've set vec's length to zero. - let cur = unsafe { &mut *self.heap.data.as_mut_ptr().add(i) }; - let extract = (self.predicate)(cur); - // Update the index *after* the predicate is called. If the index - // is updated prior and the predicate panics, the element at this - // index would be leaked. - self.index += 1; - if extract { - self.del += 1; - // SAFETY: We never touch this element again after returning it. - return Some(unsafe { ptr::read(cur) }); - } else if self.del > 0 { - // SAFETY: `self.del` > 0, so the hole slot must not overlap with current element. - // We use copy for move, and never touch this element again. - unsafe { - let hole_slot = self.heap.data.as_mut_ptr().add(i - self.del); - ptr::copy_nonoverlapping(cur, hole_slot, 1); - } - } - } - None + self.extract_if.next() } } #[unstable(feature = "binary_heap_extract_if", issue = "42849")] -impl Drop for ExtractIf<'_, T, F, A> { +impl<'a, T: Ord, F, A: Allocator> Drop for ExtractIf<'a, T, F, A> { fn drop(&mut self) { - if self.del > 0 { - // SAFETY: Trailing unchecked items must be valid since we never touch them. - unsafe { - ptr::copy( - self.heap.data.as_ptr().add(self.index), - self.heap.data.as_mut_ptr().add(self.index - self.del), - self.old_len - self.index, - ); - } - } - // SAFETY: After filling holes, all items are in contiguous memory. + // SAFETY: We need to drop this before we rebuild the heap so that its descructor resets the vec info + // We also are only calling this hear during the drop of ExtractIf and then never using it again unsafe { - self.heap.data.set_len(self.old_len - self.del); + ManuallyDrop::drop(&mut self.extract_if); } - self.heap.rebuild(); + + // SAFETY: We only generate this ptr from a reference so we know that it is never null + let heap = unsafe { self.heap_ptr.as_mut_unchecked() }; + + // Removing some items from the heap almost certainly has invalidated its invarients, we need to fix this up here + heap.rebuild(); } } #[unstable(feature = "binary_heap_extract_if", issue = "42849")] -impl FusedIterator for ExtractIf<'_, T, F, A> where F: FnMut(&T) -> bool {} +impl FusedIterator for ExtractIf<'_, T, F, A> where F: FnMut(&mut T) -> bool +{} #[unstable(feature = "binary_heap_extract_if", issue = "42849")] impl fmt::Debug for ExtractIf<'_, T, F, A> diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index b93ac84004a12..b67f708c6aa4f 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -777,12 +777,6 @@ impl BinaryHeap { #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "binary_heap_extras_15", since = "1.5.0")] pub fn into_sorted_vec(mut self) -> Vec { - self.sort_inner_vec(); - self.into_vec() - } - - /// Sorts the inner data inplace -> producing an invalid heap. Used for implementing ExtractIf - fn sort_inner_vec(&mut self) { let mut end = self.len(); while end > 1 { end -= 1; @@ -799,6 +793,7 @@ impl BinaryHeap { // Which means 0 < end and end < self.len(). unsafe { self.sift_down_range(0, end) }; } + self.into_vec() } // The implementations of sift_up and sift_down use unsafe blocks in @@ -1057,7 +1052,7 @@ impl BinaryHeap { #[must_use] pub fn extract_if(&mut self, predicate: F) -> ExtractIf<'_, T, F, A> where - F: FnMut(&T) -> bool, + F: FnMut(&mut T) -> bool, { ExtractIf::new(self, predicate) } diff --git a/library/alloctests/tests/collections/binary_heap.rs b/library/alloctests/tests/collections/binary_heap.rs index fb86f1195a2f7..138d3737e47a4 100644 --- a/library/alloctests/tests/collections/binary_heap.rs +++ b/library/alloctests/tests/collections/binary_heap.rs @@ -593,8 +593,8 @@ fn panic_safe() { #[test] fn given_a_binary_heap_can_create_an_extract_if_iterator() { - let mut heap = BinaryHeap::new(); - let iter = heap.extract_if(|_: &usize| unreachable!("there's nothing to decide on")); + let mut heap: BinaryHeap = BinaryHeap::new(); + let iter = heap.extract_if(|_| unreachable!("there's nothing to decide on")); iter.for_each(drop); assert!(heap.is_empty()) @@ -602,16 +602,16 @@ fn given_a_binary_heap_can_create_an_extract_if_iterator() { #[test] fn given_some_binary_heap_with_one_item_when_extracting_if_true_extracts_all_items() { - let mut heap = BinaryHeap::new(); + let mut heap: BinaryHeap = BinaryHeap::new(); heap.push(10); - let v: Vec = heap.extract_if(|_: &usize| true).collect(); + let v: Vec = heap.extract_if(|_| true).collect(); assert!(heap.is_empty()); assert_eq!(v, vec![10]); } #[test] -fn given_some_binary_heap_with_three_items_when_extracting_if_true_extracts_all_items_in_sorted_order() +fn given_some_binary_heap_with_three_items_when_extracting_if_true_extracts_all_items_in_arbitray_order() { let mut heap = BinaryHeap::new(); heap.push(10); @@ -620,7 +620,7 @@ fn given_some_binary_heap_with_three_items_when_extracting_if_true_extracts_all_ let v: Vec<_> = heap.extract_if(|_| true).collect(); assert!(heap.is_empty()); - assert_eq!(v, vec![10, 11, 15]); + assert_eq!(v, vec![15, 10, 11]); } #[test] @@ -629,7 +629,7 @@ fn given_some_binary_heap_with_some_items_when_extracting_if_even_extracts_just_ heap.push(10); heap.push(15); heap.push(11); - let v: Vec<_> = heap.extract_if(|&x| x % 2 == 0).collect(); + let v: Vec<_> = heap.extract_if(|&mut x| x % 2 == 0).collect(); assert_eq!(v, vec![10]); assert_eq!(heap.pop(), Some(15)); @@ -645,7 +645,7 @@ fn given_some_binary_heap_with_some_items_when_extracting_if_when_dropping_witho heap.push(15); heap.push(11); - drop(heap.extract_if(|&x| x % 2 == 0)); + drop(heap.extract_if(|&mut x| x % 2 == 0)); assert_eq!(heap.pop(), Some(15)); assert_eq!(heap.pop(), Some(11)); From 6d7cb3dd00358ab62f0888a82a0327515b043205 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 2 Apr 2026 13:01:30 -0400 Subject: [PATCH 3/4] Update tracking issue number --- .../alloc/src/collections/binary_heap/extract_if.rs | 10 +++++----- library/alloc/src/collections/binary_heap/mod.rs | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/library/alloc/src/collections/binary_heap/extract_if.rs b/library/alloc/src/collections/binary_heap/extract_if.rs index 6d630647c2576..83f6f0d3ed00d 100644 --- a/library/alloc/src/collections/binary_heap/extract_if.rs +++ b/library/alloc/src/collections/binary_heap/extract_if.rs @@ -18,7 +18,7 @@ use crate::alloc::{Allocator, Global}; /// /// let mut heap: BinaryHeap = (0..128).collect(); /// let iter: Vec = heap.extract_if(|x| *x % 2 == 0).collect(); -#[unstable(feature = "binary_heap_extract_if", issue = "42849")] +#[unstable(feature = "binary_heap_extract_if", issue = "154721")] #[must_use = "iterators are lazy and do nothing unless consumed; \ use `retain_mut` or `extract_if().for_each(drop)` to remove and discard elements"] pub struct ExtractIf< @@ -44,7 +44,7 @@ where } } -#[unstable(feature = "binary_heap_extract_if", issue = "42849")] +#[unstable(feature = "binary_heap_extract_if", issue = "154721")] impl Iterator for ExtractIf<'_, T, F, A> where F: FnMut(&mut T) -> bool, @@ -56,7 +56,7 @@ where } } -#[unstable(feature = "binary_heap_extract_if", issue = "42849")] +#[unstable(feature = "binary_heap_extract_if", issue = "154721")] impl<'a, T: Ord, F, A: Allocator> Drop for ExtractIf<'a, T, F, A> { fn drop(&mut self) { // SAFETY: We need to drop this before we rebuild the heap so that its descructor resets the vec info @@ -73,11 +73,11 @@ impl<'a, T: Ord, F, A: Allocator> Drop for ExtractIf<'a, T, F, A> { } } -#[unstable(feature = "binary_heap_extract_if", issue = "42849")] +#[unstable(feature = "binary_heap_extract_if", issue = "154721")] impl FusedIterator for ExtractIf<'_, T, F, A> where F: FnMut(&mut T) -> bool {} -#[unstable(feature = "binary_heap_extract_if", issue = "42849")] +#[unstable(feature = "binary_heap_extract_if", issue = "154721")] impl fmt::Debug for ExtractIf<'_, T, F, A> where T: fmt::Debug, diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index b67f708c6aa4f..c7ad4430d71c3 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -150,7 +150,7 @@ use core::num::NonZero; use core::ops::{Deref, DerefMut}; use core::{fmt, ptr}; -#[unstable(feature = "binary_heap_extract_if", issue = "42849")] +#[unstable(feature = "binary_heap_extract_if", issue = "154721")] pub use self::extract_if::ExtractIf; mod extract_if; @@ -1048,7 +1048,7 @@ impl BinaryHeap { /// The items are checked in sorted order /// /// If the closure returns `true`, the element is marked to be removed and yielded - #[unstable(feature = "binary_heap_extract_if", issue = "42849")] + #[unstable(feature = "binary_heap_extract_if", issue = "154721")] #[must_use] pub fn extract_if(&mut self, predicate: F) -> ExtractIf<'_, T, F, A> where From fcff0df474281f7035e1301ab0a199c1abacd9ec Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 2 Apr 2026 17:56:31 -0400 Subject: [PATCH 4/4] Fix typos --- library/alloc/src/collections/binary_heap/extract_if.rs | 2 +- library/alloctests/tests/collections/binary_heap.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/collections/binary_heap/extract_if.rs b/library/alloc/src/collections/binary_heap/extract_if.rs index 83f6f0d3ed00d..3aa50fc67e097 100644 --- a/library/alloc/src/collections/binary_heap/extract_if.rs +++ b/library/alloc/src/collections/binary_heap/extract_if.rs @@ -68,7 +68,7 @@ impl<'a, T: Ord, F, A: Allocator> Drop for ExtractIf<'a, T, F, A> { // SAFETY: We only generate this ptr from a reference so we know that it is never null let heap = unsafe { self.heap_ptr.as_mut_unchecked() }; - // Removing some items from the heap almost certainly has invalidated its invarients, we need to fix this up here + // Removing some items from the heap almost certainly has invalidated its invariants, we need to fix this up here heap.rebuild(); } } diff --git a/library/alloctests/tests/collections/binary_heap.rs b/library/alloctests/tests/collections/binary_heap.rs index 138d3737e47a4..c712918a98b35 100644 --- a/library/alloctests/tests/collections/binary_heap.rs +++ b/library/alloctests/tests/collections/binary_heap.rs @@ -611,7 +611,7 @@ fn given_some_binary_heap_with_one_item_when_extracting_if_true_extracts_all_ite } #[test] -fn given_some_binary_heap_with_three_items_when_extracting_if_true_extracts_all_items_in_arbitray_order() +fn given_some_binary_heap_with_three_items_when_extracting_if_true_extracts_all_items_in_arbitrary_order() { let mut heap = BinaryHeap::new(); heap.push(10);