Skip to content

Commit 179344d

Browse files
committed
Auto merge of #392 - JustForFun88:doc_new, r=Amanieu
Doc `new_uninitialized` and `fallible_with_capacity`
2 parents 7a4f5cc + 0de173b commit 179344d

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

src/raw/mod.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1480,6 +1480,11 @@ where
14801480
}
14811481

14821482
impl<A> RawTableInner<A> {
1483+
/// Creates a new empty hash table without allocating any memory.
1484+
///
1485+
/// In effect this returns a table with exactly 1 bucket. However we can
1486+
/// leave the data pointer dangling since that bucket is never accessed
1487+
/// due to our load factor forcing us to always have at least 1 free bucket.
14831488
#[inline]
14841489
const fn new_in(alloc: A) -> Self {
14851490
Self {
@@ -1494,6 +1499,18 @@ impl<A> RawTableInner<A> {
14941499
}
14951500

14961501
impl<A: Allocator + Clone> RawTableInner<A> {
1502+
/// Allocates a new [`RawTableInner`] with the given number of buckets.
1503+
/// The control bytes and buckets are left uninitialized.
1504+
///
1505+
/// # Safety
1506+
///
1507+
/// The caller of this function must ensure that the `buckets` is power of two
1508+
/// and also initialize all control bytes of the length `self.bucket_mask + 1 +
1509+
/// Group::WIDTH` with the [`EMPTY`] bytes.
1510+
///
1511+
/// See also [`Allocator`] API for other safety concerns.
1512+
///
1513+
/// [`Allocator`]: https://doc.rust-lang.org/alloc/alloc/trait.Allocator.html
14971514
#[cfg_attr(feature = "inline-more", inline)]
14981515
unsafe fn new_uninitialized(
14991516
alloc: A,
@@ -1514,6 +1531,7 @@ impl<A: Allocator + Clone> RawTableInner<A> {
15141531
Err(_) => return Err(fallibility.alloc_err(layout)),
15151532
};
15161533

1534+
// SAFETY: null pointer will be caught in above check
15171535
let ctrl = NonNull::new_unchecked(ptr.as_ptr().add(ctrl_offset));
15181536
Ok(Self {
15191537
ctrl,
@@ -1524,6 +1542,10 @@ impl<A: Allocator + Clone> RawTableInner<A> {
15241542
})
15251543
}
15261544

1545+
/// Attempts to allocate a new [`RawTableInner`] with at least enough
1546+
/// capacity for inserting the given number of elements without reallocating.
1547+
///
1548+
/// All the control bytes are initialized with the [`EMPTY`] bytes.
15271549
#[inline]
15281550
fn fallible_with_capacity(
15291551
alloc: A,
@@ -1534,11 +1556,16 @@ impl<A: Allocator + Clone> RawTableInner<A> {
15341556
if capacity == 0 {
15351557
Ok(Self::new_in(alloc))
15361558
} else {
1559+
// SAFETY: We checked that we could successfully allocate the new table, and then
1560+
// initialized all control bytes with the constant `EMPTY` byte.
15371561
unsafe {
15381562
let buckets =
15391563
capacity_to_buckets(capacity).ok_or_else(|| fallibility.capacity_overflow())?;
15401564

15411565
let result = Self::new_uninitialized(alloc, table_layout, buckets, fallibility)?;
1566+
// SAFETY: We checked that the table is allocated and therefore the table already has
1567+
// `self.bucket_mask + 1 + Group::WIDTH` number of control bytes (see TableLayout::calculate_layout_for)
1568+
// so writing `self.num_ctrl_bytes() == bucket_mask + 1 + Group::WIDTH` bytes is safe.
15421569
result.ctrl(0).write_bytes(EMPTY, result.num_ctrl_bytes());
15431570

15441571
Ok(result)

0 commit comments

Comments
 (0)