diff --git a/CHANGELOG.md b/CHANGELOG.md index 71baba694..0fef4caf7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- The `get_many_mut` family of methods have been renamed to `get_disjoint_mut` + to match the standard library. The old names are still present for now, but + deprecated. + ## [0.16.0](https://github.com/rust-lang/hashbrown/compare/v0.15.5...v0.16.0) - 2025-08-28 ### Changed diff --git a/src/map.rs b/src/map.rs index 392a7463c..86f0ce09a 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1486,13 +1486,13 @@ where /// libraries.insert("Library of Congress".to_string(), 1800); /// /// // Get Athenæum and Bodleian Library - /// let [Some(a), Some(b)] = libraries.get_many_mut([ + /// let [Some(a), Some(b)] = libraries.get_disjoint_mut([ /// "Athenæum", /// "Bodleian Library", /// ]) else { panic!() }; /// /// // Assert values of Athenæum and Library of Congress - /// let got = libraries.get_many_mut([ + /// let got = libraries.get_disjoint_mut([ /// "Athenæum", /// "Library of Congress", /// ]); @@ -1505,7 +1505,7 @@ where /// ); /// /// // Missing keys result in None - /// let got = libraries.get_many_mut([ + /// let got = libraries.get_disjoint_mut([ /// "Athenæum", /// "New York Public Library", /// ]); @@ -1525,16 +1525,26 @@ where /// libraries.insert("Athenæum".to_string(), 1807); /// /// // Duplicate keys panic! - /// let got = libraries.get_many_mut([ + /// let got = libraries.get_disjoint_mut([ /// "Athenæum", /// "Athenæum", /// ]); /// ``` + pub fn get_disjoint_mut(&mut self, ks: [&Q; N]) -> [Option<&'_ mut V>; N] + where + Q: Hash + Equivalent + ?Sized, + { + self.get_disjoint_mut_inner(ks) + .map(|res| res.map(|(_, v)| v)) + } + + /// Attempts to get mutable references to `N` values in the map at once. + #[deprecated(note = "use `get_disjoint_mut` instead")] pub fn get_many_mut(&mut self, ks: [&Q; N]) -> [Option<&'_ mut V>; N] where Q: Hash + Equivalent + ?Sized, { - self.get_many_mut_inner(ks).map(|res| res.map(|(_, v)| v)) + self.get_disjoint_mut(ks) } /// Attempts to get mutable references to `N` values in the map at once, without validating that @@ -1543,7 +1553,7 @@ where /// Returns an array of length `N` with the results of each query. `None` will be used if /// the key is missing. /// - /// For a safe alternative see [`get_many_mut`](`HashMap::get_many_mut`). + /// For a safe alternative see [`get_disjoint_mut`](`HashMap::get_disjoint_mut`). /// /// # Safety /// @@ -1564,13 +1574,13 @@ where /// libraries.insert("Library of Congress".to_string(), 1800); /// /// // SAFETY: The keys do not overlap. - /// let [Some(a), Some(b)] = (unsafe { libraries.get_many_unchecked_mut([ + /// let [Some(a), Some(b)] = (unsafe { libraries.get_disjoint_unchecked_mut([ /// "Athenæum", /// "Bodleian Library", /// ]) }) else { panic!() }; /// /// // SAFETY: The keys do not overlap. - /// let got = unsafe { libraries.get_many_unchecked_mut([ + /// let got = unsafe { libraries.get_disjoint_unchecked_mut([ /// "Athenæum", /// "Library of Congress", /// ]) }; @@ -1583,24 +1593,37 @@ where /// ); /// /// // SAFETY: The keys do not overlap. - /// let got = unsafe { libraries.get_many_unchecked_mut([ + /// let got = unsafe { libraries.get_disjoint_unchecked_mut([ /// "Athenæum", /// "New York Public Library", /// ]) }; /// // Missing keys result in None /// assert_eq!(got, [Some(&mut 1807), None]); /// ``` - pub unsafe fn get_many_unchecked_mut( + pub unsafe fn get_disjoint_unchecked_mut( &mut self, ks: [&Q; N], ) -> [Option<&'_ mut V>; N] where Q: Hash + Equivalent + ?Sized, { - self.get_many_unchecked_mut_inner(ks) + self.get_disjoint_unchecked_mut_inner(ks) .map(|res| res.map(|(_, v)| v)) } + /// Attempts to get mutable references to `N` values in the map at once, without validating that + /// the values are unique. + #[deprecated(note = "use `get_disjoint_unchecked_mut` instead")] + pub unsafe fn get_many_unchecked_mut( + &mut self, + ks: [&Q; N], + ) -> [Option<&'_ mut V>; N] + where + Q: Hash + Equivalent + ?Sized, + { + self.get_disjoint_unchecked_mut(ks) + } + /// Attempts to get mutable references to `N` values in the map at once, with immutable /// references to the corresponding keys. /// @@ -1622,7 +1645,7 @@ where /// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691); /// libraries.insert("Library of Congress".to_string(), 1800); /// - /// let got = libraries.get_many_key_value_mut([ + /// let got = libraries.get_disjoint_key_value_mut([ /// "Bodleian Library", /// "Herzogin-Anna-Amalia-Bibliothek", /// ]); @@ -1634,7 +1657,7 @@ where /// ], /// ); /// // Missing keys result in None - /// let got = libraries.get_many_key_value_mut([ + /// let got = libraries.get_disjoint_key_value_mut([ /// "Bodleian Library", /// "Gewandhaus", /// ]); @@ -1649,30 +1672,43 @@ where /// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691); /// /// // Duplicate keys result in panic! - /// let got = libraries.get_many_key_value_mut([ + /// let got = libraries.get_disjoint_key_value_mut([ /// "Bodleian Library", /// "Herzogin-Anna-Amalia-Bibliothek", /// "Herzogin-Anna-Amalia-Bibliothek", /// ]); /// ``` - pub fn get_many_key_value_mut( + pub fn get_disjoint_key_value_mut( &mut self, ks: [&Q; N], ) -> [Option<(&'_ K, &'_ mut V)>; N] where Q: Hash + Equivalent + ?Sized, { - self.get_many_mut_inner(ks) + self.get_disjoint_mut_inner(ks) .map(|res| res.map(|(k, v)| (&*k, v))) } + /// Attempts to get mutable references to `N` values in the map at once, with immutable + /// references to the corresponding keys. + #[deprecated(note = "use `get_disjoint_key_value_mut` instead")] + pub fn get_many_key_value_mut( + &mut self, + ks: [&Q; N], + ) -> [Option<(&'_ K, &'_ mut V)>; N] + where + Q: Hash + Equivalent + ?Sized, + { + self.get_disjoint_key_value_mut(ks) + } + /// Attempts to get mutable references to `N` values in the map at once, with immutable /// references to the corresponding keys, without validating that the values are unique. /// /// Returns an array of length `N` with the results of each query. `None` will be returned if /// any of the keys are missing. /// - /// For a safe alternative see [`get_many_key_value_mut`](`HashMap::get_many_key_value_mut`). + /// For a safe alternative see [`get_disjoint_key_value_mut`](`HashMap::get_disjoint_key_value_mut`). /// /// # Safety /// @@ -1692,7 +1728,7 @@ where /// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691); /// libraries.insert("Library of Congress".to_string(), 1800); /// - /// let got = libraries.get_many_key_value_mut([ + /// let got = libraries.get_disjoint_key_value_mut([ /// "Bodleian Library", /// "Herzogin-Anna-Amalia-Bibliothek", /// ]); @@ -1704,7 +1740,7 @@ where /// ], /// ); /// // Missing keys result in None - /// let got = libraries.get_many_key_value_mut([ + /// let got = libraries.get_disjoint_key_value_mut([ /// "Bodleian Library", /// "Gewandhaus", /// ]); @@ -1716,27 +1752,43 @@ where /// ], /// ); /// ``` - pub unsafe fn get_many_key_value_unchecked_mut( + pub unsafe fn get_disjoint_key_value_unchecked_mut( &mut self, ks: [&Q; N], ) -> [Option<(&'_ K, &'_ mut V)>; N] where Q: Hash + Equivalent + ?Sized, { - self.get_many_unchecked_mut_inner(ks) + self.get_disjoint_unchecked_mut_inner(ks) .map(|res| res.map(|(k, v)| (&*k, v))) } - fn get_many_mut_inner(&mut self, ks: [&Q; N]) -> [Option<&'_ mut (K, V)>; N] + /// Attempts to get mutable references to `N` values in the map at once, with immutable + /// references to the corresponding keys, without validating that the values are unique. + #[deprecated(note = "use `get_disjoint_key_value_unchecked_mut` instead")] + pub unsafe fn get_many_key_value_unchecked_mut( + &mut self, + ks: [&Q; N], + ) -> [Option<(&'_ K, &'_ mut V)>; N] + where + Q: Hash + Equivalent + ?Sized, + { + self.get_disjoint_key_value_unchecked_mut(ks) + } + + fn get_disjoint_mut_inner( + &mut self, + ks: [&Q; N], + ) -> [Option<&'_ mut (K, V)>; N] where Q: Hash + Equivalent + ?Sized, { let hashes = self.build_hashes_inner(ks); self.table - .get_many_mut(hashes, |i, (k, _)| ks[i].equivalent(k)) + .get_disjoint_mut(hashes, |i, (k, _)| ks[i].equivalent(k)) } - unsafe fn get_many_unchecked_mut_inner( + unsafe fn get_disjoint_unchecked_mut_inner( &mut self, ks: [&Q; N], ) -> [Option<&'_ mut (K, V)>; N] @@ -1745,7 +1797,7 @@ where { let hashes = self.build_hashes_inner(ks); self.table - .get_many_unchecked_mut(hashes, |i, (k, _)| ks[i].equivalent(k)) + .get_disjoint_unchecked_mut(hashes, |i, (k, _)| ks[i].equivalent(k)) } fn build_hashes_inner(&self, ks: [&Q; N]) -> [u64; N] @@ -6056,20 +6108,20 @@ mod test_map { } #[test] - fn test_get_many_mut() { + fn test_get_disjoint_mut() { let mut map = HashMap::new(); map.insert("foo".to_owned(), 0); map.insert("bar".to_owned(), 10); map.insert("baz".to_owned(), 20); map.insert("qux".to_owned(), 30); - let xs = map.get_many_mut(["foo", "qux"]); + let xs = map.get_disjoint_mut(["foo", "qux"]); assert_eq!(xs, [Some(&mut 0), Some(&mut 30)]); - let xs = map.get_many_mut(["foo", "dud"]); + let xs = map.get_disjoint_mut(["foo", "dud"]); assert_eq!(xs, [Some(&mut 0), None]); - let ys = map.get_many_key_value_mut(["bar", "baz"]); + let ys = map.get_disjoint_key_value_mut(["bar", "baz"]); assert_eq!( ys, [ @@ -6078,17 +6130,17 @@ mod test_map { ], ); - let ys = map.get_many_key_value_mut(["bar", "dip"]); + let ys = map.get_disjoint_key_value_mut(["bar", "dip"]); assert_eq!(ys, [Some((&"bar".to_string(), &mut 10)), None]); } #[test] #[should_panic = "duplicate keys found"] - fn test_get_many_mut_duplicate() { + fn test_get_disjoint_mut_duplicate() { let mut map = HashMap::new(); map.insert("foo".to_owned(), 0); - let _xs = map.get_many_mut(["foo", "foo"]); + let _xs = map.get_disjoint_mut(["foo", "foo"]); } #[test] diff --git a/src/raw/mod.rs b/src/raw/mod.rs index c0d82a1b5..6a8d37d82 100644 --- a/src/raw/mod.rs +++ b/src/raw/mod.rs @@ -1234,13 +1234,13 @@ impl RawTable { /// /// The `eq` argument should be a closure such that `eq(i, k)` returns true if `k` is equal to /// the `i`th key to be looked up. - pub fn get_many_mut( + pub fn get_disjoint_mut( &mut self, hashes: [u64; N], eq: impl FnMut(usize, &T) -> bool, ) -> [Option<&'_ mut T>; N] { unsafe { - let ptrs = self.get_many_mut_pointers(hashes, eq); + let ptrs = self.get_disjoint_mut_pointers(hashes, eq); for (i, cur) in ptrs.iter().enumerate() { if cur.is_some() && ptrs[..i].contains(cur) { @@ -1254,16 +1254,16 @@ impl RawTable { } } - pub unsafe fn get_many_unchecked_mut( + pub unsafe fn get_disjoint_unchecked_mut( &mut self, hashes: [u64; N], eq: impl FnMut(usize, &T) -> bool, ) -> [Option<&'_ mut T>; N] { - let ptrs = self.get_many_mut_pointers(hashes, eq); + let ptrs = self.get_disjoint_mut_pointers(hashes, eq); ptrs.map(|ptr| ptr.map(|mut ptr| ptr.as_mut())) } - unsafe fn get_many_mut_pointers( + unsafe fn get_disjoint_mut_pointers( &mut self, hashes: [u64; N], mut eq: impl FnMut(usize, &T) -> bool, diff --git a/src/table.rs b/src/table.rs index 2565f6f8b..dd9d9e3cf 100644 --- a/src/table.rs +++ b/src/table.rs @@ -994,7 +994,7 @@ where /// } /// /// let keys = ["Athenæum", "Library of Congress"]; - /// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0); + /// let got = libraries.get_disjoint_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0); /// assert_eq!( /// got, /// [Some(&mut ("Athenæum", 1807)), Some(&mut ("Library of Congress", 1800))], @@ -1002,7 +1002,7 @@ where /// /// // Missing keys result in None /// let keys = ["Athenæum", "New York Public Library"]; - /// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0); + /// let got = libraries.get_disjoint_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0); /// assert_eq!(got, [Some(&mut ("Athenæum", 1807)), None]); /// # } /// # fn main() { @@ -1029,7 +1029,7 @@ where /// /// // Duplicate keys result in a panic! /// let keys = ["Athenæum", "Athenæum"]; - /// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0); + /// let got = libraries.get_disjoint_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0); /// # } /// # fn main() { /// # #[cfg(feature = "nightly")] @@ -1038,12 +1038,22 @@ where /// # panic!(); /// # } /// ``` + pub fn get_disjoint_mut( + &mut self, + hashes: [u64; N], + eq: impl FnMut(usize, &T) -> bool, + ) -> [Option<&'_ mut T>; N] { + self.raw.get_disjoint_mut(hashes, eq) + } + + /// Attempts to get mutable references to `N` values in the map at once. + #[deprecated(note = "use `get_disjoint_mut` instead")] pub fn get_many_mut( &mut self, hashes: [u64; N], eq: impl FnMut(usize, &T) -> bool, ) -> [Option<&'_ mut T>; N] { - self.raw.get_many_mut(hashes, eq) + self.raw.get_disjoint_mut(hashes, eq) } /// Attempts to get mutable references to `N` values in the map at once, without validating that @@ -1055,7 +1065,7 @@ where /// Returns an array of length `N` with the results of each query. `None` will be returned if /// any of the keys are missing. /// - /// For a safe alternative see [`get_many_mut`](`HashTable::get_many_mut`). + /// For a safe alternative see [`get_disjoint_mut`](`HashTable::get_disjoint_mut`). /// /// # Safety /// @@ -1086,7 +1096,7 @@ where /// } /// /// let keys = ["Athenæum", "Library of Congress"]; - /// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0); + /// let got = libraries.get_disjoint_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0); /// assert_eq!( /// got, /// [Some(&mut ("Athenæum", 1807)), Some(&mut ("Library of Congress", 1800))], @@ -1094,7 +1104,7 @@ where /// /// // Missing keys result in None /// let keys = ["Athenæum", "New York Public Library"]; - /// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0); + /// let got = libraries.get_disjoint_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0); /// assert_eq!(got, [Some(&mut ("Athenæum", 1807)), None]); /// # } /// # fn main() { @@ -1102,12 +1112,23 @@ where /// # test() /// # } /// ``` + pub unsafe fn get_disjoint_unchecked_mut( + &mut self, + hashes: [u64; N], + eq: impl FnMut(usize, &T) -> bool, + ) -> [Option<&'_ mut T>; N] { + self.raw.get_disjoint_unchecked_mut(hashes, eq) + } + + /// Attempts to get mutable references to `N` values in the map at once, without validating that + /// the values are unique. + #[deprecated(note = "use `get_disjoint_unchecked_mut` instead")] pub unsafe fn get_many_unchecked_mut( &mut self, hashes: [u64; N], eq: impl FnMut(usize, &T) -> bool, ) -> [Option<&'_ mut T>; N] { - self.raw.get_many_unchecked_mut(hashes, eq) + self.raw.get_disjoint_unchecked_mut(hashes, eq) } /// Returns the total amount of memory allocated internally by the hash