Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
7 changes: 6 additions & 1 deletion library/alloc/src/collections/btree/append.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ where
/// If two keys are equal, returns the key-value pair from the right source.
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));
b_next.or(a_next)
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,
}
}
}
34 changes: 31 additions & 3 deletions library/alloc/src/collections/btree/map/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::fmt::Debug;
use crate::rc::Rc;
use crate::string::{String, ToString};
use crate::testing::crash_test::{CrashTestDummy, Panic};
use crate::testing::ord_chaos::{Cyclic3, Governed, Governor};
use crate::testing::ord_chaos::{Cyclic3, Governed, Governor, IdBased};
use crate::testing::rng::DeterministicRng;

// Minimum number of elements to insert, to guarantee a tree with 2 levels,
Expand Down Expand Up @@ -2137,9 +2137,9 @@ fn test_append_drop_leak() {
let mut left = BTreeMap::new();
let mut right = BTreeMap::new();
left.insert(a.spawn(Panic::Never), ());
left.insert(b.spawn(Panic::InDrop), ()); // first duplicate key, dropped during append
left.insert(b.spawn(Panic::Never), ());
left.insert(c.spawn(Panic::Never), ());
right.insert(b.spawn(Panic::Never), ());
right.insert(b.spawn(Panic::InDrop), ()); // first duplicate key, dropped during append
right.insert(c.spawn(Panic::Never), ());

catch_unwind(move || left.append(&mut right)).unwrap_err();
Expand Down Expand Up @@ -2587,3 +2587,31 @@ fn cursor_peek_prev_agrees_with_cursor_mut() {
let prev = cursor.peek_prev();
assert_matches!(prev, Some((&3, _)));
}

#[test]
fn test_id_based_insert() {
let mut lhs = BTreeMap::new();
let mut rhs = BTreeMap::new();

lhs.insert(IdBased { id: 0, name: "lhs_k".to_string() }, "lhs_v".to_string());
rhs.insert(IdBased { id: 0, name: "rhs_k".to_string() }, "rhs_v".to_string());

for (k, v) in rhs.into_iter() {
lhs.insert(k, v);
}

assert_eq!(lhs.pop_first().unwrap().0.name, "lhs_k".to_string());
}

#[test]
fn test_id_based_append() {
let mut lhs = BTreeMap::new();
let mut rhs = BTreeMap::new();

lhs.insert(IdBased { id: 0, name: "lhs_k".to_string() }, "lhs_v".to_string());
rhs.insert(IdBased { id: 0, name: "rhs_k".to_string() }, "rhs_v".to_string());

lhs.append(&mut rhs);

assert_eq!(lhs.pop_first().unwrap().0.name, "lhs_k".to_string());
}
30 changes: 30 additions & 0 deletions library/alloctests/testing/ord_chaos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use std::cell::Cell;
use std::cmp::Ordering::{self, *};
use std::ptr;

use crate::string::String;

// Minimal type with an `Ord` implementation violating transitivity.
#[derive(Debug)]
pub(crate) enum Cyclic3 {
Expand Down Expand Up @@ -79,3 +81,31 @@ impl<T: PartialEq> PartialEq for Governed<'_, T> {
}

impl<T: Eq> Eq for Governed<'_, T> {}

// Comparison based only on the ID, the name is ignored.
#[derive(Debug)]
pub(crate) struct IdBased {
pub id: u32,
#[allow(dead_code)]
pub name: String,
}

impl PartialEq for IdBased {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}

impl Eq for IdBased {}

impl PartialOrd for IdBased {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

impl Ord for IdBased {
fn cmp(&self, other: &Self) -> Ordering {
self.id.cmp(&other.id)
}
}
Loading