Rollup merge of #122201 - coolreader18:doc-clone_from, r=dtolnay

Document overrides of `clone_from()` in core/std

As mentioned in https://github.com/rust-lang/rust/pull/96979#discussion_r1379502413

Specifically, when an override doesn't just forward to an inner type, document the behavior and that it's preferred over simply assigning a clone of source. Also, change instances where the second parameter is "other" to "source".

I reused some of the wording over and over for similar impls, but I'm not sure that the wording is actually *good*. Would appreciate feedback about that.

Also, now some of these seem to provide pretty specific guarantees about behavior (e.g. will reuse the exact same allocation iff the len is the same), but I was basing it off of the docs for [`Box::clone_from`](https://doc.rust-lang.org/1.75.0/std/boxed/struct.Box.html#method.clone_from-1) - I'm not sure if providing those strong guarantees is actually good or not.
This commit is contained in:
Matthias Krüger 2024-04-17 18:01:37 +02:00 committed by GitHub
commit 21deaed4a1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 133 additions and 25 deletions

View File

@ -2088,11 +2088,29 @@ impl<T: Clone, A: Allocator + Clone> Clone for Box<[T], A> {
self.to_vec_in(alloc).into_boxed_slice()
}
fn clone_from(&mut self, other: &Self) {
if self.len() == other.len() {
self.clone_from_slice(&other);
/// Copies `source`'s contents into `self` without creating a new allocation,
/// so long as the two are of the same length.
///
/// # Examples
///
/// ```
/// let x = Box::new([5, 6, 7]);
/// let mut y = Box::new([8, 9, 10]);
/// let yp: *const [i32] = &*y;
///
/// y.clone_from(&x);
///
/// // The value is the same
/// assert_eq!(x, y);
///
/// // And no allocation occurred
/// assert_eq!(yp, &*y);
/// ```
fn clone_from(&mut self, source: &Self) {
if self.len() == source.len() {
self.clone_from_slice(&source);
} else {
*self = other.clone();
*self = source.clone();
}
}
}

View File

@ -385,6 +385,12 @@ impl<T: Clone, A: Allocator + Clone> Clone for BinaryHeap<T, A> {
BinaryHeap { data: self.data.clone() }
}
/// Overwrites the contents of `self` with a clone of the contents of `source`.
///
/// This method is preferred over simply assigning `source.clone()` to `self`,
/// as it avoids reallocation if possible.
///
/// See [`Vec::clone_from()`] for more details.
fn clone_from(&mut self, source: &Self) {
self.data.clone_from(&source.data);
}

View File

@ -116,8 +116,8 @@ impl<T: Clone, A: Allocator + Clone> Clone for BTreeSet<T, A> {
BTreeSet { map: self.map.clone() }
}
fn clone_from(&mut self, other: &Self) {
self.map.clone_from(&other.map);
fn clone_from(&mut self, source: &Self) {
self.map.clone_from(&source.map);
}
}

View File

@ -2126,16 +2126,22 @@ impl<T: Clone, A: Allocator + Clone> Clone for LinkedList<T, A> {
list
}
fn clone_from(&mut self, other: &Self) {
let mut iter_other = other.iter();
if self.len() > other.len() {
self.split_off(other.len());
/// Overwrites the contents of `self` with a clone of the contents of `source`.
///
/// This method is preferred over simply assigning `source.clone()` to `self`,
/// as it avoids reallocation of the nodes of the linked list. Additionally,
/// if the element type `T` overrides `clone_from()`, this will reuse the
/// resources of `self`'s elements as well.
fn clone_from(&mut self, source: &Self) {
let mut source_iter = source.iter();
if self.len() > source.len() {
self.split_off(source.len());
}
for (elem, elem_other) in self.iter_mut().zip(&mut iter_other) {
elem.clone_from(elem_other);
for (elem, source_elem) in self.iter_mut().zip(&mut source_iter) {
elem.clone_from(source_elem);
}
if !iter_other.is_empty() {
self.extend(iter_other.cloned());
if !source_iter.is_empty() {
self.extend(source_iter.cloned());
}
}
}

View File

@ -113,9 +113,13 @@ impl<T: Clone, A: Allocator + Clone> Clone for VecDeque<T, A> {
deq
}
fn clone_from(&mut self, other: &Self) {
/// Overwrites the contents of `self` with a clone of the contents of `source`.
///
/// This method is preferred over simply assigning `source.clone()` to `self`,
/// as it avoids reallocation if possible.
fn clone_from(&mut self, source: &Self) {
self.clear();
self.extend(other.iter().cloned());
self.extend(source.iter().cloned());
}
}

View File

@ -2097,6 +2097,10 @@ impl Clone for String {
String { vec: self.vec.clone() }
}
/// Clones the contents of `source` into `self`.
///
/// This method is preferred over simply assigning `source.clone()` to `self`,
/// as it avoids reallocation if possible.
fn clone_from(&mut self, source: &Self) {
self.vec.clone_from(&source.vec);
}

View File

@ -2846,8 +2846,30 @@ impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> {
crate::slice::to_vec(&**self, alloc)
}
fn clone_from(&mut self, other: &Self) {
crate::slice::SpecCloneIntoVec::clone_into(other.as_slice(), self);
/// Overwrites the contents of `self` with a clone of the contents of `source`.
///
/// This method is preferred over simply assigning `source.clone()` to `self`,
/// as it avoids reallocation if possible. Additionally, if the element type
/// `T` overrides `clone_from()`, this will reuse the resources of `self`'s
/// elements as well.
///
/// # Examples
///
/// ```
/// let x = vec![5, 6, 7];
/// let mut y = vec![8, 9, 10];
/// let yp: *const i32 = y.as_ptr();
///
/// y.clone_from(&x);
///
/// // The value is the same
/// assert_eq!(x, y);
///
/// // And no reallocation occurred
/// assert_eq!(yp, y.as_ptr());
/// ```
fn clone_from(&mut self, source: &Self) {
crate::slice::SpecCloneIntoVec::clone_into(source.as_slice(), self);
}
}

View File

@ -1277,11 +1277,11 @@ impl<T: Clone> Clone for RefCell<T> {
/// # Panics
///
/// Panics if `other` is currently mutably borrowed.
/// Panics if `source` is currently mutably borrowed.
#[inline]
#[track_caller]
fn clone_from(&mut self, other: &Self) {
self.get_mut().clone_from(&other.borrow())
fn clone_from(&mut self, source: &Self) {
self.get_mut().clone_from(&source.borrow())
}
}

View File

@ -688,8 +688,8 @@ impl<T: Clone> Clone for Reverse<T> {
}
#[inline]
fn clone_from(&mut self, other: &Self) {
self.0.clone_from(&other.0)
fn clone_from(&mut self, source: &Self) {
self.0.clone_from(&source.0)
}
}

View File

@ -576,6 +576,42 @@ impl Clone for Waker {
}
}
/// Assigns a clone of `source` to `self`, unless [`self.will_wake(source)`][Waker::will_wake] anyway.
///
/// This method is preferred over simply assigning `source.clone()` to `self`,
/// as it avoids cloning the waker if `self` is already the same waker.
///
/// # Examples
///
/// ```
/// use std::future::Future;
/// use std::pin::Pin;
/// use std::sync::{Arc, Mutex};
/// use std::task::{Context, Poll, Waker};
///
/// struct Waiter {
/// shared: Arc<Mutex<Shared>>,
/// }
///
/// struct Shared {
/// waker: Waker,
/// // ...
/// }
///
/// impl Future for Waiter {
/// type Output = ();
/// fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
/// let mut shared = self.shared.lock().unwrap();
///
/// // update the waker
/// shared.waker.clone_from(cx.waker());
///
/// // readiness logic ...
/// # Poll::Ready(())
/// }
/// }
///
/// ```
#[inline]
fn clone_from(&mut self, source: &Self) {
if !self.will_wake(source) {

View File

@ -1271,8 +1271,8 @@ where
}
#[inline]
fn clone_from(&mut self, other: &Self) {
self.base.clone_from(&other.base);
fn clone_from(&mut self, source: &Self) {
self.base.clone_from(&source.base);
}
}

View File

@ -978,6 +978,10 @@ where
Self { base: self.base.clone() }
}
/// Overwrites the contents of `self` with a clone of the contents of `source`.
///
/// This method is preferred over simply assigning `source.clone()` to `self`,
/// as it avoids reallocation if possible.
#[inline]
fn clone_from(&mut self, other: &Self) {
self.base.clone_from(&other.base);

View File

@ -606,6 +606,10 @@ impl Clone for OsString {
OsString { inner: self.inner.clone() }
}
/// Clones the contents of `source` into `self`.
///
/// This method is preferred over simply assigning `source.clone()` to `self`,
/// as it avoids reallocation if possible.
#[inline]
fn clone_from(&mut self, source: &Self) {
self.inner.clone_from(&source.inner)

View File

@ -1628,6 +1628,10 @@ impl Clone for PathBuf {
PathBuf { inner: self.inner.clone() }
}
/// Clones the contents of `source` into `self`.
///
/// This method is preferred over simply assigning `source.clone()` to `self`,
/// as it avoids reallocation if possible.
#[inline]
fn clone_from(&mut self, source: &Self) {
self.inner.clone_from(&source.inner)