diff --git a/src/map.rs b/src/map.rs index bb182ed3..e16e064a 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1648,6 +1648,28 @@ mod tests { assert_eq!(&mut TestEnum::DefaultValue, map.entry(2).or_default()); } + #[test] + fn occupied_entry_key() { + // These keys match hash and equality, but their addresses are distinct. + let (k1, k2) = (&mut 1, &mut 1); + let k1_ptr = k1 as *const i32; + let k2_ptr = k2 as *const i32; + assert_ne!(k1_ptr, k2_ptr); + + let mut map = IndexMap::new(); + map.insert(k1, "value"); + match map.entry(k2) { + Entry::Occupied(ref e) => { + // `OccupiedEntry::key` should reference the key in the map, + // not the key that was used to find the entry. + let ptr = *e.key() as *const i32; + assert_eq!(ptr, k1_ptr); + assert_ne!(ptr, k2_ptr); + }, + Entry::Vacant(_) => panic!(), + } + } + #[test] fn keys() { let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; diff --git a/src/map/core.rs b/src/map/core.rs index 02e99e07..9482b2f5 100644 --- a/src/map/core.rs +++ b/src/map/core.rs @@ -464,6 +464,8 @@ impl<'a, K, V> Entry<'a, K, V> { } } + /// Gets a reference to the entry's key, either within the map if occupied, + /// or else the new key that was used to find the entry. pub fn key(&self) -> &K { match *self { Entry::Occupied(ref entry) => entry.key(), @@ -583,6 +585,7 @@ pub struct VacantEntry<'a, K, V> { } impl<'a, K, V> VacantEntry<'a, K, V> { + /// Gets a reference to the key that was used to find the entry. pub fn key(&self) -> &K { &self.key } diff --git a/src/map/core/raw.rs b/src/map/core/raw.rs index 3388f123..be91b3d6 100644 --- a/src/map/core/raw.rs +++ b/src/map/core/raw.rs @@ -104,8 +104,13 @@ unsafe impl Sync for OccupiedEntry<'_, K, V> {} // The parent module also adds methods that don't threaten the unsafe encapsulation. impl<'a, K, V> OccupiedEntry<'a, K, V> { + /// Gets a reference to the entry's key in the map. + /// + /// Note that this is not the key that was used to find the entry. There may be an observable + /// difference if the key type has any distinguishing features outside of `Hash` and `Eq`, like + /// extra fields or the memory address of an allocation. pub fn key(&self) -> &K { - &self.key + &self.map.entries[self.index()].key } pub fn get(&self) -> &V {