Skip to content

Commit 8d64fd8

Browse files
authored
Rollup merge of #72499 - mendess:master, r=dtolnay
Override Box::<[T]>::clone_from Avoid dropping and reallocating when cloning to an existing box if the lengths are the same. It would be nice if this could also be specialized for `Copy` but I don't know how that works since it's not on stable. Will gladly look into it if it's deemed as a good idea. This is my first PR with code, hope I did everything right 😄
2 parents 49ca99d + dbf32e2 commit 8d64fd8

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

src/liballoc/boxed.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1109,6 +1109,14 @@ impl<T: Clone> Clone for Box<[T]> {
11091109
fn clone(&self) -> Self {
11101110
self.to_vec().into_boxed_slice()
11111111
}
1112+
1113+
fn clone_from(&mut self, other: &Self) {
1114+
if self.len() == other.len() {
1115+
self.clone_from_slice(&other);
1116+
} else {
1117+
*self = other.clone();
1118+
}
1119+
}
11121120
}
11131121

11141122
#[stable(feature = "box_borrow", since = "1.1.0")]

src/liballoc/tests/boxed.rs

+33
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,36 @@ fn unitialized_zero_size_box() {
1616
NonNull::<MaybeUninit<String>>::dangling().as_ptr(),
1717
);
1818
}
19+
20+
#[derive(Clone, PartialEq, Eq, Debug)]
21+
struct Dummy {
22+
_data: u8,
23+
}
24+
25+
#[test]
26+
fn box_clone_and_clone_from_equivalence() {
27+
for size in (0..8).map(|i| 2usize.pow(i)) {
28+
let control = vec![Dummy { _data: 42 }; size].into_boxed_slice();
29+
let clone = control.clone();
30+
let mut copy = vec![Dummy { _data: 84 }; size].into_boxed_slice();
31+
copy.clone_from(&control);
32+
assert_eq!(control, clone);
33+
assert_eq!(control, copy);
34+
}
35+
}
36+
37+
/// This test might give a false positive in case the box realocates, but the alocator keeps the
38+
/// original pointer.
39+
///
40+
/// On the other hand it won't give a false negative, if it fails than the memory was definitly not
41+
/// reused
42+
#[test]
43+
fn box_clone_from_ptr_stability() {
44+
for size in (0..8).map(|i| 2usize.pow(i)) {
45+
let control = vec![Dummy { _data: 42 }; size].into_boxed_slice();
46+
let mut copy = vec![Dummy { _data: 84 }; size].into_boxed_slice();
47+
let copy_raw = copy.as_ptr() as usize;
48+
copy.clone_from(&control);
49+
assert_eq!(copy.as_ptr() as usize, copy_raw);
50+
}
51+
}

0 commit comments

Comments
 (0)