Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement (HashMap) Entry::insert as per #60142 #64656

Merged
merged 1 commit into from
Oct 9, 2019
Merged

Implement (HashMap) Entry::insert as per #60142 #64656

merged 1 commit into from
Oct 9, 2019

Conversation

passcod
Copy link
Contributor

@passcod passcod commented Sep 21, 2019

Implementation of Entry::insert as per @SimonSapin's comment on #60142. This requires a patch to hashbrown:

diff --git a/src/rustc_entry.rs b/src/rustc_entry.rs
index fefa5c3..7de8300 100644
--- a/src/rustc_entry.rs
+++ b/src/rustc_entry.rs
@@ -546,6 +546,32 @@ impl<'a, K, V> RustcVacantEntry<'a, K, V> {
         let bucket = self.table.insert_no_grow(self.hash, (self.key, value));
         unsafe { &mut bucket.as_mut().1 }
     }
+
+    /// Sets the value of the entry with the RustcVacantEntry's key,
+    /// and returns a RustcOccupiedEntry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use hashbrown::HashMap;
+    /// use hashbrown::hash_map::RustcEntry;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    ///
+    /// if let RustcEntry::Vacant(v) = map.rustc_entry("poneyland") {
+    ///     let o = v.insert_and_return(37);
+    ///     assert_eq!(o.get(), &37);
+    /// }
+    /// ```
+     #[inline]
+    pub fn insert_and_return(self, value: V) -> RustcOccupiedEntry<'a, K, V> {
+        let bucket = self.table.insert_no_grow(self.hash, (self.key, value));
+        RustcOccupiedEntry {
+            key: None,
+            elem: bucket,
+            table: self.table
+        }
+    }
 }
 
 impl<K, V> IterMut<'_, K, V> {

This is also only an implementation for HashMap. I tried implementing for BTreeMap, but I don't really understand BTreeMap's internals and require more guidance on implementing the equivalent VacantEntry::insert_and_return such that it returns an OccupiedEntry. Notably, following the original PR's modifications I end up needing a Handle<NodeRef<marker::Mut<'_>, _, _, marker::LeafOrInternal>, _> while I only have a Handle<NodeRef<marker::Mut<'_>, _, _, marker::Internal>, _> and don't know how to proceed.

(To be clear, I'm not asking for guidance right now; I'd be happy getting only the HashMap implementation — the subject of this PR — reviewed and ready, and leave the BTreeMap implementation for a latter PR.)

@rust-highfive
Copy link
Collaborator

r? @dtolnay

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 21, 2019
@rust-highfive
Copy link
Collaborator

The job mingw-check of your PR failed (pretty log, raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
2019-09-21T11:31:54.2466283Z ##[command]git remote add origin https://github.com/rust-lang/rust
2019-09-21T11:31:54.2664221Z ##[command]git config gc.auto 0
2019-09-21T11:31:54.2736007Z ##[command]git config --get-all http.https://github.com/rust-lang/rust.extraheader
2019-09-21T11:31:54.2785343Z ##[command]git config --get-all http.proxy
2019-09-21T11:31:54.2925697Z ##[command]git -c http.extraheader="AUTHORIZATION: basic ***" fetch --force --tags --prune --progress --no-recurse-submodules --depth=2 origin +refs/heads/*:refs/remotes/origin/* +refs/pull/64656/merge:refs/remotes/pull/64656/merge
---
2019-09-21T11:38:13.5746691Z     Checking backtrace v0.3.37
2019-09-21T11:38:15.3711429Z     Checking rustc-std-workspace-alloc v1.99.0 (/checkout/src/tools/rustc-std-workspace-alloc)
2019-09-21T11:38:15.3736375Z     Checking panic_unwind v0.0.0 (/checkout/src/libpanic_unwind)
2019-09-21T11:38:15.5245754Z     Checking hashbrown v0.5.0
2019-09-21T11:38:17.6918371Z error[E0599]: no method named `insert_and_return` found for type `hashbrown::rustc_entry::RustcVacantEntry<'a, K, V>` in the current scope
2019-09-21T11:38:17.6919879Z     --> src/libstd/collections/hash/map.rs:2402:30
2019-09-21T11:38:17.6920557Z      |
2019-09-21T11:38:17.6921094Z 2402 |         let base = self.base.insert_and_return(value);
2019-09-21T11:38:17.6921878Z 
2019-09-21T11:38:18.9418845Z error: aborting due to previous error
2019-09-21T11:38:18.9420065Z 
2019-09-21T11:38:18.9420704Z For more information about this error, try `rustc --explain E0599`.
---
2019-09-21T11:38:18.9837256Z == clock drift check ==
2019-09-21T11:38:18.9854219Z   local time: Sat Sep 21 11:38:18 UTC 2019
2019-09-21T11:38:19.0710362Z   network time: Sat, 21 Sep 2019 11:38:19 GMT
2019-09-21T11:38:19.0713701Z == end clock drift check ==
2019-09-21T11:38:24.8051745Z ##[error]Bash exited with code '1'.
2019-09-21T11:38:24.8084124Z ##[section]Starting: Checkout
2019-09-21T11:38:24.8086451Z ==============================================================================
2019-09-21T11:38:24.8086507Z Task         : Get sources
2019-09-21T11:38:24.8086572Z Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@JohnCSimon
Copy link
Member

Ping from triage:

@dtolnay Can you please review this PR?
CC: @passcod
Thank you!

/// assert_eq!(map["poneyland"], 37);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line should be removed. I don't think we put stability attributes on private signatures.

@dtolnay
Copy link
Member

dtolnay commented Sep 29, 2019

The signature of Entry::insert looks good to me. Are there any next steps on the hashbrown side before we can land this?

@passcod
Copy link
Contributor Author

passcod commented Sep 29, 2019

Thanks! I'll do the changes here and go open a PR on the hashbrown side with the changeset.

@rust-highfive
Copy link
Collaborator

The job mingw-check of your PR failed (pretty log, raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
2019-09-30T08:49:34.7490971Z ##[command]git remote add origin https://github.com/rust-lang/rust
2019-09-30T08:49:34.7727710Z ##[command]git config gc.auto 0
2019-09-30T08:49:34.7784813Z ##[command]git config --get-all http.https://github.com/rust-lang/rust.extraheader
2019-09-30T08:49:34.7835297Z ##[command]git config --get-all http.proxy
2019-09-30T08:49:34.7975845Z ##[command]git -c http.extraheader="AUTHORIZATION: basic ***" fetch --force --tags --prune --progress --no-recurse-submodules --depth=2 origin +refs/heads/*:refs/remotes/origin/* +refs/pull/64656/merge:refs/remotes/pull/64656/merge
---
2019-09-30T08:55:51.6580367Z     Checking backtrace v0.3.37
2019-09-30T08:55:53.4206638Z     Checking rustc-std-workspace-alloc v1.99.0 (/checkout/src/tools/rustc-std-workspace-alloc)
2019-09-30T08:55:53.4986989Z     Checking panic_unwind v0.0.0 (/checkout/src/libpanic_unwind)
2019-09-30T08:55:53.5330549Z     Checking hashbrown v0.5.0
2019-09-30T08:55:56.8664986Z error[E0599]: no method named `insert_and_return` found for type `hashbrown::rustc_entry::RustcVacantEntry<'a, K, V>` in the current scope
2019-09-30T08:55:56.8666032Z     --> src/libstd/collections/hash/map.rs:2400:30
2019-09-30T08:55:56.8666406Z      |
2019-09-30T08:55:56.8666819Z 2400 |         let base = self.base.insert_and_return(value);
2019-09-30T08:55:56.8667445Z      |                              ^^^^^^^^^^^^^^^^^ method not found in `hashbrown::rustc_entry::RustcVacantEntry<'a, K, V>`
2019-09-30T08:55:58.1192889Z error: aborting due to previous error
2019-09-30T08:55:58.1193047Z 
2019-09-30T08:55:58.1193339Z For more information about this error, try `rustc --explain E0599`.
2019-09-30T08:55:58.1538410Z error: could not compile `std`.
---
2019-09-30T08:55:58.1620872Z == clock drift check ==
2019-09-30T08:55:58.9903892Z   local time: Mon Sep 30 08:55:58 UTC 2019
2019-09-30T08:55:59.1735870Z   network time: Mon, 30 Sep 2019 08:55:59 GMT
2019-09-30T08:55:59.1736605Z == end clock drift check ==
2019-09-30T08:56:06.0860845Z ##[error]Bash exited with code '1'.
2019-09-30T08:56:06.0897580Z ##[section]Starting: Checkout
2019-09-30T08:56:06.0899825Z ==============================================================================
2019-09-30T08:56:06.0899872Z Task         : Get sources
2019-09-30T08:56:06.0899911Z Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@Amanieu
Copy link
Member

Amanieu commented Sep 30, 2019

I'm not too happy with the naming here. I feel that calling both methods (in Entry and VacantEntry) insert_entry would be clearer. In particular insert_and_return is a terrible name since it doesn't give any information about what is returned.

@passcod
Copy link
Contributor Author

passcod commented Sep 30, 2019

Weakly disagree on the public, as what's being inserted is a value, like or_insert, not an Entry. But the private internals I can certainly change.

@Amanieu
Copy link
Member

Amanieu commented Sep 30, 2019

Oh I didn't notice that insert_and_return was private. In that case I retract my comment about the public API, it's fine as it is.

Regarding the implementation, I think hashbrown's RustcEntry (and Entry) should have an insert method which libstd should use directly. The insert_entry method should be private to hashbrown.

@rust-highfive
Copy link
Collaborator

The job mingw-check of your PR failed (pretty log, raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
2019-09-30T09:35:54.4767292Z ##[command]git remote add origin https://github.com/rust-lang/rust
2019-09-30T09:35:54.4783140Z ##[command]git config gc.auto 0
2019-09-30T09:35:54.4784829Z ##[command]git config --get-all http.https://github.com/rust-lang/rust.extraheader
2019-09-30T09:35:54.4788585Z ##[command]git config --get-all http.proxy
2019-09-30T09:35:54.4793140Z ##[command]git -c http.extraheader="AUTHORIZATION: basic ***" fetch --force --tags --prune --progress --no-recurse-submodules --depth=2 origin +refs/heads/*:refs/remotes/origin/* +refs/pull/64656/merge:refs/remotes/pull/64656/merge
---
2019-09-30T09:42:02.2843202Z     Checking backtrace v0.3.37
2019-09-30T09:42:04.0872648Z     Checking rustc-std-workspace-alloc v1.99.0 (/checkout/src/tools/rustc-std-workspace-alloc)
2019-09-30T09:42:04.1645854Z     Checking panic_unwind v0.0.0 (/checkout/src/libpanic_unwind)
2019-09-30T09:42:04.1986093Z     Checking hashbrown v0.5.0
2019-09-30T09:42:06.4237412Z error[E0599]: no method named `insert_entry` found for type `hashbrown::rustc_entry::RustcVacantEntry<'a, K, V>` in the current scope
2019-09-30T09:42:06.4238821Z     --> src/libstd/collections/hash/map.rs:2398:30
2019-09-30T09:42:06.4239396Z      |
2019-09-30T09:42:06.4240180Z 2398 |         let base = self.base.insert_entry(value);
2019-09-30T09:42:06.4240607Z      |                              ^^^^^^^^^^^^ method not found in `hashbrown::rustc_entry::RustcVacantEntry<'a, K, V>`
2019-09-30T09:42:07.5811473Z error: aborting due to previous error
2019-09-30T09:42:07.5811571Z 
2019-09-30T09:42:07.5811835Z For more information about this error, try `rustc --explain E0599`.
2019-09-30T09:42:07.6147053Z error: could not compile `std`.
---
2019-09-30T09:42:07.6224768Z == clock drift check ==
2019-09-30T09:42:07.6242888Z   local time: Mon Sep 30 09:42:07 UTC 2019
2019-09-30T09:42:07.7752571Z   network time: Mon, 30 Sep 2019 09:42:07 GMT
2019-09-30T09:42:07.7757194Z == end clock drift check ==
2019-09-30T09:42:09.6879512Z ##[error]Bash exited with code '1'.
2019-09-30T09:42:09.6914124Z ##[section]Starting: Checkout
2019-09-30T09:42:09.6915554Z ==============================================================================
2019-09-30T09:42:09.6915599Z Task         : Get sources
2019-09-30T09:42:09.6915635Z Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@passcod
Copy link
Contributor Author

passcod commented Sep 30, 2019

Is that possible? In libstd Entry is not a wrapper for hashbrown's RustcEntry, but rather directly the Vacant/Occupied enum, and then reimplements the inherent methods instead of delegating. insert_entry needs to be public on RustcVacantEntry so it can be used in the libstd.

That does feel awkward, though, to be sure.

@Amanieu
Copy link
Member

Amanieu commented Sep 30, 2019

Ah good point, I guess that's not possible then. In that case I'm happy to accept it as it is.

@rust-highfive
Copy link
Collaborator

The job mingw-check of your PR failed (pretty log, raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
2019-09-30T12:51:10.7561090Z ##[command]git remote add origin https://github.com/rust-lang/rust
2019-09-30T12:51:10.7742367Z ##[command]git config gc.auto 0
2019-09-30T12:51:10.7809025Z ##[command]git config --get-all http.https://github.com/rust-lang/rust.extraheader
2019-09-30T12:51:10.7864617Z ##[command]git config --get-all http.proxy
2019-09-30T12:51:10.8006210Z ##[command]git -c http.extraheader="AUTHORIZATION: basic ***" fetch --force --tags --prune --progress --no-recurse-submodules --depth=2 origin +refs/heads/*:refs/remotes/origin/* +refs/pull/64656/merge:refs/remotes/pull/64656/merge
---
2019-09-30T12:57:32.2260874Z     Checking backtrace v0.3.37
2019-09-30T12:57:33.8398790Z     Checking rustc-std-workspace-alloc v1.99.0 (/checkout/src/tools/rustc-std-workspace-alloc)
2019-09-30T12:57:33.8801601Z     Checking panic_unwind v0.0.0 (/checkout/src/libpanic_unwind)
2019-09-30T12:57:34.0141297Z     Checking hashbrown v0.5.0
2019-09-30T12:57:36.4783350Z error[E0599]: no method named `insert_entry` found for type `hashbrown::rustc_entry::RustcVacantEntry<'a, K, V>` in the current scope
2019-09-30T12:57:36.4785008Z     --> src/libstd/collections/hash/map.rs:2399:30
2019-09-30T12:57:36.4785562Z      |
2019-09-30T12:57:36.4786072Z 2399 |         let base = self.base.insert_entry(value);
2019-09-30T12:57:36.4786645Z      |                              ^^^^^^^^^^^^ method not found in `hashbrown::rustc_entry::RustcVacantEntry<'a, K, V>`
2019-09-30T12:57:37.8707566Z error: aborting due to previous error
2019-09-30T12:57:37.8708183Z 
2019-09-30T12:57:37.8708871Z For more information about this error, try `rustc --explain E0599`.
2019-09-30T12:57:37.9078062Z error: could not compile `std`.
---
2019-09-30T12:57:37.9223137Z == clock drift check ==
2019-09-30T12:57:37.9235497Z   local time: Mon Sep 30 12:57:37 UTC 2019
2019-09-30T12:57:38.2604990Z   network time: Mon, 30 Sep 2019 12:57:38 GMT
2019-09-30T12:57:38.2605889Z == end clock drift check ==
2019-09-30T12:57:41.7513219Z ##[error]Bash exited with code '1'.
2019-09-30T12:57:41.7553456Z ##[section]Starting: Checkout
2019-09-30T12:57:41.7556090Z ==============================================================================
2019-09-30T12:57:41.7556152Z Task         : Get sources
2019-09-30T12:57:41.7556220Z Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@dtolnay
Copy link
Member

dtolnay commented Sep 30, 2019

r? @Amanieu

@rust-highfive rust-highfive assigned Amanieu and unassigned dtolnay Sep 30, 2019
@Dylan-DPC-zz Dylan-DPC-zz added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 1, 2019
@passcod
Copy link
Contributor Author

passcod commented Oct 4, 2019

Er, sorry, can I get clarification on what action is required from me (re S-waiting-on-author tag), or is this a mistag?

@tesuji
Copy link
Contributor

tesuji commented Oct 4, 2019

I think the build fail is the reason.

@passcod
Copy link
Contributor Author

passcod commented Oct 4, 2019

Yeah, but that's because the patch in hashbrown needs landing first, and I'm also not seeing action I have to take over there (the build failing there "seems unrelated" as per maintainer). I'm fine if that's ambiguous to tag, just was wondering if I'd missed something.

Edit: PR on hashbrown is waiting on another PR to land, so this will probably move soonish.

Okay, this is now waiting on hashbrown release.

bors added a commit to rust-lang/hashbrown that referenced this pull request Oct 4, 2019
Add RustcVacantEntry::insert_entry for rust-lang/rust#64656

See rust-lang/rust#64656.

~~This was based on v0.5.0 as that's what rustc uses; I can rebase onto master, but I'm not sure whether rustc wants v0.6.0 or if v0.6.0 is rustc-ready.~~

For context, this ultimately provides an API with this shape:

```rust
impl Entry<'a, K, V> {
    fn insert(self, value: V) -> OccupiedEntry<'a, K, V> {…}
}
```

to be used when one wants to insert a value without consuming the Entry, e.g. because one wants to keep a reference to the key around. There's more at the original (defunct) PR: rust-lang/rust#60142.
@Dylan-DPC-zz Dylan-DPC-zz added S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 4, 2019
@Amanieu
Copy link
Member

Amanieu commented Oct 4, 2019

I just published hashbrown 0.6.1 with your patch. Now you need to update hashbrown in Cargo.lock in this PR.

@passcod passcod requested a review from dtolnay October 6, 2019 12:37
@Dylan-DPC-zz Dylan-DPC-zz added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Oct 8, 2019
@mati865
Copy link
Contributor

mati865 commented Oct 8, 2019

@rustbot modify labels: -S-waiting-on-author +S-waiting-on-review

Hashbrown update was amended to previous commit.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 8, 2019
@Amanieu
Copy link
Member

Amanieu commented Oct 8, 2019

Can you create a tracking issue and point to it in the unstable attribute? After that it should be good to merge.

@passcod
Copy link
Contributor Author

passcod commented Oct 8, 2019

@Amanieu all done

@Amanieu
Copy link
Member

Amanieu commented Oct 8, 2019

@bors r+

@bors
Copy link
Contributor

bors commented Oct 8, 2019

📌 Commit bdcc21c has been approved by Amanieu

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 8, 2019
@bors
Copy link
Contributor

bors commented Oct 9, 2019

⌛ Testing commit bdcc21c with merge 54ff3e75f4ac76ce517a58d221d55cda6096b47d...

Centril added a commit to Centril/rust that referenced this pull request Oct 9, 2019
Implement (HashMap) Entry::insert as per rust-lang#60142

Implementation of `Entry::insert` as per @SimonSapin's comment on rust-lang#60142. This requires a patch to hashbrown:

```diff
diff --git a/src/rustc_entry.rs b/src/rustc_entry.rs
index fefa5c3..7de8300 100644
--- a/src/rustc_entry.rs
+++ b/src/rustc_entry.rs
@@ -546,6 +546,32 @@ impl<'a, K, V> RustcVacantEntry<'a, K, V> {
         let bucket = self.table.insert_no_grow(self.hash, (self.key, value));
         unsafe { &mut bucket.as_mut().1 }
     }
+
+    /// Sets the value of the entry with the RustcVacantEntry's key,
+    /// and returns a RustcOccupiedEntry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use hashbrown::HashMap;
+    /// use hashbrown::hash_map::RustcEntry;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    ///
+    /// if let RustcEntry::Vacant(v) = map.rustc_entry("poneyland") {
+    ///     let o = v.insert_and_return(37);
+    ///     assert_eq!(o.get(), &37);
+    /// }
+    /// ```
+     #[inline]
+    pub fn insert_and_return(self, value: V) -> RustcOccupiedEntry<'a, K, V> {
+        let bucket = self.table.insert_no_grow(self.hash, (self.key, value));
+        RustcOccupiedEntry {
+            key: None,
+            elem: bucket,
+            table: self.table
+        }
+    }
 }

 impl<K, V> IterMut<'_, K, V> {
```

This is also only an implementation for HashMap. I tried implementing for BTreeMap, but I don't really understand BTreeMap's internals and require more guidance on implementing the equivalent `VacantEntry::insert_and_return` such that it returns an `OccupiedEntry`. Notably, following the original PR's modifications I end up needing a `Handle<NodeRef<marker::Mut<'_>, _, _, marker::LeafOrInternal>, _>` while I only have a `Handle<NodeRef<marker::Mut<'_>, _, _, marker::Internal>, _>` and don't know how to proceed.

(To be clear, I'm not asking for guidance right now; I'd be happy getting only the HashMap implementation — the subject of this PR — reviewed and ready, and leave the BTreeMap implementation for a latter PR.)
@Centril
Copy link
Contributor

Centril commented Oct 9, 2019

@bors retry rolled up.

bors added a commit that referenced this pull request Oct 9, 2019
Rollup of 6 pull requests

Successful merges:

 - #64656 (Implement (HashMap) Entry::insert as per #60142)
 - #64986 (Function pointers as const generic arguments)
 - #65037 (`#[track_caller]` feature gate (RFC 2091 1/N))
 - #65166 (Suggest to add `move` keyword for generator capture)
 - #65175 (add more info in debug traces for gcu merging)
 - #65220 (Update LLVM for Emscripten exception handling support)

Failed merges:

r? @ghost
@bors
Copy link
Contributor

bors commented Oct 9, 2019

⌛ Testing commit bdcc21c with merge eef1f5eeb8d8bb8b57919a58795d2f2ad1bcf27c...

Centril added a commit to Centril/rust that referenced this pull request Oct 9, 2019
Implement (HashMap) Entry::insert as per rust-lang#60142

Implementation of `Entry::insert` as per @SimonSapin's comment on rust-lang#60142. This requires a patch to hashbrown:

```diff
diff --git a/src/rustc_entry.rs b/src/rustc_entry.rs
index fefa5c3..7de8300 100644
--- a/src/rustc_entry.rs
+++ b/src/rustc_entry.rs
@@ -546,6 +546,32 @@ impl<'a, K, V> RustcVacantEntry<'a, K, V> {
         let bucket = self.table.insert_no_grow(self.hash, (self.key, value));
         unsafe { &mut bucket.as_mut().1 }
     }
+
+    /// Sets the value of the entry with the RustcVacantEntry's key,
+    /// and returns a RustcOccupiedEntry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use hashbrown::HashMap;
+    /// use hashbrown::hash_map::RustcEntry;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    ///
+    /// if let RustcEntry::Vacant(v) = map.rustc_entry("poneyland") {
+    ///     let o = v.insert_and_return(37);
+    ///     assert_eq!(o.get(), &37);
+    /// }
+    /// ```
+     #[inline]
+    pub fn insert_and_return(self, value: V) -> RustcOccupiedEntry<'a, K, V> {
+        let bucket = self.table.insert_no_grow(self.hash, (self.key, value));
+        RustcOccupiedEntry {
+            key: None,
+            elem: bucket,
+            table: self.table
+        }
+    }
 }

 impl<K, V> IterMut<'_, K, V> {
```

This is also only an implementation for HashMap. I tried implementing for BTreeMap, but I don't really understand BTreeMap's internals and require more guidance on implementing the equivalent `VacantEntry::insert_and_return` such that it returns an `OccupiedEntry`. Notably, following the original PR's modifications I end up needing a `Handle<NodeRef<marker::Mut<'_>, _, _, marker::LeafOrInternal>, _>` while I only have a `Handle<NodeRef<marker::Mut<'_>, _, _, marker::Internal>, _>` and don't know how to proceed.

(To be clear, I'm not asking for guidance right now; I'd be happy getting only the HashMap implementation — the subject of this PR — reviewed and ready, and leave the BTreeMap implementation for a latter PR.)
@Centril
Copy link
Contributor

Centril commented Oct 9, 2019

@bors retry rolled up.

bors added a commit that referenced this pull request Oct 9, 2019
Rollup of 4 pull requests

Successful merges:

 - #64656 (Implement (HashMap) Entry::insert as per #60142)
 - #65037 (`#[track_caller]` feature gate (RFC 2091 1/N))
 - #65166 (Suggest to add `move` keyword for generator capture)
 - #65175 (add more info in debug traces for gcu merging)

Failed merges:

r? @ghost
@bors
Copy link
Contributor

bors commented Oct 9, 2019

⌛ Testing commit bdcc21c with merge 275cf4b...

@bors bors merged commit bdcc21c into rust-lang:master Oct 9, 2019
@passcod passcod deleted the map-entry-insert branch November 16, 2019 05:26
@passcod passcod mentioned this pull request Oct 27, 2021
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Dec 21, 2021
Stabilise entry_insert

This stabilises `HashMap:Entry::insert_entry` etc. Tracking issue rust-lang#65225. It will need an FCP.

This was implemented in rust-lang#64656 two years ago.

This PR includes the rename and change discussed in rust-lang#65225 (comment), happy to split if needed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet