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 😄
This commit is contained in:
commit
8d64fd80ad
|
@ -1109,6 +1109,14 @@ impl<T: Clone> Clone for Box<[T]> {
|
|||
fn clone(&self) -> Self {
|
||||
self.to_vec().into_boxed_slice()
|
||||
}
|
||||
|
||||
fn clone_from(&mut self, other: &Self) {
|
||||
if self.len() == other.len() {
|
||||
self.clone_from_slice(&other);
|
||||
} else {
|
||||
*self = other.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "box_borrow", since = "1.1.0")]
|
||||
|
|
|
@ -16,3 +16,36 @@ fn unitialized_zero_size_box() {
|
|||
NonNull::<MaybeUninit<String>>::dangling().as_ptr(),
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
struct Dummy {
|
||||
_data: u8,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn box_clone_and_clone_from_equivalence() {
|
||||
for size in (0..8).map(|i| 2usize.pow(i)) {
|
||||
let control = vec![Dummy { _data: 42 }; size].into_boxed_slice();
|
||||
let clone = control.clone();
|
||||
let mut copy = vec![Dummy { _data: 84 }; size].into_boxed_slice();
|
||||
copy.clone_from(&control);
|
||||
assert_eq!(control, clone);
|
||||
assert_eq!(control, copy);
|
||||
}
|
||||
}
|
||||
|
||||
/// This test might give a false positive in case the box realocates, but the alocator keeps the
|
||||
/// original pointer.
|
||||
///
|
||||
/// On the other hand it won't give a false negative, if it fails than the memory was definitly not
|
||||
/// reused
|
||||
#[test]
|
||||
fn box_clone_from_ptr_stability() {
|
||||
for size in (0..8).map(|i| 2usize.pow(i)) {
|
||||
let control = vec![Dummy { _data: 42 }; size].into_boxed_slice();
|
||||
let mut copy = vec![Dummy { _data: 84 }; size].into_boxed_slice();
|
||||
let copy_raw = copy.as_ptr() as usize;
|
||||
copy.clone_from(&control);
|
||||
assert_eq!(copy.as_ptr() as usize, copy_raw);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue