Skip to content

Commit c4b66d1

Browse files
committed
slightly change the entry code to make miri happier
1 parent 647c1e5 commit c4b66d1

File tree

1 file changed

+27
-26
lines changed

1 file changed

+27
-26
lines changed

table_seq/src/table_seq/entry.rs

+27-26
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ enum VacantEntryKind<'a, T> {
1515
/// It is part of the [`Entry`] enum.
1616
// SAFETY: The kind accurately describes the state of the subtable.
1717
pub struct VacantEntry<'a, T> {
18-
tables: &'a mut TableSeq<T>,
18+
tables: *mut TableSeq<T>,
1919
subtable: usize,
2020
kind: VacantEntryKind<'a, T>,
2121
}
@@ -26,14 +26,15 @@ enum OccupiedEntryKind<'a, T> {
2626
PairTable(usize),
2727
// On both SmallTable and LargeTable the `bool` is true iff the OccupiedEntry is the only entry in the table.
2828
SmallTable(SmallSubtableOccupiedEntry<'a, T>, bool),
29-
LargeTable(hashbrown::hash_table::OccupiedEntry<'a, T>, bool),
29+
// We need MaybeUninit here because we may deallocate the HashTable, at which point the OccupiedEntry becomes invalid.
30+
LargeTable(MaybeUninit<hashbrown::hash_table::OccupiedEntry<'a, T>>, bool),
3031
}
3132

3233
/// A view into an occupied entry in a [`TableSeq`]'s subtable.
3334
/// It is part of the [`Entry`] enum.
3435
// SAFETY: The kind accurately describes the state of the subtable.
3536
pub struct OccupiedEntry<'a, T> {
36-
tables: &'a mut TableSeq<T>,
37+
tables: *mut TableSeq<T>,
3738
subtable: usize,
3839
entry_ptr: *mut T,
3940
kind: OccupiedEntryKind<'a, T>,
@@ -154,7 +155,7 @@ impl<T> TableSeq<T> {
154155
tables: self,
155156
subtable,
156157
entry_ptr: &mut *entry.get_mut(),
157-
kind: OccupiedEntryKind::LargeTable(entry, is_single)
158+
kind: OccupiedEntryKind::LargeTable(MaybeUninit::new(entry), is_single)
158159
}),
159160
hashbrown::hash_table::Entry::Vacant(entry) =>
160161
Entry::Vacant(VacantEntry {
@@ -228,11 +229,11 @@ impl<'a, T> VacantEntry<'a, T> {
228229
let chunk_index = self.subtable >> CHUNK_SHIFT;
229230
let allocator_index = self.subtable >> ALLOCATOR_SHIFT;
230231

231-
let chunk_alloc = unsafe { tables.allocators.get_unchecked_mut(allocator_index) };
232-
let chunk = unsafe { tables.chunks.get_unchecked_mut(chunk_index) };
232+
let chunk_alloc = unsafe { (*tables).allocators.get_unchecked_mut(allocator_index) };
233+
let chunk = unsafe { (*tables).chunks.get_unchecked_mut(chunk_index) };
233234
match kind {
234235
VacantEntryKind::EmptyChunk => unsafe {
235-
tables.entries += 1;
236+
(*tables).entries += 1;
236237
let size_class = SizeClass::class_for_index(0);
237238

238239
chunk.node = chunk_alloc.alloc(size_class);
@@ -247,7 +248,7 @@ impl<'a, T> VacantEntry<'a, T> {
247248
}
248249
},
249250
VacantEntryKind::EmptyTable => unsafe {
250-
tables.entries += 1;
251+
(*tables).entries += 1;
251252
let mut node = chunk.node(chunk_alloc);
252253

253254
let entry_offset = chunk.meta.entry_offset(chunk_slot);
@@ -267,7 +268,7 @@ impl<'a, T> VacantEntry<'a, T> {
267268
VacantEntryKind::SingletonTable => unsafe {
268269
let mut node = chunk.node(chunk_alloc);
269270
let entry_offset = chunk.meta.entry_offset(chunk_slot);
270-
tables.entries += 1;
271+
(*tables).entries += 1;
271272

272273
node.make_entry_gap_resize(entry_offset, chunk, chunk_alloc);
273274

@@ -285,7 +286,7 @@ impl<'a, T> VacantEntry<'a, T> {
285286
VacantEntryKind::PairTable(hash, pair_hashes) => unsafe {
286287
let mut node = chunk.node(chunk_alloc);
287288
let entry_offset = chunk.meta.entry_offset(chunk_slot);
288-
tables.entries += 1;
289+
(*tables).entries += 1;
289290

290291
let found_pair = node.entry_ptr(entry_offset).cast::<[T; 2]>().read();
291292
let table_offset = chunk.meta.table_offset(chunk_slot);
@@ -299,7 +300,7 @@ impl<'a, T> VacantEntry<'a, T> {
299300

300301
let table_ptr = node.table_ptr(table_offset);
301302

302-
let table_alloc = &mut tables.allocators[allocator_index ^ 1];
303+
let table_alloc = &mut (*tables).allocators[allocator_index ^ 1];
303304
let (entry_ptr, table) =
304305
SmallSubtable::new(found_pair, pair_hashes, value, hash, table_alloc);
305306

@@ -317,9 +318,9 @@ impl<'a, T> VacantEntry<'a, T> {
317318
}
318319
},
319320
VacantEntryKind::SmallTable(vacant_entry) => {
320-
let table_alloc = &mut tables.allocators[allocator_index ^ 1];
321+
let table_alloc = unsafe { &mut (*tables).allocators[allocator_index ^ 1] };
321322
let mut new_entry = unsafe { vacant_entry.insert(value, table_alloc) };
322-
tables.entries += 1;
323+
unsafe { (*tables).entries += 1 };
323324
OccupiedEntry {
324325
tables,
325326
subtable,
@@ -329,20 +330,20 @@ impl<'a, T> VacantEntry<'a, T> {
329330
},
330331
VacantEntryKind::LargeTable(vacant_entry) => {
331332
let mut new_entry = vacant_entry.insert(value);
332-
tables.entries += 1;
333+
unsafe { (*tables).entries += 1 };
333334
OccupiedEntry {
334335
tables,
335336
subtable,
336337
entry_ptr: &mut *new_entry.get_mut(),
337-
kind: OccupiedEntryKind::LargeTable(new_entry, false)
338+
kind: OccupiedEntryKind::LargeTable(MaybeUninit::new(new_entry), false)
338339
}
339340
},
340341
}
341342
}
342343

343344
/// Converts the `VacantEntry` into a mutable reference to the underlying `TableSeq`.
344345
pub fn into_tables(self) -> &'a mut TableSeq<T> {
345-
self.tables
346+
unsafe { &mut *self.tables }
346347
}
347348
/// Returns the subtable index of the `VacantEntry`.
348349
pub fn subtable(&self) -> usize {
@@ -365,7 +366,7 @@ impl<'a, T> OccupiedEntry<'a, T> {
365366
}
366367
/// Converts the `OccupiedEntry` into a mutable reference to the underlying `TableSeq`.
367368
pub fn into_tables(self) -> &'a mut TableSeq<T> {
368-
self.tables
369+
unsafe { &mut *self.tables }
369370
}
370371
/// Returns the subtable index of the `OccupiedEntry`.
371372
pub fn subtable(&self) -> usize {
@@ -378,15 +379,15 @@ impl<'a, T> OccupiedEntry<'a, T> {
378379
let chunk_index = subtable >> CHUNK_SHIFT;
379380
let allocator_index = subtable >> ALLOCATOR_SHIFT;
380381

381-
let chunk = unsafe { tables.chunks.get_unchecked_mut(chunk_index) };
382-
let chunk_alloc = unsafe { tables.allocators.get_unchecked_mut(allocator_index) };
382+
let chunk = unsafe { (*tables).chunks.get_unchecked_mut(chunk_index) };
383+
let chunk_alloc = unsafe { (*tables).allocators.get_unchecked_mut(allocator_index) };
383384

384385
match kind {
385386
OccupiedEntryKind::SingletonTable => unsafe {
386387
let mut node = chunk.node(chunk_alloc);
387388
let entry_offset = chunk.meta.entry_offset(chunk_slot);
388389

389-
tables.entries -= 1;
390+
(*tables).entries -= 1;
390391
let value = entry_ptr.read();
391392

392393
node.close_entry_gap_resize(entry_offset, chunk, chunk_alloc);
@@ -404,7 +405,7 @@ impl<'a, T> OccupiedEntry<'a, T> {
404405
let mut node = chunk.node(chunk_alloc);
405406
let entry_offset = chunk.meta.entry_offset(chunk_slot) + index;
406407

407-
tables.entries -= 1;
408+
(*tables).entries -= 1;
408409
let value = entry_ptr.read();
409410

410411
node.close_entry_gap_resize(entry_offset, chunk, chunk_alloc);
@@ -414,8 +415,8 @@ impl<'a, T> OccupiedEntry<'a, T> {
414415
},
415416
OccupiedEntryKind::SmallTable(entry, will_delete) => unsafe {
416417
let mut node = chunk.node(chunk_alloc);
417-
let table_alloc = &mut tables.allocators[allocator_index ^ 1];
418-
tables.entries -= 1;
418+
let table_alloc = &mut (*tables).allocators[allocator_index ^ 1];
419+
(*tables).entries -= 1;
419420
let (removed, entry) = entry.remove(table_alloc);
420421

421422
// TODO earlier shrinking
@@ -424,7 +425,7 @@ impl<'a, T> OccupiedEntry<'a, T> {
424425
let table_offset = chunk.meta.table_offset(chunk_slot);
425426
table.drop_and_dealloc(table_alloc);
426427
let chunk_alloc =
427-
tables.allocators.get_unchecked_mut(allocator_index);
428+
(*tables).allocators.get_unchecked_mut(allocator_index);
428429
node.close_table_gap_resize(table_offset, chunk, chunk_alloc);
429430
chunk.meta.make_empty(chunk_slot);
430431
if chunk.meta.is_empty() {
@@ -439,8 +440,8 @@ impl<'a, T> OccupiedEntry<'a, T> {
439440
(removed, VacantEntry { tables, subtable, kind })
440441
},
441442
OccupiedEntryKind::LargeTable(entry, will_delete) => unsafe {
442-
tables.entries -= 1;
443-
let (removed, entry) = entry.remove();
443+
(*tables).entries -= 1;
444+
let (removed, entry) = entry.assume_init().remove();
444445

445446
// TODO external -> internal shrinking
446447
let kind = if will_delete {

0 commit comments

Comments
 (0)