Skip to content

Commit 61b2d9b

Browse files
capickettfacebook-github-bot
authored andcommitted
Migrate off of RawTable APIs
Summary: The `RawTable` APIs are removed in latest `hashbrown` upgrade (coming in D68793000). rust-lang/hashbrown#546 The PR notes that users should migrate to the `HashTable` APIs instead. - `HashTable`: https://docs.rs/hashbrown/latest/hashbrown/struct.HashTable.html - `RawTable`: https://docs.rs/hashbrown/0.14.5/hashbrown/raw/struct.RawTable.html Reviewed By: dtolnay Differential Revision: D69195912 fbshipit-source-id: b5c4d0cc33a977d9ceb247ffedcf49d7be0b01ec
1 parent 6607d28 commit 61b2d9b

File tree

4 files changed

+49
-111
lines changed

4 files changed

+49
-111
lines changed

allocative/allocative/src/impls/hashbrown.rs

-34
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
use std::mem;
1313

14-
use hashbrown::raw::RawTable;
1514
use hashbrown::HashTable;
1615

1716
use crate::Allocative;
@@ -20,28 +19,6 @@ use crate::Visitor;
2019

2120
const CAPACITY_NAME: Key = Key::new("capacity");
2221

23-
impl<T: Allocative> Allocative for RawTable<T> {
24-
fn visit<'a, 'b: 'a>(&self, visitor: &'a mut Visitor<'b>) {
25-
use crate::impls::common::DATA_NAME;
26-
use crate::impls::hashbrown_util;
27-
28-
let mut visitor = visitor.enter_self_sized::<Self>();
29-
{
30-
let mut visitor = visitor.enter_unique(DATA_NAME, mem::size_of::<*const T>());
31-
{
32-
let mut visitor = visitor.enter(
33-
CAPACITY_NAME,
34-
hashbrown_util::raw_table_alloc_size_for_len::<T>(self.capacity()),
35-
);
36-
unsafe { visitor.visit_iter(self.iter().map(|e| e.as_ref())) };
37-
visitor.exit();
38-
}
39-
visitor.exit();
40-
}
41-
visitor.exit();
42-
}
43-
}
44-
4522
impl<T: Allocative> Allocative for HashTable<T> {
4623
fn visit<'a, 'b: 'a>(&self, visitor: &'a mut Visitor<'b>) {
4724
use crate::impls::common::DATA_NAME;
@@ -70,7 +47,6 @@ mod tests {
7047
use std::hash::Hash;
7148
use std::hash::Hasher;
7249

73-
use hashbrown::raw::RawTable;
7450
use hashbrown::HashTable;
7551

7652
use crate::golden::golden_test;
@@ -81,16 +57,6 @@ mod tests {
8157
hasher.finish()
8258
}
8359

84-
#[test]
85-
fn test_raw_table() {
86-
let mut table = RawTable::with_capacity(100);
87-
for i in 0..100 {
88-
table.insert(hash(&i.to_string()), i.to_string(), hash);
89-
}
90-
91-
golden_test!(&table);
92-
}
93-
9460
#[test]
9561
fn test_hash_table() {
9662
let mut table = HashTable::with_capacity(100);

starlark/src/values/trace.rs

-9
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ use std::sync::Arc;
3535
use std::sync::Mutex;
3636

3737
use either::Either;
38-
use hashbrown::raw::RawTable;
3938
use hashbrown::HashTable;
4039
use starlark_map::small_set::SmallSet;
4140
use starlark_map::Hashed;
@@ -81,14 +80,6 @@ unsafe impl<'v, T: Trace<'v>> Trace<'v> for [T] {
8180
}
8281
}
8382

84-
unsafe impl<'v, T: Trace<'v>> Trace<'v> for RawTable<T> {
85-
fn trace(&mut self, tracer: &Tracer<'v>) {
86-
unsafe {
87-
self.iter().for_each(|e| e.as_mut().trace(tracer));
88-
}
89-
}
90-
}
91-
9283
unsafe impl<'v, T: Trace<'v>> Trace<'v> for HashTable<T> {
9384
fn trace(&mut self, tracer: &Tracer<'v>) {
9485
self.iter_mut().for_each(|e| e.trace(tracer));

starlark/src/values/types/string/intern/interner.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
//! Generic interner for starlark strings.
1919
20-
use hashbrown::raw::RawTable;
20+
use hashbrown::HashTable;
2121

2222
use crate as starlark;
2323
use crate::collections::Hashed;
@@ -28,7 +28,7 @@ use crate::values::Trace;
2828
/// `[FrozenStringValue]` interner.
2929
#[derive(Default)]
3030
pub(crate) struct FrozenStringValueInterner {
31-
map: RawTable<FrozenStringValue>,
31+
map: HashTable<FrozenStringValue>,
3232
}
3333

3434
impl FrozenStringValueInterner {
@@ -39,14 +39,15 @@ impl FrozenStringValueInterner {
3939
) -> FrozenStringValue {
4040
match self
4141
.map
42-
.get(s.hash().promote(), |x| s == x.get_hashed_str())
42+
.find(s.hash().promote(), |x| s == x.get_hashed_str())
4343
{
4444
Some(frozen_string) => *frozen_string,
4545
None => {
4646
let frozen_string = alloc();
47-
self.map.insert(s.hash().promote(), frozen_string, |x| {
48-
x.get_hash().promote()
49-
});
47+
self.map
48+
.insert_unique(s.hash().promote(), frozen_string, |x| {
49+
x.get_hash().promote()
50+
});
5051
frozen_string
5152
}
5253
}
@@ -55,7 +56,7 @@ impl FrozenStringValueInterner {
5556

5657
#[derive(Default, Trace)]
5758
pub(crate) struct StringValueInterner<'v> {
58-
map: RawTable<StringValue<'v>>,
59+
map: HashTable<StringValue<'v>>,
5960
}
6061

6162
impl<'v> StringValueInterner<'v> {
@@ -66,13 +67,13 @@ impl<'v> StringValueInterner<'v> {
6667
) -> StringValue<'v> {
6768
match self
6869
.map
69-
.get(s.hash().promote(), |x| s == x.get_hashed_str())
70+
.find(s.hash().promote(), |x| s == x.get_hashed_str())
7071
{
7172
Some(string_value) => *string_value,
7273
None => {
7374
let string_value = alloc();
7475
self.map
75-
.insert(s.hash().promote(), string_value, |x| x.get_hash().promote());
76+
.insert_unique(s.hash().promote(), string_value, |x| x.get_hash().promote());
7677
string_value
7778
}
7879
}

starlark_map/src/unordered_map.rs

+39-59
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ use std::mem;
2424
use std::ops::Index;
2525

2626
use allocative::Allocative;
27-
use hashbrown::raw::Bucket;
28-
use hashbrown::raw::RawTable;
27+
use hashbrown::hash_table;
28+
use hashbrown::HashTable;
2929

3030
use crate::Equivalent;
3131
use crate::Hashed;
@@ -35,7 +35,7 @@ use crate::StarlarkHasher;
3535
/// Hash map which does not expose any insertion order-specific behavior
3636
/// (except `Debug`).
3737
#[derive(Clone, Allocative)]
38-
pub struct UnorderedMap<K, V>(RawTable<(K, V)>);
38+
pub struct UnorderedMap<K, V>(HashTable<(K, V)>);
3939

4040
impl<K, V> Default for UnorderedMap<K, V> {
4141
#[inline]
@@ -48,13 +48,13 @@ impl<K, V> UnorderedMap<K, V> {
4848
/// Create a new empty map.
4949
#[inline]
5050
pub const fn new() -> UnorderedMap<K, V> {
51-
UnorderedMap(RawTable::new())
51+
UnorderedMap(HashTable::new())
5252
}
5353

5454
/// Create a new empty map with the specified capacity.
5555
#[inline]
5656
pub fn with_capacity(n: usize) -> UnorderedMap<K, V> {
57-
UnorderedMap(RawTable::with_capacity(n))
57+
UnorderedMap(HashTable::with_capacity(n))
5858
}
5959

6060
/// Get the number of elements in the map.
@@ -87,7 +87,7 @@ impl<K, V> UnorderedMap<K, V> {
8787
{
8888
let hash = key.hash().promote();
8989
self.0
90-
.get(hash, |(next_k, _v)| key.key().equivalent(next_k))
90+
.find(hash, |(next_k, _v)| key.key().equivalent(next_k))
9191
.map(|(_, v)| v)
9292
}
9393

@@ -99,7 +99,7 @@ impl<K, V> UnorderedMap<K, V> {
9999
{
100100
let hash = StarlarkHashValue::new(k).promote();
101101
self.0
102-
.get_mut(hash, |(next_k, _v)| k.equivalent(next_k))
102+
.find_mut(hash, |(next_k, _v)| k.equivalent(next_k))
103103
.map(|(_, v)| v)
104104
}
105105

@@ -157,19 +157,7 @@ impl<K, V> UnorderedMap<K, V> {
157157
where
158158
F: FnMut(&K, &mut V) -> bool,
159159
{
160-
// TODO(nga): update hashbrown and use safe `HashTable` instead of this heavily unsafe code:
161-
// https://docs.rs/hashbrown/latest/hashbrown/struct.HashTable.html
162-
163-
// Unsafe code is copy-paste from `hashbrown` crate:
164-
// https://github.com/rust-lang/hashbrown/blob/f2e62124cd947b5e2309dd6a24c7e422932aae97/src/map.rs#L923
165-
unsafe {
166-
for item in self.0.iter() {
167-
let (k, v) = item.as_mut();
168-
if !f(k, v) {
169-
self.0.erase(item);
170-
}
171-
}
172-
}
160+
self.0.retain(move |(k, v)| f(k, v));
173161
}
174162

175163
/// Get an entry in the map for in-place manipulation.
@@ -179,14 +167,13 @@ impl<K, V> UnorderedMap<K, V> {
179167
K: Hash + Eq,
180168
{
181169
let hash = StarlarkHashValue::new(&k).promote();
182-
if let Some(bucket) = self.0.find(hash, |(next_k, _v)| k.equivalent(next_k)) {
183-
Entry::Occupied(OccupiedEntry { _map: self, bucket })
184-
} else {
185-
Entry::Vacant(VacantEntry {
186-
map: self,
187-
key: k,
188-
hash,
189-
})
170+
match self.0.entry(
171+
hash,
172+
|(next_k, _v)| k.equivalent(next_k),
173+
|(k, _v)| StarlarkHashValue::new(k).promote(),
174+
) {
175+
hash_table::Entry::Occupied(entry) => Entry::Occupied(OccupiedEntry { entry }),
176+
hash_table::Entry::Vacant(entry) => Entry::Vacant(VacantEntry { entry, key: k }),
190177
}
191178
}
192179

@@ -205,13 +192,13 @@ impl<K, V> UnorderedMap<K, V> {
205192
/// Entries in the map, in arbitrary order.
206193
#[inline]
207194
pub fn entries_unordered(&self) -> impl ExactSizeIterator<Item = (&K, &V)> {
208-
unsafe { self.0.iter().map(|e| (&e.as_ref().0, &e.as_ref().1)) }
195+
self.0.iter().map(|e| (&e.0, &e.1))
209196
}
210197

211198
/// Entries in the map, in arbitrary order.
212199
#[inline]
213200
pub fn entries_unordered_mut(&mut self) -> impl ExactSizeIterator<Item = (&K, &mut V)> {
214-
unsafe { self.0.iter().map(|e| (&e.as_ref().0, &mut e.as_mut().1)) }
201+
self.0.iter_mut().map(|e| (&e.0, &mut e.1))
215202
}
216203

217204
/// Keys in the map, in arbitrary order.
@@ -322,14 +309,12 @@ impl<K: Eq + Hash, V> FromIterator<(K, V)> for UnorderedMap<K, V> {
322309

323310
/// Reference to an occupied entry in a [`UnorderedMap`].
324311
pub struct OccupiedEntry<'a, K, V> {
325-
_map: &'a mut UnorderedMap<K, V>,
326-
bucket: Bucket<(K, V)>,
312+
entry: hash_table::OccupiedEntry<'a, (K, V)>,
327313
}
328314

329315
/// Reference to a vacant entry in a [`UnorderedMap`].
330316
pub struct VacantEntry<'a, K, V> {
331-
map: &'a mut UnorderedMap<K, V>,
332-
hash: u64,
317+
entry: hash_table::VacantEntry<'a, (K, V)>,
333318
key: K,
334319
}
335320

@@ -345,23 +330,21 @@ impl<'a, K: Eq + Hash, V> VacantEntry<'a, K, V> {
345330
/// Insert a value into the map.
346331
#[inline]
347332
pub fn insert(self, value: V) {
348-
self.map.0.insert(self.hash, (self.key, value), |(k, _v)| {
349-
StarlarkHashValue::new(k).promote()
350-
});
333+
self.entry.insert((self.key, value));
351334
}
352335
}
353336

354337
impl<'a, K, V> OccupiedEntry<'a, K, V> {
355338
/// Remove the entry from the map.
356339
#[inline]
357340
pub fn get(&self) -> &V {
358-
unsafe { &self.bucket.as_ref().1 }
341+
&self.entry.get().1
359342
}
360343

361344
/// Get a reference to the value associated with the entry.
362345
#[inline]
363346
pub fn get_mut(&mut self) -> &mut V {
364-
unsafe { &mut self.bucket.as_mut().1 }
347+
&mut self.entry.get_mut().1
365348
}
366349

367350
/// Replace the value associated with the entry.
@@ -403,26 +386,23 @@ impl<'a, K, V> RawEntryBuilderMut<'a, K, V> {
403386
F: for<'b> FnMut(&'b K) -> bool,
404387
{
405388
let hash = hash.promote();
406-
if let Some(bucket) = self.map.0.find(hash, |(next_k, _v)| is_match(next_k)) {
407-
RawEntryMut::Occupied(RawOccupiedEntryMut {
408-
map: self.map,
409-
bucket,
410-
})
411-
} else {
412-
RawEntryMut::Vacant(RawVacantEntryMut { map: self.map })
389+
match self.map.0.find_entry(hash, |(next_k, _v)| is_match(next_k)) {
390+
Ok(entry) => RawEntryMut::Occupied(RawOccupiedEntryMut { entry }),
391+
Err(entry) => RawEntryMut::Vacant(RawVacantEntryMut {
392+
table: entry.into_table(),
393+
}),
413394
}
414395
}
415396
}
416397

417398
/// Occupied entry.
418399
pub struct RawOccupiedEntryMut<'a, K, V> {
419-
map: &'a mut UnorderedMap<K, V>,
420-
bucket: Bucket<(K, V)>,
400+
entry: hash_table::OccupiedEntry<'a, (K, V)>,
421401
}
422402

423403
/// Vacant entry.
424404
pub struct RawVacantEntryMut<'a, K, V> {
425-
map: &'a mut UnorderedMap<K, V>,
405+
table: &'a mut HashTable<(K, V)>,
426406
}
427407

428408
/// Raw entry.
@@ -449,19 +429,19 @@ impl<'a, K, V> RawOccupiedEntryMut<'a, K, V> {
449429
/// Get a reference to the value associated with the entry.
450430
#[inline]
451431
pub fn get(&self) -> &V {
452-
unsafe { &self.bucket.as_ref().1 }
432+
&self.entry.get().1
453433
}
454434

455435
/// Get a reference to the value associated with the entry.
456436
#[inline]
457437
pub fn get_mut(&mut self) -> &mut V {
458-
unsafe { &mut self.bucket.as_mut().1 }
438+
&mut self.entry.get_mut().1
459439
}
460440

461441
/// Get a reference to the key associated with the entry.
462442
#[inline]
463443
pub fn key_mut(&mut self) -> &mut K {
464-
unsafe { &mut self.bucket.as_mut().0 }
444+
&mut self.entry.get_mut().0
465445
}
466446

467447
/// Remove the entry, return the value.
@@ -473,7 +453,7 @@ impl<'a, K, V> RawOccupiedEntryMut<'a, K, V> {
473453
/// Remove the entry, return the key and value.
474454
#[inline]
475455
pub fn remove_entry(self) -> (K, V) {
476-
unsafe { self.map.0.remove(self.bucket).0 }
456+
self.entry.remove().0
477457
}
478458
}
479459

@@ -496,12 +476,12 @@ impl<'a, K, V> RawVacantEntryMut<'a, K, V> {
496476
where
497477
K: Hash,
498478
{
499-
let (k, v) =
500-
self.map
501-
.0
502-
.insert_entry(key.hash().promote(), (key.into_key(), value), |(k, _v)| {
503-
StarlarkHashValue::new(k).promote()
504-
});
479+
let (k, v) = self
480+
.table
481+
.insert_unique(key.hash().promote(), (key.into_key(), value), |(k, _v)| {
482+
StarlarkHashValue::new(k).promote()
483+
})
484+
.into_mut();
505485
(k, v)
506486
}
507487
}

0 commit comments

Comments
 (0)