Skip to content

Commit f8df2e1

Browse files
committed
Generalize Box::clone
1 parent 76cba19 commit f8df2e1

File tree

5 files changed

+14
-80
lines changed

5 files changed

+14
-80
lines changed

library/alloc/src/boxed.rs

Lines changed: 14 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,6 @@ use core::task::{Context, Poll};
205205
use crate::alloc::handle_alloc_error;
206206
use crate::alloc::{AllocError, Allocator, Global, Layout};
207207
use crate::raw_vec::RawVec;
208-
#[cfg(not(no_global_oom_handling))]
209-
use crate::str::from_boxed_utf8_unchecked;
210208

211209
/// Conversion related impls for `Box<_>` (`From`, `downcast`, etc)
212210
mod convert;
@@ -1733,7 +1731,7 @@ where
17331731

17341732
#[cfg(not(no_global_oom_handling))]
17351733
#[stable(feature = "rust1", since = "1.0.0")]
1736-
impl<T: Clone, A: Allocator + Clone> Clone for Box<T, A> {
1734+
impl<T: CloneToUninit + ?Sized, A: Allocator + Clone> Clone for Box<T, A> {
17371735
/// Returns a new box with a `clone()` of this box's contents.
17381736
///
17391737
/// # Examples
@@ -1751,14 +1749,21 @@ impl<T: Clone, A: Allocator + Clone> Clone for Box<T, A> {
17511749
#[inline]
17521750
fn clone(&self) -> Self {
17531751
// Pre-allocate memory to allow writing the cloned value directly.
1754-
let mut boxed = Self::new_uninit_in(self.1.clone());
1752+
let mut boxed = unsafe {
1753+
uninit::UninitBox::<T, A>::new_for_metadata_in(
1754+
ptr::metadata(Self::as_ptr(self)),
1755+
self.1.clone(),
1756+
)
1757+
};
1758+
17551759
unsafe {
17561760
(**self).clone_to_uninit(boxed.as_mut_ptr().cast());
17571761
boxed.assume_init()
17581762
}
17591763
}
17601764

1761-
/// Copies `source`'s contents into `self` without creating a new allocation.
1765+
/// Copies `source`'s contents into `self` without creating a new allocation,
1766+
/// so long as the two have the same metadata.
17621767
///
17631768
/// # Examples
17641769
///
@@ -1777,55 +1782,16 @@ impl<T: Clone, A: Allocator + Clone> Clone for Box<T, A> {
17771782
/// ```
17781783
#[inline]
17791784
fn clone_from(&mut self, source: &Self) {
1780-
(**self).clone_from(&(**source));
1781-
}
1782-
}
1783-
1784-
#[cfg(not(no_global_oom_handling))]
1785-
#[stable(feature = "box_slice_clone", since = "1.3.0")]
1786-
impl<T: Clone, A: Allocator + Clone> Clone for Box<[T], A> {
1787-
fn clone(&self) -> Self {
1788-
let alloc = Box::allocator(self).clone();
1789-
self.to_vec_in(alloc).into_boxed_slice()
1790-
}
1791-
1792-
/// Copies `source`'s contents into `self` without creating a new allocation,
1793-
/// so long as the two are of the same length.
1794-
///
1795-
/// # Examples
1796-
///
1797-
/// ```
1798-
/// let x = Box::new([5, 6, 7]);
1799-
/// let mut y = Box::new([8, 9, 10]);
1800-
/// let yp: *const [i32] = &*y;
1801-
///
1802-
/// y.clone_from(&x);
1803-
///
1804-
/// // The value is the same
1805-
/// assert_eq!(x, y);
1806-
///
1807-
/// // And no allocation occurred
1808-
/// assert_eq!(yp, &*y);
1809-
/// ```
1810-
fn clone_from(&mut self, source: &Self) {
1811-
if self.len() == source.len() {
1812-
self.clone_from_slice(&source);
1785+
// The following comparison may fail for vtable pointers even if both
1786+
// types are the same, in which case we take the slow path.
1787+
if ptr::metadata(self) == ptr::metadata(source) {
1788+
unsafe { (**source).clone_to_init(Box::as_mut_ptr(self).cast()) };
18131789
} else {
18141790
*self = source.clone();
18151791
}
18161792
}
18171793
}
18181794

1819-
#[cfg(not(no_global_oom_handling))]
1820-
#[stable(feature = "box_slice_clone", since = "1.3.0")]
1821-
impl Clone for Box<str> {
1822-
fn clone(&self) -> Self {
1823-
// this makes a copy of the data
1824-
let buf: Box<[u8]> = self.as_bytes().into();
1825-
unsafe { from_boxed_utf8_unchecked(buf) }
1826-
}
1827-
}
1828-
18291795
#[stable(feature = "rust1", since = "1.0.0")]
18301796
impl<T: ?Sized + PartialEq, A: Allocator> PartialEq for Box<T, A> {
18311797
#[inline]

library/alloc/src/bstr.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -589,14 +589,6 @@ impl<'a> TryFrom<&'a ByteString> for &'a str {
589589

590590
// Additional impls for `ByteStr` that require types from `alloc`:
591591

592-
#[unstable(feature = "bstr", issue = "134915")]
593-
impl Clone for Box<ByteStr> {
594-
#[inline]
595-
fn clone(&self) -> Self {
596-
Self::from(Box::<[u8]>::from(&self.0))
597-
}
598-
}
599-
600592
#[unstable(feature = "bstr", issue = "134915")]
601593
impl<'a> From<&'a ByteStr> for Cow<'a, ByteStr> {
602594
#[inline]

library/alloc/src/ffi/c_str.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -851,14 +851,6 @@ impl TryFrom<CString> for String {
851851
}
852852
}
853853

854-
#[stable(feature = "more_box_slice_clone", since = "1.29.0")]
855-
impl Clone for Box<CStr> {
856-
#[inline]
857-
fn clone(&self) -> Self {
858-
(**self).into()
859-
}
860-
}
861-
862854
#[stable(feature = "box_from_c_string", since = "1.20.0")]
863855
impl From<CString> for Box<CStr> {
864856
/// Converts a [`CString`] into a <code>[Box]<[CStr]></code> without copying or allocating.

library/std/src/ffi/os_str.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,14 +1329,6 @@ impl From<OsString> for Box<OsStr> {
13291329
}
13301330
}
13311331

1332-
#[stable(feature = "more_box_slice_clone", since = "1.29.0")]
1333-
impl Clone for Box<OsStr> {
1334-
#[inline]
1335-
fn clone(&self) -> Self {
1336-
self.to_os_string().into_boxed_os_str()
1337-
}
1338-
}
1339-
13401332
#[unstable(feature = "clone_to_uninit", issue = "126799")]
13411333
unsafe impl CloneToUninit for OsStr {
13421334
#[inline]

library/std/src/path.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1825,14 +1825,6 @@ impl From<PathBuf> for Box<Path> {
18251825
}
18261826
}
18271827

1828-
#[stable(feature = "more_box_slice_clone", since = "1.29.0")]
1829-
impl Clone for Box<Path> {
1830-
#[inline]
1831-
fn clone(&self) -> Self {
1832-
self.to_path_buf().into_boxed_path()
1833-
}
1834-
}
1835-
18361828
#[stable(feature = "rust1", since = "1.0.0")]
18371829
impl<T: ?Sized + AsRef<OsStr>> From<&T> for PathBuf {
18381830
/// Converts a borrowed [`OsStr`] to a [`PathBuf`].

0 commit comments

Comments
 (0)