diff options
| author | bors <bors@rust-lang.org> | 2025-09-25 20:35:49 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2025-09-25 20:35:49 +0000 |
| commit | 7ac0330c6d684d86d6f86fabe601a3defdc3b234 (patch) | |
| tree | 5c1a901b7316ab94dc6ad125c5524a23f86bd101 /library/alloc/src | |
| parent | eabf390b4ceeb34db9f37e97f435134abbcdea92 (diff) | |
| parent | c6d0059fb887c172a9325adae78548c975653572 (diff) | |
| download | rust-7ac0330c6d684d86d6f86fabe601a3defdc3b234.tar.gz rust-7ac0330c6d684d86d6f86fabe601a3defdc3b234.zip | |
Auto merge of #147037 - matthiaskrgr:rollup-xtgqzuu, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - rust-lang/rust#116882 (rustdoc: hide `#[repr]` if it isn't part of the public ABI) - rust-lang/rust#135771 ([rustdoc] Add support for associated items in "jump to def" feature) - rust-lang/rust#141032 (avoid violating `slice::from_raw_parts` safety contract in `Vec::extract_if`) - rust-lang/rust#142401 (Add proper name mangling for pattern types) - rust-lang/rust#146293 (feat: non-panicking `Vec::try_remove`) - rust-lang/rust#146859 (BTreeMap: Don't leak allocators when initializing nodes) - rust-lang/rust#146924 (Add doc for `NonZero*` const creation) - rust-lang/rust#146933 (Make `render_example_with_highlighting` return an `impl fmt::Display`) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'library/alloc/src')
| -rw-r--r-- | library/alloc/src/collections/btree/map.rs | 3 | ||||
| -rw-r--r-- | library/alloc/src/collections/btree/node.rs | 12 | ||||
| -rw-r--r-- | library/alloc/src/vec/extract_if.rs | 64 | ||||
| -rw-r--r-- | library/alloc/src/vec/mod.rs | 32 |
4 files changed, 82 insertions, 29 deletions
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index cebd25c6039..e3b53b2fe29 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -194,6 +194,9 @@ pub struct BTreeMap< root: Option<Root<K, V>>, length: usize, /// `ManuallyDrop` to control drop order (needs to be dropped after all the nodes). + // Although some of the accessory types store a copy of the allocator, the nodes do not. + // Because allocations will remain live as long as any copy (like this one) of the allocator + // is live, it's unnecessary to store the allocator in each node. pub(super) alloc: ManuallyDrop<A>, // For dropck; the `Box` avoids making the `Unpin` impl more strict than before _marker: PhantomData<crate::boxed::Box<(K, V), A>>, diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 2b8103c8b77..a87259e7c58 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -225,7 +225,11 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::Leaf> { } fn from_new_leaf<A: Allocator + Clone>(leaf: Box<LeafNode<K, V>, A>) -> Self { - NodeRef { height: 0, node: NonNull::from(Box::leak(leaf)), _marker: PhantomData } + // The allocator must be dropped, not leaked. See also `BTreeMap::alloc`. + let (leaf, _alloc) = Box::into_raw_with_allocator(leaf); + // SAFETY: the node was just allocated. + let node = unsafe { NonNull::new_unchecked(leaf) }; + NodeRef { height: 0, node, _marker: PhantomData } } } @@ -243,7 +247,11 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::Internal> { height: usize, ) -> Self { debug_assert!(height > 0); - let node = NonNull::from(Box::leak(internal)).cast(); + // The allocator must be dropped, not leaked. See also `BTreeMap::alloc`. + let (internal, _alloc) = Box::into_raw_with_allocator(internal); + // SAFETY: the node was just allocated. + let internal = unsafe { NonNull::new_unchecked(internal) }; + let node = internal.cast(); let mut this = NodeRef { height, node, _marker: PhantomData }; this.borrow_mut().correct_all_childrens_parent_links(); this diff --git a/library/alloc/src/vec/extract_if.rs b/library/alloc/src/vec/extract_if.rs index a456d3d9e60..cb9e14f554d 100644 --- a/library/alloc/src/vec/extract_if.rs +++ b/library/alloc/src/vec/extract_if.rs @@ -64,27 +64,37 @@ where type Item = T; fn next(&mut self) -> Option<T> { - unsafe { - 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]); - // 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.idx += 1; - if drained { - self.del += 1; - return Some(ptr::read(&v[i])); - } else if self.del > 0 { - let del = self.del; - let src: *const T = &v[i]; - let dst: *mut T = &mut v[i - del]; - ptr::copy_nonoverlapping(src, dst, 1); + while self.idx < self.end { + let i = self.idx; + // 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.vec.as_mut_ptr().add(i) }; + let drained = (self.pred)(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.idx += 1; + if drained { + 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.vec.as_mut_ptr().add(i - self.del); + ptr::copy_nonoverlapping(cur, hole_slot, 1); } } - None } + None } fn size_hint(&self) -> (usize, Option<usize>) { @@ -95,14 +105,18 @@ where #[stable(feature = "extract_if", since = "1.87.0")] impl<T, F, A: Allocator> Drop for ExtractIf<'_, T, F, A> { fn drop(&mut self) { - unsafe { - if self.idx < self.old_len && self.del > 0 { - let ptr = self.vec.as_mut_ptr(); - let src = ptr.add(self.idx); - let dst = src.sub(self.del); - let tail_len = self.old_len - self.idx; - src.copy_to(dst, tail_len); + if self.del > 0 { + // SAFETY: Trailing unchecked items must be valid since we never touch them. + unsafe { + ptr::copy( + self.vec.as_ptr().add(self.idx), + self.vec.as_mut_ptr().add(self.idx - self.del), + self.old_len - self.idx, + ); } + } + // SAFETY: After filling holes, all items are in contiguous memory. + unsafe { self.vec.set_len(self.old_len - self.del); } } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index ebdb86f98a8..694b7b2df08 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2173,9 +2173,37 @@ impl<T, A: Allocator> Vec<T, A> { panic!("removal index (is {index}) should be < len (is {len})"); } + match self.try_remove(index) { + Some(elem) => elem, + None => assert_failed(index, self.len()), + } + } + + /// Remove and return the element at position `index` within the vector, + /// shifting all elements after it to the left, or [`None`] if it does not + /// exist. + /// + /// Note: Because this shifts over the remaining elements, it has a + /// worst-case performance of *O*(*n*). If you'd like to remove + /// elements from the beginning of the `Vec`, consider using + /// [`VecDeque::pop_front`] instead. + /// + /// [`VecDeque::pop_front`]: crate::collections::VecDeque::pop_front + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_try_remove)] + /// let mut v = vec![1, 2, 3]; + /// assert_eq!(v.try_remove(0), Some(1)); + /// assert_eq!(v.try_remove(2), None); + /// ``` + #[unstable(feature = "vec_try_remove", issue = "146954")] + #[rustc_confusables("delete", "take", "remove")] + pub fn try_remove(&mut self, index: usize) -> Option<T> { let len = self.len(); if index >= len { - assert_failed(index, len); + return None; } unsafe { // infallible @@ -2191,7 +2219,7 @@ impl<T, A: Allocator> Vec<T, A> { ptr::copy(ptr.add(1), ptr, len - index - 1); } self.set_len(len - 1); - ret + Some(ret) } } |
