From de37dfd1fb8ca66662d4c571b4804ea2dbbe01ef Mon Sep 17 00:00:00 2001 From: Peter Hall Date: Tue, 6 Feb 2024 13:49:41 +0000 Subject: [PATCH 1/2] Add or_try_* variants for HashMap Entry API Doc typo --- library/std/src/collections/hash/map.rs | 76 +++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 5 deletions(-) diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 887efd12f550f..3eca5b6f974b6 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -2538,9 +2538,42 @@ impl<'a, K, V, A: Allocator> Entry<'a, K, V, A> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn or_insert_with V>(self, default: F) -> &'a mut V { + self.or_try_insert_with(|| Result::<_, !>::Ok(default())).unwrap() + } + + /// Ensures a value is in the entry by inserting the result of a fallible default function + /// if empty, and returns a mutable reference to the value in the entry. + /// + /// This method works identically to [`or_insert_with`] except that the default function + /// should return a `Result` and, in the case of an error, the error is propagated. + /// + /// [`or_insert_with`]: Self::or_insert_with + /// + /// # Examples + /// + /// ``` + /// # #![feature(try_entry)] + /// # fn main() -> Result<(), std::num::ParseIntError> { + /// use std::collections::HashMap; + /// + /// let mut map: HashMap<&str, usize> = HashMap::new(); + /// let value = "42"; + /// + /// map.entry("poneyland").or_try_insert_with(|| value.parse())?; + /// + /// assert_eq!(map["poneyland"], 42); + /// # Ok(()) + /// # } + /// ``` + #[inline] + #[unstable(feature = "try_entry", issue = "none")] + pub fn or_try_insert_with Result, E>( + self, + default: F, + ) -> Result<&'a mut V, E> { match self { - Occupied(entry) => entry.into_mut(), - Vacant(entry) => entry.insert(default()), + Occupied(entry) => Ok(entry.into_mut()), + Vacant(entry) => Ok(entry.insert(default()?)), } } @@ -2565,11 +2598,44 @@ impl<'a, K, V, A: Allocator> Entry<'a, K, V, A> { #[inline] #[stable(feature = "or_insert_with_key", since = "1.50.0")] pub fn or_insert_with_key V>(self, default: F) -> &'a mut V { + self.or_try_insert_with_key(|k| Result::<_, !>::Ok(default(k))).unwrap() + } + + /// Ensures a value is in the entry by inserting, if empty, the result of the default function. + /// This method allows for generating key-derived values for insertion by providing the default + /// function a reference to the key that was moved during the `entry(key)` method call. + /// + /// This method works identically to [`or_insert_with_key`] except that the default function + /// should return a `Result` and, in the case of an error, the error is propagated. + /// + /// [`or_insert_with_key`]: Self::or_insert_with_key + /// + /// # Examples + /// + /// ``` + /// # #![feature(try_entry)] + /// # fn main() -> Result<(), std::num::ParseIntError> { + /// use std::collections::HashMap; + /// + /// let mut map: HashMap<&str, usize> = HashMap::new(); + /// + /// map.entry("42").or_try_insert_with_key(|key| key.parse())?; + /// + /// assert_eq!(map["42"], 42); + /// # Ok(()) + /// # } + /// ``` + #[inline] + #[unstable(feature = "try_entry", issue = "none")] + pub fn or_try_insert_with_key Result, E>( + self, + default: F, + ) -> Result<&'a mut V, E> { match self { - Occupied(entry) => entry.into_mut(), + Occupied(entry) => Ok(entry.into_mut()), Vacant(entry) => { - let value = default(entry.key()); - entry.insert(value) + let value = default(entry.key())?; + Ok(entry.insert(value)) } } } From 683176de8e909ad668facad7ee2138a8d487957b Mon Sep 17 00:00:00 2001 From: Mahdi Ali-Raihan Date: Wed, 3 Jun 2026 00:53:20 -0400 Subject: [PATCH 2/2] Implement or_try_* methods on BTreeMap Entry API --- .../alloc/src/collections/btree/map/entry.rs | 76 +++++++++++++++++-- library/std/src/collections/hash/map.rs | 8 +- 2 files changed, 75 insertions(+), 9 deletions(-) diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs index b99fbb5e84bd6..38cc3f0b14f2b 100644 --- a/library/alloc/src/collections/btree/map/entry.rs +++ b/library/alloc/src/collections/btree/map/entry.rs @@ -165,9 +165,42 @@ impl<'a, K: Ord, V, A: Allocator + Clone> Entry<'a, K, V, A> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn or_insert_with V>(self, default: F) -> &'a mut V { + self.or_try_insert_with(|| Result::<_, !>::Ok(default())).unwrap() + } + + /// Ensures a value is in the entry by inserting the result of a fallible default function + /// if empty, and returns a mutable reference to the value in the entry. + /// + /// This method works identically to [`or_insert_with`] except that the default function + /// should return a `Result` and, in the case of an error, the error is propagated. + /// + /// [`or_insert_with`]: Self::or_insert_with + /// + /// # Examples + /// + /// ``` + /// #![feature(try_entry)] + /// # fn main() -> Result<(), std::num::ParseIntError> { + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// let value = "42"; + /// + /// map.entry("poneyland").or_try_insert_with(|| value.parse())?; + /// + /// assert_eq!(map["poneyland"], 42); + /// # Ok(()) + /// # } + /// ``` + #[inline] + #[unstable(feature = "try_entry", issue = "157354")] + pub fn or_try_insert_with Result, E>( + self, + default: F, + ) -> Result<&'a mut V, E> { match self { - Occupied(entry) => entry.into_mut(), - Vacant(entry) => entry.insert(default()), + Occupied(entry) => Ok(entry.into_mut()), + Vacant(entry) => Ok(entry.insert(default()?)), } } @@ -193,11 +226,44 @@ impl<'a, K: Ord, V, A: Allocator + Clone> Entry<'a, K, V, A> { #[inline] #[stable(feature = "or_insert_with_key", since = "1.50.0")] pub fn or_insert_with_key V>(self, default: F) -> &'a mut V { + self.or_try_insert_with_key(|k| Result::<_, !>::Ok(default(k))).unwrap() + } + + /// Ensures a value is in the entry by inserting, if empty, the result of the default function. + /// This method allows for generating key-derived values for insertion by providing the default + /// function a reference to the key that was moved during the `entry(key)` method call. + /// + /// This method works identically to [`or_insert_with_key`] except that the default function + /// should return a `Result` and, in the case of an error, the error is propagated. + /// + /// [`or_insert_with_key`]: Self::or_insert_with_key + /// + /// # Examples + /// + /// ``` + /// #![feature(try_entry)] + /// # fn main() -> Result<(), std::num::ParseIntError> { + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// + /// map.entry("42").or_try_insert_with_key(|key| key.parse())?; + /// + /// assert_eq!(map["42"], 42); + /// # Ok(()) + /// # } + /// ``` + #[inline] + #[unstable(feature = "try_entry", issue = "157354")] + pub fn or_try_insert_with_key Result, E>( + self, + default: F, + ) -> Result<&'a mut V, E> { match self { - Occupied(entry) => entry.into_mut(), + Occupied(entry) => Ok(entry.into_mut()), Vacant(entry) => { - let value = default(entry.key()); - entry.insert(value) + let value = default(entry.key())?; + Ok(entry.insert(value)) } } } diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 3eca5b6f974b6..e2c459d0ab467 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -2552,7 +2552,7 @@ impl<'a, K, V, A: Allocator> Entry<'a, K, V, A> { /// # Examples /// /// ``` - /// # #![feature(try_entry)] + /// #![feature(try_entry)] /// # fn main() -> Result<(), std::num::ParseIntError> { /// use std::collections::HashMap; /// @@ -2566,7 +2566,7 @@ impl<'a, K, V, A: Allocator> Entry<'a, K, V, A> { /// # } /// ``` #[inline] - #[unstable(feature = "try_entry", issue = "none")] + #[unstable(feature = "try_entry", issue = "157354")] pub fn or_try_insert_with Result, E>( self, default: F, @@ -2613,7 +2613,7 @@ impl<'a, K, V, A: Allocator> Entry<'a, K, V, A> { /// # Examples /// /// ``` - /// # #![feature(try_entry)] + /// #![feature(try_entry)] /// # fn main() -> Result<(), std::num::ParseIntError> { /// use std::collections::HashMap; /// @@ -2626,7 +2626,7 @@ impl<'a, K, V, A: Allocator> Entry<'a, K, V, A> { /// # } /// ``` #[inline] - #[unstable(feature = "try_entry", issue = "none")] + #[unstable(feature = "try_entry", issue = "157354")] pub fn or_try_insert_with_key Result, E>( self, default: F,