diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 8094356910f8c..7d994359ed48b 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -1059,7 +1059,7 @@ impl BTreeMap { /// a mutable reference to the value in the entry. /// /// If the map already had this key present, nothing is updated, and - /// an error containing the occupied entry and the value is returned. + /// an error containing the occupied entry, key, and the value is returned. /// /// # Examples /// @@ -1074,6 +1074,7 @@ impl BTreeMap { /// let err = map.try_insert(37, "b").unwrap_err(); /// assert_eq!(err.entry.key(), &37); /// assert_eq!(err.entry.get(), &"a"); + /// assert_eq!(err.key, 37); /// assert_eq!(err.value, "b"); /// ``` #[unstable(feature = "map_try_insert", issue = "82766")] @@ -1081,10 +1082,30 @@ impl BTreeMap { where K: Ord, { - match self.entry(key) { - Occupied(entry) => Err(OccupiedError { entry, value }), - Vacant(entry) => Ok(entry.insert(value)), - } + let (map, dormant_map) = DormantMutRef::new(self); + let handle = match map.root { + Some(ref mut root) => match root.borrow_mut().search_tree(&key) { + Found(handle) => { + let entry = OccupiedEntry { + handle, + dormant_map, + alloc: (*map.alloc).clone(), + _marker: PhantomData, + }; + return Err(OccupiedError { entry, key, value }); + } + GoDown(handle) => Some(handle), + }, + None => None, + }; + let entry = VacantEntry { + key, + handle, + dormant_map, + alloc: (*map.alloc).clone(), + _marker: PhantomData, + }; + Ok(entry.insert(value)) } /// Removes a key from the map, returning the value at the key if the key diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs index add8782a9499a..fc6c11fc0fb05 100644 --- a/library/alloc/src/collections/btree/map/entry.rs +++ b/library/alloc/src/collections/btree/map/entry.rs @@ -97,8 +97,9 @@ impl Debug for OccupiedEntry<'_, /// The error returned by [`try_insert`](BTreeMap::try_insert) when the key already exists. /// -/// Contains the occupied entry, and the value that was not inserted. +/// Contains the occupied entry, key, and the value that was not inserted. #[unstable(feature = "map_try_insert", issue = "82766")] +#[non_exhaustive] pub struct OccupiedError< 'a, K: 'a, @@ -109,6 +110,8 @@ pub struct OccupiedError< pub entry: OccupiedEntry<'a, K, V, A>, /// The value which was not inserted, because the entry was already occupied. pub value: V, + /// The key which was not inserted, because the entry was already occupied. + pub key: K, } #[unstable(feature = "map_try_insert", issue = "82766")] @@ -116,33 +119,13 @@ impl Debug for OccupiedError<'_, fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("OccupiedError") .field("key", self.entry.key()) + .field("uninserted_key", &self.key) .field("old_value", self.entry.get()) .field("new_value", &self.value) .finish() } } -#[unstable(feature = "map_try_insert", issue = "82766")] -impl<'a, K: Debug + Ord, V: Debug, A: Allocator + Clone> fmt::Display - for OccupiedError<'a, K, V, A> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "failed to insert {:?}, key {:?} already exists with value {:?}", - self.value, - self.entry.key(), - self.entry.get(), - ) - } -} - -#[unstable(feature = "map_try_insert", issue = "82766")] -impl<'a, K: core::fmt::Debug + Ord, V: core::fmt::Debug> core::error::Error - for crate::collections::btree_map::OccupiedError<'a, K, V> -{ -} - impl<'a, K: Ord, V, A: Allocator + Clone> Entry<'a, K, V, A> { /// Ensures a value is in the entry by inserting the default if empty, and returns /// a mutable reference to the value in the entry. diff --git a/library/alloc/src/collections/mod.rs b/library/alloc/src/collections/mod.rs index d306d2016ea28..d11cf5a594148 100644 --- a/library/alloc/src/collections/mod.rs +++ b/library/alloc/src/collections/mod.rs @@ -19,6 +19,7 @@ pub mod vec_deque; pub mod btree_map { //! An ordered map based on a B-Tree. #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(not(test))] pub use super::btree::map::*; } diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 4192254f6c824..33e5ae530f499 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -1,13 +1,12 @@ #[cfg(test)] mod tests; -use hashbrown::hash_map as base; +use hashbrown::hash_map::{self as base, RustcEntry}; use self::Entry::*; use crate::alloc::{Allocator, Global}; use crate::borrow::Borrow; use crate::collections::{TryReserveError, TryReserveErrorKind}; -use crate::error::Error; use crate::fmt::{self, Debug}; use crate::hash::{BuildHasher, Hash, RandomState}; use crate::iter::FusedIterator; @@ -1333,7 +1332,7 @@ where /// a mutable reference to the value in the entry. /// /// If the map already had this key present, nothing is updated, and - /// an error containing the occupied entry and the value is returned. + /// an error containing the occupied entry, key, and the value is returned. /// /// # Examples /// @@ -1350,13 +1349,16 @@ where /// let err = map.try_insert(37, "b").unwrap_err(); /// assert_eq!(err.entry.key(), &37); /// assert_eq!(err.entry.get(), &"a"); + /// assert_eq!(err.key, 37); /// assert_eq!(err.value, "b"); /// ``` #[unstable(feature = "map_try_insert", issue = "82766")] pub fn try_insert(&mut self, key: K, value: V) -> Result<&mut V, OccupiedError<'_, K, V, A>> { - match self.entry(key) { - Occupied(entry) => Err(OccupiedError { entry, value }), - Vacant(entry) => Ok(entry.insert(value)), + match self.base.rustc_entry(key) { + RustcEntry::Occupied(entry, key) => { + Err(OccupiedError { entry: OccupiedEntry { base: entry }, key, value }) + } + RustcEntry::Vacant(entry) => Ok(entry.insert(value)), } } @@ -2007,8 +2009,9 @@ impl Debug for VacantEntry<'_, K, V, A> { /// The error returned by [`try_insert`](HashMap::try_insert) when the key already exists. /// -/// Contains the occupied entry, and the value that was not inserted. +/// Contains the occupied entry, key, and the value that was not inserted. #[unstable(feature = "map_try_insert", issue = "82766")] +#[non_exhaustive] pub struct OccupiedError< 'a, K: 'a, @@ -2019,6 +2022,8 @@ pub struct OccupiedError< pub entry: OccupiedEntry<'a, K, V, A>, /// The value which was not inserted, because the entry was already occupied. pub value: V, + /// The key which was not inserted, because the entry was already occupied. + pub key: K, } #[unstable(feature = "map_try_insert", issue = "82766")] @@ -2026,28 +2031,13 @@ impl Debug for OccupiedError<'_, K, V, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("OccupiedError") .field("key", self.entry.key()) + .field("uninserted_key", &self.key) .field("old_value", self.entry.get()) .field("new_value", &self.value) .finish_non_exhaustive() } } -#[unstable(feature = "map_try_insert", issue = "82766")] -impl<'a, K: Debug, V: Debug, A: Allocator> fmt::Display for OccupiedError<'a, K, V, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "failed to insert {:?}, key {:?} already exists with value {:?}", - self.value, - self.entry.key(), - self.entry.get(), - ) - } -} - -#[unstable(feature = "map_try_insert", issue = "82766")] -impl<'a, K: Debug, V: Debug, A: Allocator> Error for OccupiedError<'a, K, V, A> {} - #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K, V, S, A: Allocator> IntoIterator for &'a HashMap { type Item = (&'a K, &'a V); @@ -3010,7 +3000,7 @@ fn map_entry<'a, K: 'a, V: 'a, A: Allocator>( raw: base::RustcEntry<'a, K, V, A>, ) -> Entry<'a, K, V, A> { match raw { - base::RustcEntry::Occupied(base) => Entry::Occupied(OccupiedEntry { base }), + base::RustcEntry::Occupied(base, _) => Entry::Occupied(OccupiedEntry { base }), base::RustcEntry::Vacant(base) => Entry::Vacant(VacantEntry { base }), } }