@@ -2,6 +2,7 @@ use crate::raw::{
22 Allocator , Bucket , Global , RawDrain , RawExtractIf , RawIntoIter , RawIter , RawTable ,
33} ;
44use crate :: { DefaultHashBuilder , Equivalent , TryReserveError } ;
5+ use :: alloc:: borrow:: ToOwned ;
56use core:: borrow:: Borrow ;
67use core:: fmt:: { self , Debug } ;
78use core:: hash:: { BuildHasher , Hash } ;
@@ -3963,6 +3964,42 @@ impl<'a, K, V, S, A: Allocator> OccupiedEntry<'a, K, V, S, A> {
39633964 unsafe { & mut self . elem . as_mut ( ) . 1 }
39643965 }
39653966
3967+ /// Converts the `OccupiedEntry` into a reference to the key and a
3968+ /// mutable reference to the value in the entry with a lifetime bound to the
3969+ /// map itself.
3970+ ///
3971+ /// If you need multiple references to the `OccupiedEntry`, see [`key`] and
3972+ /// [`get_mut`].
3973+ ///
3974+ /// [`key`]: Self::key
3975+ /// [`get_mut`]: Self::get_mut
3976+ ///
3977+ /// # Examples
3978+ ///
3979+ /// ```
3980+ /// use hashbrown::hash_map::{Entry, HashMap};
3981+ ///
3982+ /// let mut map: HashMap<&str, u32> = HashMap::new();
3983+ /// map.entry("poneyland").or_insert(12);
3984+ ///
3985+ /// assert_eq!(map["poneyland"], 12);
3986+ ///
3987+ /// let key_val: (&&str, &mut u32);
3988+ /// match map.entry("poneyland") {
3989+ /// Entry::Occupied(entry) => key_val = entry.into_entry(),
3990+ /// Entry::Vacant(_) => panic!(),
3991+ /// }
3992+ /// *key_val.1 += 10;
3993+ ///
3994+ /// assert_eq!(key_val, (&"poneyland", &mut 22));
3995+ /// assert_eq!(map["poneyland"], 22);
3996+ /// ```
3997+ #[ cfg_attr( feature = "inline-more" , inline) ]
3998+ pub fn into_entry ( self ) -> ( & ' a K , & ' a mut V ) {
3999+ let ( key, val) = unsafe { self . elem . as_mut ( ) } ;
4000+ ( key, val)
4001+ }
4002+
39664003 /// Sets the value of the entry, and returns the entry's old value.
39674004 ///
39684005 /// # Examples
@@ -4212,7 +4249,7 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> EntryRef<'a, 'b, K, Q, V, S, A> {
42124249 pub fn insert ( self , value : V ) -> OccupiedEntry < ' a , K , V , S , A >
42134250 where
42144251 K : Hash ,
4215- & ' b Q : Into < K > ,
4252+ Q : ToOwned < Owned = K > ,
42164253 S : BuildHasher ,
42174254 {
42184255 match self {
@@ -4246,7 +4283,7 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> EntryRef<'a, 'b, K, Q, V, S, A> {
42464283 pub fn or_insert ( self , default : V ) -> & ' a mut V
42474284 where
42484285 K : Hash ,
4249- & ' b Q : Into < K > ,
4286+ Q : ToOwned < Owned = K > ,
42504287 S : BuildHasher ,
42514288 {
42524289 match self {
@@ -4277,7 +4314,7 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> EntryRef<'a, 'b, K, Q, V, S, A> {
42774314 pub fn or_insert_with < F : FnOnce ( ) -> V > ( self , default : F ) -> & ' a mut V
42784315 where
42794316 K : Hash ,
4280- & ' b Q : Into < K > ,
4317+ Q : ToOwned < Owned = K > ,
42814318 S : BuildHasher ,
42824319 {
42834320 match self {
@@ -4309,7 +4346,7 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> EntryRef<'a, 'b, K, Q, V, S, A> {
43094346 pub fn or_insert_with_key < F : FnOnce ( & Q ) -> V > ( self , default : F ) -> & ' a mut V
43104347 where
43114348 K : Hash + Borrow < Q > ,
4312- & ' b Q : Into < K > ,
4349+ Q : ToOwned < Owned = K > ,
43134350 S : BuildHasher ,
43144351 {
43154352 match self {
@@ -4405,7 +4442,7 @@ impl<'a, 'b, K, Q: ?Sized, V: Default, S, A: Allocator> EntryRef<'a, 'b, K, Q, V
44054442 pub fn or_default ( self ) -> & ' a mut V
44064443 where
44074444 K : Hash ,
4408- & ' b Q : Into < K > ,
4445+ Q : ToOwned < Owned = K > ,
44094446 S : BuildHasher ,
44104447 {
44114448 match self {
@@ -4438,7 +4475,8 @@ impl<'a, 'b, K, Q: ?Sized, V: Default, S, A: Allocator> EntryRef<'a, 'b, K, Q, V
44384475 #[ cfg_attr( feature = "inline-more" , inline) ]
44394476 pub fn or_default_entry ( self ) -> OccupiedEntry < ' a , K , V , S , A >
44404477 where
4441- K : Hash + From < & ' b Q > ,
4478+ K : Hash ,
4479+ Q : ToOwned < Owned = K > ,
44424480 S : BuildHasher ,
44434481 {
44444482 match self {
@@ -4487,13 +4525,13 @@ impl<'map, 'key, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'map, 'key, K,
44874525 pub fn insert ( self , value : V ) -> & ' map mut V
44884526 where
44894527 K : Hash ,
4490- & ' key Q : Into < K > ,
4528+ Q : ToOwned < Owned = K > ,
44914529 S : BuildHasher ,
44924530 {
44934531 let table = & mut self . table . table ;
44944532 let entry = table. insert_entry (
44954533 self . hash ,
4496- ( self . key . into ( ) , value) ,
4534+ ( self . key . to_owned ( ) , value) ,
44974535 make_hasher :: < _ , V , S > ( & self . table . hash_builder ) ,
44984536 ) ;
44994537 & mut entry. 1
@@ -4535,17 +4573,7 @@ impl<'map, 'key, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'map, 'key, K,
45354573 Q : Equivalent < K > ,
45364574 S : BuildHasher ,
45374575 {
4538- let table = & mut self . table . table ;
4539- assert ! (
4540- ( self . key) . equivalent( & key) ,
4541- "key used for Entry creation is not equivalent to the one used for insertion"
4542- ) ;
4543- let entry = table. insert_entry (
4544- self . hash ,
4545- ( key, value) ,
4546- make_hasher :: < _ , V , S > ( & self . table . hash_builder ) ,
4547- ) ;
4548- & mut entry. 1
4576+ self . insert_entry_with_key ( key, value) . into_mut ( )
45494577 }
45504578
45514579 /// Sets the value of the entry with the [`VacantEntryRef`]'s key,
@@ -4568,12 +4596,63 @@ impl<'map, 'key, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'map, 'key, K,
45684596 pub fn insert_entry ( self , value : V ) -> OccupiedEntry < ' map , K , V , S , A >
45694597 where
45704598 K : Hash ,
4571- & ' key Q : Into < K > ,
4599+ Q : ToOwned < Owned = K > ,
4600+ S : BuildHasher ,
4601+ {
4602+ let elem = self . table . table . insert (
4603+ self . hash ,
4604+ ( self . key . to_owned ( ) , value) ,
4605+ make_hasher :: < _ , V , S > ( & self . table . hash_builder ) ,
4606+ ) ;
4607+ OccupiedEntry {
4608+ hash : self . hash ,
4609+ elem,
4610+ table : self . table ,
4611+ }
4612+ }
4613+
4614+ /// Sets the key and value of the entry and returns an [`OccupiedEntry`].
4615+ ///
4616+ /// Unlike [`VacantEntryRef::insert_entry`], this method allows the key to
4617+ /// be explicitly specified, which is useful for key types that don't
4618+ /// implement `K: From<&Q>`.
4619+ ///
4620+ /// # Panics
4621+ ///
4622+ /// This method panics if `key` is not equivalent to the key used to create
4623+ /// the `VacantEntryRef`.
4624+ ///
4625+ /// # Example
4626+ ///
4627+ /// ```
4628+ /// use hashbrown::hash_map::EntryRef;
4629+ /// use hashbrown::HashMap;
4630+ ///
4631+ /// let mut map = HashMap::<(String, String), char>::new();
4632+ /// let k = ("c".to_string(), "C".to_string());
4633+ /// let r = match map.entry_ref(&k) {
4634+ /// // Insert cannot be used here because tuples do not implement From.
4635+ /// // However this works because we can manually clone instead.
4636+ /// EntryRef::Vacant(r) => r.insert_entry_with_key(k.clone(), 'c'),
4637+ /// // In this branch we avoid the clone.
4638+ /// EntryRef::Occupied(r) => r,
4639+ /// };
4640+ /// assert_eq!(r.get(), &'c');
4641+ /// ```
4642+ #[ cfg_attr( feature = "inline-more" , inline) ]
4643+ pub fn insert_entry_with_key ( self , key : K , value : V ) -> OccupiedEntry < ' map , K , V , S , A >
4644+ where
4645+ K : Hash ,
4646+ Q : Equivalent < K > ,
45724647 S : BuildHasher ,
45734648 {
4649+ assert ! (
4650+ ( self . key) . equivalent( & key) ,
4651+ "key used for Entry creation is not equivalent to the one used for insertion"
4652+ ) ;
45744653 let elem = self . table . table . insert (
45754654 self . hash ,
4576- ( self . key . into ( ) , value) ,
4655+ ( key, value) ,
45774656 make_hasher :: < _ , V , S > ( & self . table . hash_builder ) ,
45784657 ) ;
45794658 OccupiedEntry {
0 commit comments