From 03f5a41b4fb367dd2935988cb5623c75f1b60c11 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 9 Apr 2024 08:35:04 -0700 Subject: [PATCH] Add an assertion to `HashSet::get_or_insert_with` Since the Rust libs-api team considers it problematic for `HashSet` to be unreliable with well-behaved `T` (not user-controlled), we should not allow mismatches to be inserted through `get_or_insert_with`. --- src/set.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/set.rs b/src/set.rs index 0ade464dc..a17871f17 100644 --- a/src/set.rs +++ b/src/set.rs @@ -955,6 +955,10 @@ where /// Inserts a value computed from `f` into the set if the given `value` is /// not present, then returns a reference to the value in the set. /// + /// # Panics + /// + /// Will panic if `f`'s return value is not equivalent to the query `value`. + /// /// # Examples /// /// ``` @@ -970,6 +974,13 @@ where /// } /// assert_eq!(set.len(), 4); // a new "fish" was inserted /// ``` + /// + /// The following example will panic because the new value doesn't match. + /// + /// ```should_panic + /// let mut set = hashbrown::HashSet::new(); + /// set.get_or_insert_with("rust", |_| String::new()); + /// ``` #[cfg_attr(feature = "inline-more", inline)] pub fn get_or_insert_with(&mut self, value: &Q, f: F) -> &T where @@ -981,7 +992,11 @@ where self.map .raw_entry_mut() .from_key(value) - .or_insert_with(|| (f(value), ())) + .or_insert_with(|| { + let new = f(value); + assert!(value.equivalent(&new), "new value is not equivalent"); + (new, ()) + }) .0 }