Fix double-drop in RawTable::clone_from
If an element from the destination table panics from its `Drop` impl
then elements from that table would end up being dropped twice, which is
unsound.
Bump version tested on CI to 1.58.1
This is needed because cross-rs increased its MSRV to 1.58.1.
One CI builder is kept at 1.56.1 without using cross-rs to guarantee
that compatibility is maintained.
This is needed because cross-rs increased its MSRV to 1.58.1.
One CI builder is kept at 1.56.1 without using cross-rs to guarantee
that compatibility is maintained.
Add an Entry API for HashSet
This adds `HashSet::entry` and `rustc_entry`, mimicking the API of `HashMap`. The "rustc" variants are without the `S` type parameter, just like the difference on maps. Set entries have fewer methods since there's no mutable value like in maps, but the basic insert/remove/replace functionality is there.
Resolves#274.
Improving documentation. Part 3.
Continuation of #328 and #331.
Also I made some changes in the previously added examples (made `compute_hash` generic and rename `compute_hash` to `make_hasher` in `insert_with_hasher example`)
Adding `Extend<&'a (K, V)> for HashMap<K, V, S, A>`
I think that it is strange that we can do something like this:
```rust
fn main() {
use hashbrown::HashMap;
let mut map = HashMap::new();
let some_vec: Vec<_> = vec![(1, 1), (2, 2), (3, 3), (4, 4)];
map.extend(some_vec.iter().map(|&(k, v)| (k, v)));
}
```
but cannot do something like this:
```rust
fn main() {
use hashbrown::HashMap;
let mut map = HashMap::new();
let some_vec: Vec<_> = vec![(1, 1), (2, 2), (3, 3), (4, 4)];
map.extend(some_vec.iter()); // Or map.extend(&some_vec);
}
```
In any case, it can work only if K and V are Copy, and also inside `Extend<(K, V)>` we use `HashMap::insert`, not `HashMap::insert_unique_unchecked`, so adding `Extend<&'a (K, V)>` should be Ok.
Editing `do_alloc` for reducing LLVM IR
1. I think this will speed up compilation, since one way or another everything will come down to this code (but I didn’t compare performance).
2. I don’t know if the compiler was able to optimize that old code, but it literally checked the same thing twice (due to `map` and `map_err` in a row, and roughly speaking it came down to:
```rust
pub fn do_alloc<A: Allocator>(alloc: &A, layout: Layout) -> Result<NonNull<u8>, ()> {
match match alloc.allocate(layout) {
Ok(ptr) => Ok(ptr.as_non_null_ptr()),
Err(e) => Err(e),
} {
Ok(ptr) => Ok(ptr),
Err(_) => Err(()),
}
}
```
And when the code is written explicitly, it is immediately clear that it looks strange. And why force the compiler to think beyond the need?
3. And finally, in my opinion, the readability of the code has not only not decreased, but even increased.
Current implementation works little slower than `set.iter().take(set.len())`.
See my comment [here](https://github.com/rust-lang/rust/pull/97215#issuecomment-1132871046).
So why not avoid extra integer which added by `Iterator::take` if we can add limiting logic into our iterator itself?
Also, removed end pointer check if we can limit iteration by counting items yielded.
Adding function for getting access to map `table: RawTable<(K, V), A>` field
I was a little interested in issues "API for removing by key hash and value" #330. The original question was about adding a fancy API, and of course it wasn't merged (#334).
However, it seems to me that this shows that it would be nice to just add the ability to access to map's fields. And let the user himself do what he pleases.
The user will still not be able to change the existing API. But at the same time, he will have the opportunity to add small extensions. Otherwise, when using `RawTable`, he will have to not only add one or two functions, but generally recreate all the `HashMap`’s APIs, which can be difficult.