Skip to content

Commit ddc2088

Browse files
authored
Merge pull request #170 from cuviper/entry-key
Change OccupiedEntry::key() to return the existing key in the map
2 parents 015eeea + 0d801a6 commit ddc2088

File tree

3 files changed

+47
-1
lines changed

3 files changed

+47
-1
lines changed

src/map.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1648,6 +1648,28 @@ mod tests {
16481648
assert_eq!(&mut TestEnum::DefaultValue, map.entry(2).or_default());
16491649
}
16501650

1651+
#[test]
1652+
fn occupied_entry_key() {
1653+
// These keys match hash and equality, but their addresses are distinct.
1654+
let (k1, k2) = (&mut 1, &mut 1);
1655+
let k1_ptr = k1 as *const i32;
1656+
let k2_ptr = k2 as *const i32;
1657+
assert_ne!(k1_ptr, k2_ptr);
1658+
1659+
let mut map = IndexMap::new();
1660+
map.insert(k1, "value");
1661+
match map.entry(k2) {
1662+
Entry::Occupied(ref e) => {
1663+
// `OccupiedEntry::key` should reference the key in the map,
1664+
// not the key that was used to find the entry.
1665+
let ptr = *e.key() as *const i32;
1666+
assert_eq!(ptr, k1_ptr);
1667+
assert_ne!(ptr, k2_ptr);
1668+
},
1669+
Entry::Vacant(_) => panic!(),
1670+
}
1671+
}
1672+
16511673
#[test]
16521674
fn keys() {
16531675
let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];

src/map/core.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,9 @@ pub enum Entry<'a, K, V> {
445445
}
446446

447447
impl<'a, K, V> Entry<'a, K, V> {
448+
/// Inserts the given default value in the entry if it is vacant and returns a mutable
449+
/// reference to it. Otherwise a mutable reference to an already existent value is returned.
450+
///
448451
/// Computes in **O(1)** time (amortized average).
449452
pub fn or_insert(self, default: V) -> &'a mut V {
450453
match self {
@@ -453,6 +456,9 @@ impl<'a, K, V> Entry<'a, K, V> {
453456
}
454457
}
455458

459+
/// Inserts the result of the `call` function in the entry if it is vacant and returns a mutable
460+
/// reference to it. Otherwise a mutable reference to an already existent value is returned.
461+
///
456462
/// Computes in **O(1)** time (amortized average).
457463
pub fn or_insert_with<F>(self, call: F) -> &'a mut V
458464
where
@@ -464,6 +470,8 @@ impl<'a, K, V> Entry<'a, K, V> {
464470
}
465471
}
466472

473+
/// Gets a reference to the entry's key, either within the map if occupied,
474+
/// or else the new key that was used to find the entry.
467475
pub fn key(&self) -> &K {
468476
match *self {
469477
Entry::Occupied(ref entry) => entry.key(),
@@ -583,10 +591,12 @@ pub struct VacantEntry<'a, K, V> {
583591
}
584592

585593
impl<'a, K, V> VacantEntry<'a, K, V> {
594+
/// Gets a reference to the key that was used to find the entry.
586595
pub fn key(&self) -> &K {
587596
&self.key
588597
}
589598

599+
/// Takes ownership of the key, leaving the entry vacant.
590600
pub fn into_key(self) -> K {
591601
self.key
592602
}
@@ -596,6 +606,8 @@ impl<'a, K, V> VacantEntry<'a, K, V> {
596606
self.map.len()
597607
}
598608

609+
/// Inserts the entry's key and the given value into the map, and returns a mutable reference
610+
/// to the value.
599611
pub fn insert(self, value: V) -> &'a mut V {
600612
let i = self.map.push(self.hash, self.key, value);
601613
&mut self.map.entries[i].value

src/map/core/raw.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,24 @@ unsafe impl<K: Sync, V: Sync> Sync for OccupiedEntry<'_, K, V> {}
104104

105105
// The parent module also adds methods that don't threaten the unsafe encapsulation.
106106
impl<'a, K, V> OccupiedEntry<'a, K, V> {
107+
/// Gets a reference to the entry's key in the map.
108+
///
109+
/// Note that this is not the key that was used to find the entry. There may be an observable
110+
/// difference if the key type has any distinguishing features outside of `Hash` and `Eq`, like
111+
/// extra fields or the memory address of an allocation.
107112
pub fn key(&self) -> &K {
108-
&self.key
113+
&self.map.entries[self.index()].key
109114
}
110115

116+
/// Gets a reference to the entry's value in the map.
111117
pub fn get(&self) -> &V {
112118
&self.map.entries[self.index()].value
113119
}
114120

121+
/// Gets a mutable reference to the entry's value in the map.
122+
///
123+
/// If you need a reference which may outlive the destruction of the
124+
/// `Entry` value, see `into_mut`.
115125
pub fn get_mut(&mut self) -> &mut V {
116126
let index = self.index();
117127
&mut self.map.entries[index].value
@@ -131,6 +141,8 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
131141
unsafe { self.raw_bucket.read() }
132142
}
133143

144+
/// Converts into a mutable reference to the entry's value in the map,
145+
/// with a lifetime bound to the map itself.
134146
pub fn into_mut(self) -> &'a mut V {
135147
let index = self.index();
136148
&mut self.map.entries[index].value

0 commit comments

Comments
 (0)