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

Conversation

@passcod
Copy link
Contributor

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

This comment has been minimized.

Copy link
Collaborator

rust-highfive commented Sep 21, 2019

r? @dtolnay

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

@rust-highfive

This comment has been minimized.

Copy link
Collaborator

rust-highfive commented Sep 21, 2019

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

This comment has been minimized.

Copy link
Member

JohnCSimon commented Sep 28, 2019

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")]

This comment has been minimized.

Copy link
@dtolnay

dtolnay Sep 29, 2019

Member

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

@dtolnay

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

Copy link
Collaborator

rust-highfive commented Sep 30, 2019

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

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

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.

@passcod passcod force-pushed the passcod:map-entry-insert branch from df51ad0 to a45d7a6 Sep 30, 2019
@Amanieu

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

Copy link
Collaborator

rust-highfive commented Sep 30, 2019

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

This comment has been minimized.

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

This comment has been minimized.

Copy link
Contributor

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.

@passcod passcod force-pushed the passcod:map-entry-insert branch from a45d7a6 to 9ff7715 Sep 30, 2019
@rust-highfive

This comment has been minimized.

Copy link
Collaborator

rust-highfive commented Sep 30, 2019

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

This comment has been minimized.

Copy link
Member

dtolnay commented Sep 30, 2019

@passcod

This comment has been minimized.

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?

@lzutao

This comment has been minimized.

Copy link
Contributor

lzutao commented Oct 4, 2019

I think the build fail is the reason.

@passcod

This comment has been minimized.

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.
@passcod passcod force-pushed the passcod:map-entry-insert branch from 9ff7715 to 621bd66 Oct 5, 2019
@passcod passcod requested a review from dtolnay Oct 6, 2019
@mati865

This comment has been minimized.

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.

@Amanieu

This comment has been minimized.

Copy link
Contributor

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 passcod referenced this pull request Oct 8, 2019
1 of 2 tasks complete
@passcod passcod force-pushed the passcod:map-entry-insert branch from 621bd66 to bdcc21c Oct 8, 2019
@passcod

This comment has been minimized.

Copy link
Contributor Author

passcod commented Oct 8, 2019

@Amanieu all done

@Amanieu

This comment has been minimized.

Copy link
Contributor

Amanieu commented Oct 8, 2019

@bors r+

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Oct 8, 2019

📌 Commit bdcc21c has been approved by Amanieu

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Oct 9, 2019

⌛️ Testing commit bdcc21c with merge 54ff3e7...

bors added a commit that referenced this pull request Oct 9, 2019
Implement (HashMap) Entry::insert as per #60142

Implementation of `Entry::insert` as per @SimonSapin's comment on #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 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 Centril referenced this pull request Oct 9, 2019
@Centril

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link
Contributor

bors commented Oct 9, 2019

⌛️ Testing commit bdcc21c with merge eef1f5e...

bors added a commit that referenced this pull request Oct 9, 2019
Implement (HashMap) Entry::insert as per #60142

Implementation of `Entry::insert` as per @SimonSapin's comment on #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 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 Centril referenced this pull request Oct 9, 2019
@Centril

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

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
4 of 5 checks passed
4 of 5 checks passed
homu Testing commit bdcc21cbc4dabe73662634ffada8d0f353bc1ce9 with merge 275cf4bcacad3fbe5539ecd5840462793ae46eec...
Details
pr Build #20191008.56 succeeded
Details
pr (Linux mingw-check) Linux mingw-check succeeded
Details
pr (Linux x86_64-gnu-llvm-6.0) Linux x86_64-gnu-llvm-6.0 succeeded
Details
pr (LinuxTools) LinuxTools succeeded
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
You can’t perform that action at this time.