Skip to content

Commit dee5c03

Browse files
JustForFun88a1phyr
authored andcommitted
Add comments
1 parent 5aa1b77 commit dee5c03

File tree

1 file changed

+53
-6
lines changed

1 file changed

+53
-6
lines changed

src/raw/mod.rs

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3847,8 +3847,30 @@ impl<T> RawIterRange<T> {
38473847
}
38483848
}
38493849

3850+
/// Folds every element into an accumulator by applying an operation,
3851+
/// returning the final result.
3852+
///
3853+
/// `fold_impl()` takes three arguments: a number of items in the table, an initial value,
3854+
/// and a closure with two arguments: an 'accumulator', and an element. The closure
3855+
/// returns the value that the accumulator should have for the next iteration.
3856+
///
3857+
/// The initial value is the value the accumulator will have on the first call.
3858+
///
3859+
/// After applying this closure to every element of the iterator, `fold_impl()`
3860+
/// returns the accumulator.
3861+
///
38503862
/// # Safety
3851-
/// The provided `n` value must match the actual number of items
3863+
///
3864+
/// If any of the following conditions are violated, the result is
3865+
/// [`Undefined Behavior`]:
3866+
///
3867+
/// * The [`RawTableInner`] / [`RawTable`] must be alive and not moved,
3868+
/// i.e. table outlives the `RawIterRange`;
3869+
///
3870+
/// * The provided `n` value must match the actual number of items
3871+
/// in the table.
3872+
///
3873+
/// [`Undefined Behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
38523874
#[allow(clippy::while_let_on_iterator)]
38533875
#[cfg_attr(feature = "inline-more", inline)]
38543876
unsafe fn fold_impl<F, B>(mut self, mut n: usize, mut acc: B, mut f: F) -> B
@@ -3861,6 +3883,8 @@ impl<T> RawIterRange<T> {
38613883

38623884
loop {
38633885
while let Some(index) = self.current_group.next() {
3886+
// The returned `index` will always be in the range `0..Group::WIDTH`,
3887+
// so that calling `self.data.next_n(index)` is safe (see detailed explanation below).
38643888
debug_assert!(n != 0);
38653889
let bucket = self.data.next_n(index);
38663890
acc = f(acc, bucket);
@@ -3871,11 +3895,34 @@ impl<T> RawIterRange<T> {
38713895
return acc;
38723896
}
38733897

3874-
// We might read past self.end up to the next group boundary,
3875-
// but this is fine because it only occurs on tables smaller
3876-
// than the group size where the trailing control bytes are all
3877-
// EMPTY. On larger tables self.end is guaranteed to be aligned
3878-
// to the group size (since tables are power-of-two sized).
3898+
// SAFETY: The caller of this function ensures that:
3899+
//
3900+
// 1. The provided `n` value matches the actual number of items in the table;
3901+
// 2. The table is alive and did not moved.
3902+
//
3903+
// Taking the above into account, we always stay within the bounds, because:
3904+
//
3905+
// 1. For tables smaller than the group width (self.buckets() <= Group::WIDTH),
3906+
// we will never end up in the given branch, since we should have already
3907+
// yielded all the elements of the table.
3908+
//
3909+
// 2. For tables larger than the group width. The the number of buckets is a
3910+
// power of two (2 ^ n), Group::WIDTH is also power of two (2 ^ k). Sinse
3911+
// `(2 ^ n) > (2 ^ k)`, than `(2 ^ n) % (2 ^ k) = 0`. As we start from the
3912+
// the start of the array of control bytes, and never try to iterate after
3913+
// getting all the elements, the last `self.current_group` will read bytes
3914+
// from the `self.buckets() - Group::WIDTH` index. We know also that
3915+
// `self.current_group.next()` will always retun indices within the range
3916+
// `0..Group::WIDTH`.
3917+
//
3918+
// Knowing all of the above and taking into account that we are synchronizing
3919+
// the `self.data` index with the index we used to read the `self.current_group`,
3920+
// the subsequent `self.data.next_n(index)` will always return a bucket with
3921+
// an index number less than `self.buckets()`.
3922+
//
3923+
// The last `self.next_ctrl`, whose index would be `self.buckets()`, will never
3924+
// actually be read, since we should have already yielded all the elements of
3925+
// the table.
38793926
self.current_group = Group::load_aligned(self.next_ctrl).match_full().into_iter();
38803927
self.data = self.data.next_n(Group::WIDTH);
38813928
self.next_ctrl = self.next_ctrl.add(Group::WIDTH);

0 commit comments

Comments
 (0)