From 84dde3aa3386c2d699ffc7e8f5e05cfbde67918a Mon Sep 17 00:00:00 2001 From: The 8472 Date: Wed, 20 Nov 2024 22:50:58 +0100 Subject: [PATCH 1/5] Add a range argument to vec.extract_if --- library/alloc/src/vec/extract_if.rs | 23 +++++++++++--- library/alloc/src/vec/mod.rs | 43 ++++++++++++++++--------- library/alloc/tests/vec.rs | 49 ++++++++++++++++++++++------- 3 files changed, 83 insertions(+), 32 deletions(-) diff --git a/library/alloc/src/vec/extract_if.rs b/library/alloc/src/vec/extract_if.rs index 72d51e8904488..f722d89d4005a 100644 --- a/library/alloc/src/vec/extract_if.rs +++ b/library/alloc/src/vec/extract_if.rs @@ -1,4 +1,4 @@ -use core::{ptr, slice}; +use core::{ops::{Range, RangeBounds}, ptr, slice}; use super::Vec; use crate::alloc::{Allocator, Global}; @@ -14,7 +14,7 @@ use crate::alloc::{Allocator, Global}; /// #![feature(extract_if)] /// /// let mut v = vec![0, 1, 2]; -/// let iter: std::vec::ExtractIf<'_, _, _> = v.extract_if(|x| *x % 2 == 0); +/// let iter: std::vec::ExtractIf<'_, _, _> = v.extract_if(.., |x| *x % 2 == 0); /// ``` #[unstable(feature = "extract_if", reason = "recently added", issue = "43244")] #[derive(Debug)] @@ -30,6 +30,8 @@ pub struct ExtractIf< pub(super) vec: &'a mut Vec, /// The index of the item that will be inspected by the next call to `next`. pub(super) idx: usize, + /// Elements at and beyond this point will be retained. Must be equal or smaller than `old_len`. + pub(super) end: usize, /// The number of items that have been drained (removed) thus far. pub(super) del: usize, /// The original length of `vec` prior to draining. @@ -38,10 +40,21 @@ pub struct ExtractIf< pub(super) pred: F, } -impl ExtractIf<'_, T, F, A> +impl<'a, T, F, A: Allocator> ExtractIf<'a, T, F, A> where F: FnMut(&mut T) -> bool, { + pub(super) fn new>(vec: &'a mut Vec, pred: F, range: R) -> Self { + let old_len = vec.len(); + let Range { start, end } = slice::range(range, ..old_len); + + // Guard against the vec getting leaked (leak amplification) + unsafe { + vec.set_len(0); + } + ExtractIf { vec, idx: start, del: 0, end, old_len, pred } + } + /// Returns a reference to the underlying allocator. #[unstable(feature = "allocator_api", issue = "32838")] #[inline] @@ -59,7 +72,7 @@ where fn next(&mut self) -> Option { unsafe { - while self.idx < self.old_len { + while self.idx < self.end { let i = self.idx; let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len); let drained = (self.pred)(&mut v[i]); @@ -82,7 +95,7 @@ where } fn size_hint(&self) -> (usize, Option) { - (0, Some(self.old_len - self.idx)) + (0, Some(self.end - self.idx)) } } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 07a1bd4932138..ae9d4e8c3acde 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -3610,12 +3610,15 @@ impl Vec { Splice { drain: self.drain(range), replace_with: replace_with.into_iter() } } - /// Creates an iterator which uses a closure to determine if an element should be removed. + /// Creates an iterator which uses a closure to determine if element in the range should be removed. /// /// If the closure returns true, then the element is removed and yielded. /// If the closure returns false, the element will remain in the vector and will not be yielded /// by the iterator. /// + /// Only elements that fall in the provided range are considered for extraction, but any elements + /// after the range will still have to be moved if any element has been extracted. + /// /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating /// or the iteration short-circuits, then the remaining elements will be retained. /// Use [`retain`] with a negated predicate if you do not need the returned iterator. @@ -3625,10 +3628,12 @@ impl Vec { /// Using this method is equivalent to the following code: /// /// ``` + /// # use std::cmp::min; /// # let some_predicate = |x: &mut i32| { *x == 2 || *x == 3 || *x == 6 }; /// # let mut vec = vec![1, 2, 3, 4, 5, 6]; - /// let mut i = 0; - /// while i < vec.len() { + /// # let range = 1..4; + /// let mut i = range.start; + /// while i < min(vec.len(), range.end) { /// if some_predicate(&mut vec[i]) { /// let val = vec.remove(i); /// // your code here @@ -3643,8 +3648,12 @@ impl Vec { /// But `extract_if` is easier to use. `extract_if` is also more efficient, /// because it can backshift the elements of the array in bulk. /// - /// Note that `extract_if` also lets you mutate every element in the filter closure, - /// regardless of whether you choose to keep or remove it. + /// Note that `extract_if` also lets you mutate the elements passed to the filter closure, + /// regardless of whether you choose to keep or remove them. + /// + /// # Panics + /// + /// If `range` is out of bounds. /// /// # Examples /// @@ -3654,25 +3663,29 @@ impl Vec { /// #![feature(extract_if)] /// let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]; /// - /// let evens = numbers.extract_if(|x| *x % 2 == 0).collect::>(); + /// let evens = numbers.extract_if(.., |x| *x % 2 == 0).collect::>(); /// let odds = numbers; /// /// assert_eq!(evens, vec![2, 4, 6, 8, 14]); /// assert_eq!(odds, vec![1, 3, 5, 9, 11, 13, 15]); /// ``` + /// + /// Using the range argument to only process a part of the vector: + /// + /// ``` + /// #![feature(extract_if)] + /// let mut items = vec![0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 2, 1, 2]; + /// let ones = items.extract_if(7.., |x| *x == 1).collect::>(); + /// assert_eq!(items, vec![0, 0, 0, 0, 0, 0, 0, 2, 2, 2]); + /// assert_eq!(ones.len(), 3); + /// ``` #[unstable(feature = "extract_if", reason = "recently added", issue = "43244")] - pub fn extract_if(&mut self, filter: F) -> ExtractIf<'_, T, F, A> + pub fn extract_if(&mut self, range: R, filter: F) -> ExtractIf<'_, T, F, A> where F: FnMut(&mut T) -> bool, + R: RangeBounds, { - let old_len = self.len(); - - // Guard against us getting leaked (leak amplification) - unsafe { - self.set_len(0); - } - - ExtractIf { vec: self, idx: 0, del: 0, old_len, pred: filter } + ExtractIf::new(self, filter, range) } } diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 0f27fdff3e182..75d36194c534a 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1414,7 +1414,7 @@ fn extract_if_empty() { let mut vec: Vec = vec![]; { - let mut iter = vec.extract_if(|_| true); + let mut iter = vec.extract_if(.., |_| true); assert_eq!(iter.size_hint(), (0, Some(0))); assert_eq!(iter.next(), None); assert_eq!(iter.size_hint(), (0, Some(0))); @@ -1431,7 +1431,7 @@ fn extract_if_zst() { let initial_len = vec.len(); let mut count = 0; { - let mut iter = vec.extract_if(|_| true); + let mut iter = vec.extract_if(.., |_| true); assert_eq!(iter.size_hint(), (0, Some(initial_len))); while let Some(_) = iter.next() { count += 1; @@ -1454,7 +1454,7 @@ fn extract_if_false() { let initial_len = vec.len(); let mut count = 0; { - let mut iter = vec.extract_if(|_| false); + let mut iter = vec.extract_if(.., |_| false); assert_eq!(iter.size_hint(), (0, Some(initial_len))); for _ in iter.by_ref() { count += 1; @@ -1476,7 +1476,7 @@ fn extract_if_true() { let initial_len = vec.len(); let mut count = 0; { - let mut iter = vec.extract_if(|_| true); + let mut iter = vec.extract_if(.., |_| true); assert_eq!(iter.size_hint(), (0, Some(initial_len))); while let Some(_) = iter.next() { count += 1; @@ -1492,6 +1492,31 @@ fn extract_if_true() { assert_eq!(vec, vec![]); } +#[test] +fn extract_if_ranges() { + let mut vec = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + let mut count = 0; + let it = vec.extract_if(1..=3, |_| { + count += 1; + true + }); + assert_eq!(it.collect::>(), vec![1, 2, 3]); + assert_eq!(vec, vec![0, 4, 5, 6, 7, 8, 9, 10]); + assert_eq!(count, 3); + + let it = vec.extract_if(1..=3, |_| false); + assert_eq!(it.collect::>(), vec![]); + assert_eq!(vec, vec![0, 4, 5, 6, 7, 8, 9, 10]); +} + +#[test] +#[should_panic] +fn extraxt_if_out_of_bounds() { + let mut vec = vec![0, 1]; + let _ = vec.extract_if(5.., |_| true).for_each(drop); +} + #[test] fn extract_if_complex() { { @@ -1501,7 +1526,7 @@ fn extract_if_complex() { 39, ]; - let removed = vec.extract_if(|x| *x % 2 == 0).collect::>(); + let removed = vec.extract_if(.., |x| *x % 2 == 0).collect::>(); assert_eq!(removed.len(), 10); assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); @@ -1515,7 +1540,7 @@ fn extract_if_complex() { 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, 39, ]; - let removed = vec.extract_if(|x| *x % 2 == 0).collect::>(); + let removed = vec.extract_if(.., |x| *x % 2 == 0).collect::>(); assert_eq!(removed.len(), 10); assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); @@ -1528,7 +1553,7 @@ fn extract_if_complex() { let mut vec = vec![2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36]; - let removed = vec.extract_if(|x| *x % 2 == 0).collect::>(); + let removed = vec.extract_if(.., |x| *x % 2 == 0).collect::>(); assert_eq!(removed.len(), 10); assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); @@ -1540,7 +1565,7 @@ fn extract_if_complex() { // [xxxxxxxxxx+++++++++++] let mut vec = vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19]; - let removed = vec.extract_if(|x| *x % 2 == 0).collect::>(); + let removed = vec.extract_if(.., |x| *x % 2 == 0).collect::>(); assert_eq!(removed.len(), 10); assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); @@ -1552,7 +1577,7 @@ fn extract_if_complex() { // [+++++++++++xxxxxxxxxx] let mut vec = vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]; - let removed = vec.extract_if(|x| *x % 2 == 0).collect::>(); + let removed = vec.extract_if(.., |x| *x % 2 == 0).collect::>(); assert_eq!(removed.len(), 10); assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); @@ -1600,7 +1625,7 @@ fn extract_if_consumed_panic() { } c.index < 6 }; - let drain = data.extract_if(filter); + let drain = data.extract_if(.., filter); // NOTE: The ExtractIf is explicitly consumed drain.for_each(drop); @@ -1653,7 +1678,7 @@ fn extract_if_unconsumed_panic() { } c.index < 6 }; - let _drain = data.extract_if(filter); + let _drain = data.extract_if(.., filter); // NOTE: The ExtractIf is dropped without being consumed }); @@ -1669,7 +1694,7 @@ fn extract_if_unconsumed_panic() { #[test] fn extract_if_unconsumed() { let mut vec = vec![1, 2, 3, 4]; - let drain = vec.extract_if(|&mut x| x % 2 != 0); + let drain = vec.extract_if(.., |&mut x| x % 2 != 0); drop(drain); assert_eq!(vec, [1, 2, 3, 4]); } From 94cb28c754048785c1a775080f5b454b494aa5ab Mon Sep 17 00:00:00 2001 From: The 8472 Date: Wed, 20 Nov 2024 23:13:45 +0100 Subject: [PATCH 2/5] remove bounds from vec and linkedlist ExtractIf since drain-on-drop behavior was removed those bounds no longer serve a purpose --- library/alloc/src/collections/linked_list.rs | 9 ++------- library/alloc/src/vec/extract_if.rs | 17 +++++------------ 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index ca0ea1ec8b2ba..13168b7a39fe4 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -1939,9 +1939,7 @@ pub struct ExtractIf< T: 'a, F: 'a, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, -> where - F: FnMut(&mut T) -> bool, -{ +> { list: &'a mut LinkedList, it: Option>>, pred: F, @@ -1979,10 +1977,7 @@ where } #[unstable(feature = "extract_if", reason = "recently added", issue = "43244")] -impl fmt::Debug for ExtractIf<'_, T, F> -where - F: FnMut(&mut T) -> bool, -{ +impl fmt::Debug for ExtractIf<'_, T, F> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("ExtractIf").field(&self.list).finish() } diff --git a/library/alloc/src/vec/extract_if.rs b/library/alloc/src/vec/extract_if.rs index f722d89d4005a..1ea7cbdc7e8a4 100644 --- a/library/alloc/src/vec/extract_if.rs +++ b/library/alloc/src/vec/extract_if.rs @@ -1,4 +1,5 @@ -use core::{ops::{Range, RangeBounds}, ptr, slice}; +use core::ops::{Range, RangeBounds}; +use core::{ptr, slice}; use super::Vec; use crate::alloc::{Allocator, Global}; @@ -24,9 +25,7 @@ pub struct ExtractIf< T, F, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, -> where - F: FnMut(&mut T) -> bool, -{ +> { pub(super) vec: &'a mut Vec, /// The index of the item that will be inspected by the next call to `next`. pub(super) idx: usize, @@ -40,10 +39,7 @@ pub struct ExtractIf< pub(super) pred: F, } -impl<'a, T, F, A: Allocator> ExtractIf<'a, T, F, A> -where - F: FnMut(&mut T) -> bool, -{ +impl<'a, T, F, A: Allocator> ExtractIf<'a, T, F, A> { pub(super) fn new>(vec: &'a mut Vec, pred: F, range: R) -> Self { let old_len = vec.len(); let Range { start, end } = slice::range(range, ..old_len); @@ -100,10 +96,7 @@ where } #[unstable(feature = "extract_if", reason = "recently added", issue = "43244")] -impl Drop for ExtractIf<'_, T, F, A> -where - F: FnMut(&mut T) -> bool, -{ +impl Drop for ExtractIf<'_, T, F, A> { fn drop(&mut self) { unsafe { if self.idx < self.old_len && self.del > 0 { From d4560bacee7bd51f6a8e2cbdea64af8363858d34 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Wed, 20 Nov 2024 23:45:53 +0100 Subject: [PATCH 3/5] update uses of extract_if in the compiler --- compiler/rustc_errors/src/lib.rs | 8 ++++---- compiler/rustc_lint/src/non_ascii_idents.rs | 4 ++-- compiler/rustc_metadata/src/native_libs.rs | 2 +- compiler/rustc_middle/src/ty/diagnostics.rs | 2 +- compiler/rustc_resolve/src/diagnostics.rs | 6 +++--- compiler/rustc_resolve/src/late/diagnostics.rs | 2 +- compiler/rustc_trait_selection/src/traits/mod.rs | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 98200c367f988..ccd6b1449adce 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1558,18 +1558,18 @@ impl DiagCtxtInner { debug!(?diagnostic); debug!(?self.emitted_diagnostics); - let already_emitted_sub = |sub: &mut Subdiag| { + let not_yet_emitted = |sub: &mut Subdiag| { debug!(?sub); if sub.level != OnceNote && sub.level != OnceHelp { - return false; + return true; } let mut hasher = StableHasher::new(); sub.hash(&mut hasher); let diagnostic_hash = hasher.finish(); debug!(?diagnostic_hash); - !self.emitted_diagnostics.insert(diagnostic_hash) + self.emitted_diagnostics.insert(diagnostic_hash) }; - diagnostic.children.extract_if(already_emitted_sub).for_each(|_| {}); + diagnostic.children.retain_mut(not_yet_emitted); if already_emitted { let msg = "duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`"; diagnostic.sub(Note, msg, MultiSpan::new()); diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs index 9b495c19990c1..50c64a9c94757 100644 --- a/compiler/rustc_lint/src/non_ascii_idents.rs +++ b/compiler/rustc_lint/src/non_ascii_idents.rs @@ -205,7 +205,7 @@ impl EarlyLintPass for NonAsciiIdents { (IdentifierType::Not_NFKC, "Not_NFKC"), ] { let codepoints: Vec<_> = - chars.extract_if(|(_, ty)| *ty == Some(id_ty)).collect(); + chars.extract_if(.., |(_, ty)| *ty == Some(id_ty)).collect(); if codepoints.is_empty() { continue; } @@ -217,7 +217,7 @@ impl EarlyLintPass for NonAsciiIdents { } let remaining = chars - .extract_if(|(c, _)| !GeneralSecurityProfile::identifier_allowed(*c)) + .extract_if(.., |(c, _)| !GeneralSecurityProfile::identifier_allowed(*c)) .collect::>(); if !remaining.is_empty() { cx.emit_span_lint(UNCOMMON_CODEPOINTS, sp, IdentifierUncommonCodepoints { diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index ace46891f83da..0dcaefe53bfeb 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -540,7 +540,7 @@ impl<'tcx> Collector<'tcx> { // can move them to the end of the list below. let mut existing = self .libs - .extract_if(|lib| { + .extract_if(.., |lib| { if lib.name.as_str() == passed_lib.name { // FIXME: This whole logic is questionable, whether modifiers are // involved or not, library reordering and kind overriding without diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 84f52bfe48f23..1c54a905dcd4f 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -290,7 +290,7 @@ pub fn suggest_constraining_type_params<'a>( let Some(param) = param else { return false }; { - let mut sized_constraints = constraints.extract_if(|(_, def_id)| { + let mut sized_constraints = constraints.extract_if(.., |(_, def_id)| { def_id.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Sized)) }); if let Some((_, def_id)) = sized_constraints.next() { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 5b78acd904a75..d890eae80274c 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -2805,11 +2805,11 @@ fn show_candidates( path_strings.sort_by(|a, b| a.0.cmp(&b.0)); path_strings.dedup_by(|a, b| a.0 == b.0); let core_path_strings = - path_strings.extract_if(|p| p.0.starts_with("core::")).collect::>(); + path_strings.extract_if(.., |p| p.0.starts_with("core::")).collect::>(); let std_path_strings = - path_strings.extract_if(|p| p.0.starts_with("std::")).collect::>(); + path_strings.extract_if(.., |p| p.0.starts_with("std::")).collect::>(); let foreign_crate_path_strings = - path_strings.extract_if(|p| !p.0.starts_with("crate::")).collect::>(); + path_strings.extract_if(.., |p| !p.0.starts_with("crate::")).collect::>(); // We list the `crate` local paths first. // Then we list the `std`/`core` paths. diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 09f5a8e96d3de..f2f6399a18ada 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -628,7 +628,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // Try to filter out intrinsics candidates, as long as we have // some other candidates to suggest. let intrinsic_candidates: Vec<_> = candidates - .extract_if(|sugg| { + .extract_if(.., |sugg| { let path = path_names_to_string(&sugg.path); path.starts_with("core::intrinsics::") || path.starts_with("std::intrinsics::") }) diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index c0603c06d4225..b4ad806512b3e 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -447,7 +447,7 @@ pub fn normalize_param_env_or_error<'tcx>( // This works fairly well because trait matching does not actually care about param-env // TypeOutlives predicates - these are normally used by regionck. let outlives_predicates: Vec<_> = predicates - .extract_if(|predicate| { + .extract_if(.., |predicate| { matches!(predicate.kind().skip_binder(), ty::ClauseKind::TypeOutlives(..)) }) .collect(); From aabed334c5cb884f8c016a1e18a4ad8b2b7976d5 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Wed, 20 Nov 2024 23:53:35 +0100 Subject: [PATCH 4/5] remove obsolete comment and pub(super) visibility --- library/alloc/src/vec/extract_if.rs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/library/alloc/src/vec/extract_if.rs b/library/alloc/src/vec/extract_if.rs index 1ea7cbdc7e8a4..4db13981596bc 100644 --- a/library/alloc/src/vec/extract_if.rs +++ b/library/alloc/src/vec/extract_if.rs @@ -26,17 +26,17 @@ pub struct ExtractIf< F, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, > { - pub(super) vec: &'a mut Vec, + vec: &'a mut Vec, /// The index of the item that will be inspected by the next call to `next`. - pub(super) idx: usize, + idx: usize, /// Elements at and beyond this point will be retained. Must be equal or smaller than `old_len`. - pub(super) end: usize, + end: usize, /// The number of items that have been drained (removed) thus far. - pub(super) del: usize, + del: usize, /// The original length of `vec` prior to draining. - pub(super) old_len: usize, + old_len: usize, /// The filter test predicate. - pub(super) pred: F, + pred: F, } impl<'a, T, F, A: Allocator> ExtractIf<'a, T, F, A> { @@ -100,12 +100,6 @@ impl Drop for ExtractIf<'_, T, F, A> { fn drop(&mut self) { unsafe { if self.idx < self.old_len && self.del > 0 { - // This is a pretty messed up state, and there isn't really an - // obviously right thing to do. We don't want to keep trying - // to execute `pred`, so we just backshift all the unprocessed - // elements and tell the vec that they still exist. The backshift - // is required to prevent a double-drop of the last successfully - // drained item prior to a panic in the predicate. let ptr = self.vec.as_mut_ptr(); let src = ptr.add(self.idx); let dst = src.sub(self.del); From 414acdad1cc996fe90c4e866f20df4d6022fe399 Mon Sep 17 00:00:00 2001 From: the8472 Date: Fri, 6 Dec 2024 21:33:15 +0100 Subject: [PATCH 5/5] fix spelling in library/alloc/tests/vec.rs Co-authored-by: Josh Stone --- library/alloc/tests/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 75d36194c534a..84679827ba1c0 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1512,7 +1512,7 @@ fn extract_if_ranges() { #[test] #[should_panic] -fn extraxt_if_out_of_bounds() { +fn extract_if_out_of_bounds() { let mut vec = vec![0, 1]; let _ = vec.extract_if(5.., |_| true).for_each(drop); }