Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 0 additions & 51 deletions library/alloc/src/collections/btree/append.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,8 @@
use core::alloc::Allocator;
use core::iter::FusedIterator;

use super::merge_iter::MergeIterInner;
use super::node::{self, Root};

impl<K, V> Root<K, V> {
/// Appends all key-value pairs from the union of two ascending iterators,
/// incrementing a `length` variable along the way. The latter makes it
/// easier for the caller to avoid a leak when a drop handler panicks.
///
/// If both iterators produce the same key, this method drops the pair from
/// the left iterator and appends the pair from the right iterator.
///
/// If you want the tree to end up in a strictly ascending order, like for
/// a `BTreeMap`, both iterators should produce keys in strictly ascending
/// order, each greater than all keys in the tree, including any keys
/// already in the tree upon entry.
pub(super) fn append_from_sorted_iters<I, A: Allocator + Clone>(
&mut self,
left: I,
right: I,
length: &mut usize,
alloc: A,
) where
K: Ord,
I: Iterator<Item = (K, V)> + FusedIterator,
{
// We prepare to merge `left` and `right` into a sorted sequence in linear time.
let iter = MergeIter(MergeIterInner::new(left, right));

// Meanwhile, we build a tree from the sorted sequence in linear time.
self.bulk_push(iter, length, alloc)
}

/// Pushes all key-value pairs to the end of the tree, incrementing a
/// `length` variable along the way. The latter makes it easier for the
/// caller to avoid a leak when the iterator panicks.
Expand Down Expand Up @@ -94,24 +64,3 @@ impl<K, V> Root<K, V> {
self.fix_right_border_of_plentiful();
}
}

// An iterator for merging two sorted sequences into one
struct MergeIter<K, V, I: Iterator<Item = (K, V)>>(MergeIterInner<I>);

impl<K: Ord, V, I> Iterator for MergeIter<K, V, I>
where
I: Iterator<Item = (K, V)> + FusedIterator,
{
type Item = (K, V);

/// If two keys are equal, returns the key from the left and the value from the right.
fn next(&mut self) -> Option<(K, V)> {
let (a_next, b_next) = self.0.nexts(|a: &(K, V), b: &(K, V)| K::cmp(&a.0, &b.0));
match (a_next, b_next) {
(Some((a_k, _)), Some((_, b_v))) => Some((a_k, b_v)),
(Some(a), None) => Some(a),
(None, Some(b)) => Some(b),
(None, None) => None,
}
}
}
22 changes: 2 additions & 20 deletions library/alloc/src/collections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1218,26 +1218,8 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
K: Ord,
A: Clone,
{
// Do we have to append anything at all?
if other.is_empty() {
return;
}

// We can just swap `self` and `other` if `self` is empty.
if self.is_empty() {
mem::swap(self, other);
return;
}

let self_iter = mem::replace(self, Self::new_in((*self.alloc).clone())).into_iter();
let other_iter = mem::replace(other, Self::new_in((*self.alloc).clone())).into_iter();
let root = self.root.get_or_insert_with(|| Root::new((*self.alloc).clone()));
root.append_from_sorted_iters(
self_iter,
other_iter,
&mut self.length,
(*self.alloc).clone(),
)
let other = mem::replace(other, Self::new_in((*self.alloc).clone()));
self.merge(other, |_key, _self_val, other_val| other_val);
}

/// Moves all elements from `other` into `self`, leaving `other` empty.
Expand Down
2 changes: 1 addition & 1 deletion library/alloc/src/collections/btree/map/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2224,7 +2224,7 @@ fn test_append_drop_leak() {

catch_unwind(move || left.append(&mut right)).unwrap_err();
assert_eq!(a.dropped(), 1);
assert_eq!(b.dropped(), 1); // should be 2 were it not for Rust issue #47949
assert_eq!(b.dropped(), 2);
assert_eq!(c.dropped(), 2);
}

Expand Down
Loading