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
83 changes: 35 additions & 48 deletions library/alloc/src/collections/btree/map.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use core::borrow::Borrow;
use core::cmp::Ordering;
use core::cmp::{Comparable, Ordering};
use core::error::Error;
use core::fmt::{self, Debug};
use core::hash::{Hash, Hasher};
Expand Down Expand Up @@ -317,7 +316,7 @@ impl<K, A: Allocator + Clone> BTreeMap<K, SetValZST, A> {
let (map, dormant_map) = DormantMutRef::new(self);
let root_node =
map.root.get_or_insert_with(|| Root::new((*map.alloc).clone())).borrow_mut();
match root_node.search_tree::<K>(&key) {
match root_node.search_tree(&key) {
Found(mut kv) => Some(mem::replace(kv.key_mut(), key)),
GoDown(handle) => {
VacantEntry {
Expand All @@ -333,20 +332,19 @@ impl<K, A: Allocator + Clone> BTreeMap<K, SetValZST, A> {
}
}

pub(super) fn get_or_insert_with<Q: ?Sized, F>(&mut self, q: &Q, f: F) -> &K
pub(super) fn get_or_insert_with<Q: Clone, F>(&mut self, q: Q, f: F) -> &K
where
K: Borrow<Q> + Ord,
Q: Ord,
F: FnOnce(&Q) -> K,
K: Comparable<Q> + Ord,
F: FnOnce(Q) -> K,
{
let (map, dormant_map) = DormantMutRef::new(self);
let root_node =
map.root.get_or_insert_with(|| Root::new((*map.alloc).clone())).borrow_mut();
match root_node.search_tree(q) {
match root_node.search_tree(q.clone()) {
Found(handle) => handle.into_kv_mut().0,
GoDown(handle) => {
let key = f(q);
assert!(*key.borrow() == *q, "new value is not equal");
let key = f(q.clone());
assert!(key.compare(q) == Ordering::Equal, "new value is not equal");
VacantEntry {
key,
handle: Some(handle),
Expand Down Expand Up @@ -716,10 +714,9 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// assert_eq!(map.get(&2), None);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>
pub fn get<Q: Clone>(&self, key: Q) -> Option<&V>
where
K: Borrow<Q> + Ord,
Q: Ord,
K: Comparable<Q> + Ord,
{
let root_node = self.root.as_ref()?.reborrow();
match root_node.search_tree(key) {
Expand Down Expand Up @@ -782,10 +779,9 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// assert_eq!(map.get_key_value(&p), None);
/// ```
#[stable(feature = "map_get_key_value", since = "1.40.0")]
pub fn get_key_value<Q: ?Sized>(&self, k: &Q) -> Option<(&K, &V)>
pub fn get_key_value<Q: Clone>(&self, k: Q) -> Option<(&K, &V)>
where
K: Borrow<Q> + Ord,
Q: Ord,
K: Comparable<Q> + Ord,
{
let root_node = self.root.as_ref()?.reborrow();
match root_node.search_tree(k) {
Expand Down Expand Up @@ -978,10 +974,9 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "btreemap_contains_key")]
pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
pub fn contains_key<Q: Clone>(&self, key: Q) -> bool
where
K: Borrow<Q> + Ord,
Q: Ord,
K: Comparable<Q> + Ord,
{
self.get(key).is_some()
}
Expand All @@ -1005,10 +1000,9 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// ```
// See `get` for implementation notes, this is basically a copy-paste with mut's added
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<&mut V>
pub fn get_mut<Q: Clone>(&mut self, key: Q) -> Option<&mut V>
where
K: Borrow<Q> + Ord,
Q: Ord,
K: Comparable<Q> + Ord,
{
let root_node = self.root.as_mut()?.borrow_mut();
match root_node.search_tree(key) {
Expand Down Expand Up @@ -1107,10 +1101,9 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_confusables("delete", "take")]
pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
pub fn remove<Q: Clone>(&mut self, key: Q) -> Option<V>
where
K: Borrow<Q> + Ord,
Q: Ord,
K: Comparable<Q> + Ord,
{
self.remove_entry(key).map(|(_, v)| v)
}
Expand All @@ -1132,10 +1125,9 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// assert_eq!(map.remove_entry(&1), None);
/// ```
#[stable(feature = "btreemap_remove_entry", since = "1.45.0")]
pub fn remove_entry<Q: ?Sized>(&mut self, key: &Q) -> Option<(K, V)>
pub fn remove_entry<Q: Clone>(&mut self, key: Q) -> Option<(K, V)>
where
K: Borrow<Q> + Ord,
Q: Ord,
K: Comparable<Q> + Ord,
{
let (map, dormant_map) = DormantMutRef::new(self);
let root_node = map.root.as_mut()?.borrow_mut();
Expand Down Expand Up @@ -1410,7 +1402,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
pub fn range<T: ?Sized, R>(&self, range: R) -> Range<'_, K, V>
where
T: Ord,
K: Borrow<T> + Ord,
K: for<'a> Comparable<&'a T>,
R: RangeBounds<T>,
{
if let Some(root) = &self.root {
Expand Down Expand Up @@ -1450,7 +1442,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
pub fn range_mut<T: ?Sized, R>(&mut self, range: R) -> RangeMut<'_, K, V>
where
T: Ord,
K: Borrow<T> + Ord,
K: for<'a> Comparable<&'a T>,
R: RangeBounds<T>,
{
if let Some(root) = &mut self.root {
Expand Down Expand Up @@ -1539,9 +1531,9 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// assert_eq!(b[&41], "e");
/// ```
#[stable(feature = "btree_split_off", since = "1.11.0")]
pub fn split_off<Q: ?Sized + Ord>(&mut self, key: &Q) -> Self
pub fn split_off<Q: Clone>(&mut self, key: Q) -> Self
where
K: Borrow<Q> + Ord,
K: Comparable<Q> + Ord,
A: Clone,
{
if self.is_empty() {
Expand Down Expand Up @@ -2616,10 +2608,9 @@ impl<K: Debug, V: Debug, A: Allocator + Clone> Debug for BTreeMap<K, V, A> {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<K, Q: ?Sized, V, A: Allocator + Clone> Index<&Q> for BTreeMap<K, V, A>
impl<K, Q: Clone, V, A: Allocator + Clone> Index<Q> for BTreeMap<K, V, A>
where
K: Borrow<Q> + Ord,
Q: Ord,
K: Comparable<Q> + Ord,
{
type Output = V;

Expand All @@ -2629,7 +2620,7 @@ where
///
/// Panics if the key is not present in the `BTreeMap`.
#[inline]
fn index(&self, key: &Q) -> &V {
fn index(&self, key: Q) -> &V {
self.get(key).expect("no entry found for key")
}
}
Expand Down Expand Up @@ -2870,10 +2861,9 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// assert_eq!(cursor.peek_next(), Some((&1, &"a")));
/// ```
#[unstable(feature = "btree_cursors", issue = "107540")]
pub fn lower_bound<Q: ?Sized>(&self, bound: Bound<&Q>) -> Cursor<'_, K, V>
pub fn lower_bound<Q: Clone>(&self, bound: Bound<Q>) -> Cursor<'_, K, V>
where
K: Borrow<Q> + Ord,
Q: Ord,
K: Comparable<Q> + Ord,
{
let root_node = match self.root.as_ref() {
None => return Cursor { current: None, root: None },
Expand Down Expand Up @@ -2923,10 +2913,9 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// assert_eq!(cursor.peek_next(), Some((&1, &mut "a")));
/// ```
#[unstable(feature = "btree_cursors", issue = "107540")]
pub fn lower_bound_mut<Q: ?Sized>(&mut self, bound: Bound<&Q>) -> CursorMut<'_, K, V, A>
pub fn lower_bound_mut<Q: Clone>(&mut self, bound: Bound<Q>) -> CursorMut<'_, K, V, A>
where
K: Borrow<Q> + Ord,
Q: Ord,
K: Comparable<Q> + Ord,
{
let (root, dormant_root) = DormantMutRef::new(&mut self.root);
let root_node = match root.as_mut() {
Expand Down Expand Up @@ -2993,10 +2982,9 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// assert_eq!(cursor.peek_next(), None);
/// ```
#[unstable(feature = "btree_cursors", issue = "107540")]
pub fn upper_bound<Q: ?Sized>(&self, bound: Bound<&Q>) -> Cursor<'_, K, V>
pub fn upper_bound<Q: Clone>(&self, bound: Bound<Q>) -> Cursor<'_, K, V>
where
K: Borrow<Q> + Ord,
Q: Ord,
K: Comparable<Q> + Ord,
{
let root_node = match self.root.as_ref() {
None => return Cursor { current: None, root: None },
Expand Down Expand Up @@ -3046,10 +3034,9 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// assert_eq!(cursor.peek_next(), None);
/// ```
#[unstable(feature = "btree_cursors", issue = "107540")]
pub fn upper_bound_mut<Q: ?Sized>(&mut self, bound: Bound<&Q>) -> CursorMut<'_, K, V, A>
pub fn upper_bound_mut<Q: Clone>(&mut self, bound: Bound<Q>) -> CursorMut<'_, K, V, A>
where
K: Borrow<Q> + Ord,
Q: Ord,
K: Comparable<Q> + Ord,
{
let (root, dormant_root) = DormantMutRef::new(&mut self.root);
let root_node = match root.as_mut() {
Expand Down
17 changes: 17 additions & 0 deletions library/alloc/src/collections/btree/map/tests.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use core::assert_matches;
use std::borrow::Borrow;
use std::ops::Bound::{Excluded, Included, Unbounded};
use std::panic::{AssertUnwindSafe, catch_unwind};
use std::sync::atomic::AtomicUsize;
Expand Down Expand Up @@ -2795,3 +2796,19 @@ fn test_id_based_merge() {
assert_eq!(merged_kv_pair.0.id, 0);
assert_eq!(merged_kv_pair.0.name, "lhs_k".to_string());
}

#[test]
fn test_comparable_tuple_lookup() {
let mut map = BTreeMap::new();
map.insert(("hello".to_string(), "world".to_string()), 1);
map.insert(("foo".to_string(), "bar".to_string()), 2);

assert_eq!(map.get(("hello", "world")), Some(&1));
assert_eq!(map.get(("foo", "bar")), Some(&2));
assert_eq!(map.get(("missing", "key")), None);

assert!(map.contains_key(("hello", "world")));
assert!(!map.contains_key(("missing", "key")));

assert_eq!(map[("foo", "bar")], 2);
}
22 changes: 10 additions & 12 deletions library/alloc/src/collections/btree/navigate.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use core::borrow::Borrow;
use core::cmp::Comparable;
use core::ops::RangeBounds;
use core::{hint, ptr};

Expand Down Expand Up @@ -267,7 +267,7 @@ impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Lea
) -> LeafRange<BorrowType, K, V>
where
Q: Ord,
K: Borrow<Q>,
K: for<'a> Comparable<&'a Q>,
R: RangeBounds<Q>,
{
match self.search_tree_for_bifurcation(&range) {
Expand Down Expand Up @@ -316,7 +316,7 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>
pub(super) fn range_search<Q, R>(self, range: R) -> LeafRange<marker::Immut<'a>, K, V>
where
Q: ?Sized + Ord,
K: Borrow<Q>,
K: for<'b> Comparable<&'b Q>,
R: RangeBounds<Q>,
{
// SAFETY: our borrow type is immutable.
Expand All @@ -342,7 +342,7 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::ValMut<'a>, K, V, marker::LeafOrInternal>
pub(super) fn range_search<Q, R>(self, range: R) -> LeafRange<marker::ValMut<'a>, K, V>
where
Q: ?Sized + Ord,
K: Borrow<Q>,
K: for<'b> Comparable<&'b Q>,
R: RangeBounds<Q>,
{
unsafe { self.find_leaf_edges_spanning_range(range) }
Expand Down Expand Up @@ -741,13 +741,12 @@ impl<BorrowType: marker::BorrowType, K, V>
impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
/// Returns the leaf edge corresponding to the first point at which the
/// given bound is true.
pub(super) fn lower_bound<Q: ?Sized>(
pub(super) fn lower_bound<Q: Clone>(
self,
mut bound: SearchBound<&Q>,
mut bound: SearchBound<Q>,
) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>
where
Q: Ord,
K: Borrow<Q>,
K: Comparable<Q>,
{
let mut node = self;
loop {
Expand All @@ -764,13 +763,12 @@ impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Lea

/// Returns the leaf edge corresponding to the last point at which the
/// given bound is true.
pub(super) fn upper_bound<Q: ?Sized>(
pub(super) fn upper_bound<Q: Clone>(
self,
mut bound: SearchBound<&Q>,
mut bound: SearchBound<Q>,
) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>
where
Q: Ord,
K: Borrow<Q>,
K: Comparable<Q>,
{
let mut node = self;
loop {
Expand Down
Loading
Loading