提交 fd34606d 编写于 作者: B bors

Auto merge of #80391 - ssomers:btree_cleanup_slices_3, r=Mark-Simulacrum

BTreeMap: tougher checking on most uses of copy_nonoverlapping

Miri checks pointer provenance and destination, but we can check it in debug builds already.
Also, we can let Miri confirm we don't mistake imprints of moved keys and values as genuine.
r? `@Mark-Simulacrum`
......@@ -1124,21 +1124,20 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>
/// by taking care of leaf data.
fn split_leaf_data(&mut self, new_node: &mut LeafNode<K, V>) -> (K, V) {
debug_assert!(self.idx < self.node.len());
let new_len = self.node.len() - self.idx - 1;
let old_len = self.node.len();
let new_len = old_len - self.idx - 1;
new_node.len = new_len as u16;
unsafe {
let k = self.node.key_area_mut(self.idx).assume_init_read();
let v = self.node.val_area_mut(self.idx).assume_init_read();
ptr::copy_nonoverlapping(
self.node.key_area_mut(self.idx + 1..).as_ptr(),
new_node.keys.as_mut_ptr(),
new_len,
move_to_slice(
self.node.key_area_mut(self.idx + 1..old_len),
&mut new_node.keys[..new_len],
);
ptr::copy_nonoverlapping(
self.node.val_area_mut(self.idx + 1..).as_ptr(),
new_node.vals.as_mut_ptr(),
new_len,
move_to_slice(
self.node.val_area_mut(self.idx + 1..old_len),
&mut new_node.vals[..new_len],
);
*self.node.len_mut() = self.idx as u16;
......@@ -1190,20 +1189,20 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>,
/// - All the edges and key-value pairs to the right of this handle are put into
/// a newly allocated node.
pub fn split(mut self) -> SplitResult<'a, K, V, marker::Internal> {
let old_len = self.node.len();
unsafe {
let mut new_node = Box::new(InternalNode::new());
let kv = self.split_leaf_data(&mut new_node.data);
let new_len = usize::from(new_node.data.len);
ptr::copy_nonoverlapping(
self.node.edge_area_mut(self.idx + 1..).as_ptr(),
new_node.edges.as_mut_ptr(),
new_len + 1,
move_to_slice(
self.node.edge_area_mut(self.idx + 1..old_len + 1),
&mut new_node.edges[..new_len + 1],
);
let height = self.node.height;
let mut right = NodeRef::from_new_internal(new_node, height);
right.borrow_mut().correct_childrens_parent_links(0..=new_len);
right.borrow_mut().correct_childrens_parent_links(0..new_len + 1);
SplitResult { left: self.node, kv, right }
}
......@@ -1323,18 +1322,16 @@ pub fn merge(
let parent_key = slice_remove(parent_node.key_area_mut(..old_parent_len), parent_idx);
left_node.key_area_mut(old_left_len).write(parent_key);
ptr::copy_nonoverlapping(
right_node.key_area_mut(..).as_ptr(),
left_node.key_area_mut(old_left_len + 1..).as_mut_ptr(),
right_len,
move_to_slice(
right_node.key_area_mut(..right_len),
left_node.key_area_mut(old_left_len + 1..new_left_len),
);
let parent_val = slice_remove(parent_node.val_area_mut(..old_parent_len), parent_idx);
left_node.val_area_mut(old_left_len).write(parent_val);
ptr::copy_nonoverlapping(
right_node.val_area_mut(..).as_ptr(),
left_node.val_area_mut(old_left_len + 1..).as_mut_ptr(),
right_len,
move_to_slice(
right_node.val_area_mut(..right_len),
left_node.val_area_mut(old_left_len + 1..new_left_len),
);
slice_remove(&mut parent_node.edge_area_mut(..old_parent_len + 1), parent_idx + 1);
......@@ -1346,10 +1343,9 @@ pub fn merge(
// of the node of this edge, thus above zero, so they are internal.
let mut left_node = left_node.reborrow_mut().cast_to_internal_unchecked();
let mut right_node = right_node.cast_to_internal_unchecked();
ptr::copy_nonoverlapping(
right_node.edge_area_mut(..).as_ptr(),
left_node.edge_area_mut(old_left_len + 1..).as_mut_ptr(),
right_len + 1,
move_to_slice(
right_node.edge_area_mut(..right_len + 1),
left_node.edge_area_mut(old_left_len + 1..new_left_len + 1),
);
left_node.correct_childrens_parent_links(old_left_len + 1..new_left_len + 1);
......@@ -1741,5 +1737,15 @@ unsafe fn slice_remove<T>(slice: &mut [MaybeUninit<T>], idx: usize) -> T {
}
}
/// Moves all values from a slice of initialized elements to a slice
/// of uninitialized elements, leaving behind `src` as all uninitialized.
/// Works like `dst.copy_from_slice(src)` but does not require `T` to be `Copy`.
fn move_to_slice<T>(src: &mut [MaybeUninit<T>], dst: &mut [MaybeUninit<T>]) {
assert!(src.len() == dst.len());
unsafe {
ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), src.len());
}
}
#[cfg(test)]
mod tests;
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册