From ca70543ca4e5d499503e23bf0bd42af1b9869a0a Mon Sep 17 00:00:00 2001 From: malezjaa Date: Wed, 15 Apr 2026 23:13:54 +0200 Subject: [PATCH] map_try_insert changes --- library/Cargo.lock | 4 +-- library/alloc/src/collections/btree/map.rs | 31 +++++++++++++--- .../alloc/src/collections/btree/map/entry.rs | 27 +++----------- library/alloc/src/collections/mod.rs | 1 + library/std/Cargo.toml | 2 +- library/std/src/collections/hash/map.rs | 36 +++++++------------ 6 files changed, 48 insertions(+), 53 deletions(-) diff --git a/library/Cargo.lock b/library/Cargo.lock index d7227def0461d..ae0b1da8396fb 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -125,9 +125,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.17.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" dependencies = [ "foldhash", "rustc-std-workspace-alloc", 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..b99fbb5e84bd6 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, @@ -107,6 +108,8 @@ pub struct OccupiedError< > { /// The entry in the map that was already occupied. pub entry: OccupiedEntry<'a, K, V, A>, + /// The key which was not inserted, because the entry was already occupied. + pub key: K, /// The value which was not inserted, because the entry was already occupied. pub value: V, } @@ -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/Cargo.toml b/library/std/Cargo.toml index a22ef6c6689c8..4825aa1f5aa7f 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -20,7 +20,7 @@ panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } unwind = { path = "../unwind" } -hashbrown = { version = "0.17.0", default-features = false, features = [ +hashbrown = { version = "0.17.1", default-features = false, features = [ 'rustc-dep-of-std', ] } std_detect = { path = "../std_detect", public = true } diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 4192254f6c824..50cfe8da150f9 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, RustcOccupiedError}; 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_try_insert(key, value) { + Result::Ok(value) => Ok(value), + Result::Err(RustcOccupiedError { entry, key, value, .. }) => { + Err(OccupiedError { entry: OccupiedEntry { base: entry }, key, 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, @@ -2017,6 +2020,8 @@ pub struct OccupiedError< > { /// The entry in the map that was already occupied. pub entry: OccupiedEntry<'a, K, V, A>, + /// The key which was not inserted, because the entry was already occupied. + pub key: K, /// The value which was not inserted, because the entry was already occupied. pub value: V, } @@ -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);