@@ -1622,17 +1622,39 @@ impl<A: Allocator + Clone> RawTableInner<A> {
16221622 }
16231623 }
16241624
1625- /// Searches for an element in the table. This uses dynamic dispatch to reduce the amount of
1626- /// code generated, but it is eliminated by LLVM optimizations.
1625+ /// Searches for an element in a table, returning the `index` of the found element.
1626+ /// This uses dynamic dispatch to reduce the amount of code generated, but it is
1627+ /// eliminated by LLVM optimizations.
1628+ ///
1629+ /// This function does not make any changes to the `data` part of the table, or any
1630+ /// changes to the `items` or `growth_left` field of the table.
1631+ ///
1632+ /// The table must have at least 1 empty `bucket`, otherwise, if the
1633+ /// `eq: &mut dyn FnMut(usize) -> bool` function does not return `true`,
1634+ /// this function will also never return (will go into an infinite loop).
16271635 #[ inline( always) ]
16281636 fn find_inner ( & self , hash : u64 , eq : & mut dyn FnMut ( usize ) -> bool ) -> Option < usize > {
16291637 let h2_hash = h2 ( hash) ;
16301638 let mut probe_seq = self . probe_seq ( hash) ;
16311639
16321640 loop {
1641+ // SAFETY:
1642+ // * `ProbeSeq.pos` cannot be greater than `self.bucket_mask = self.buckets() - 1`
1643+ // of the table due to masking with `self.bucket_mask`.
1644+ //
1645+ // * Even if `ProbeSeq.pos` returns `position == self.bucket_mask`, it is safe to
1646+ // call `Group::load` due to the extended control bytes range, which is
1647+ // `self.bucket_mask + 1 + Group::WIDTH` (in fact, this means that the last control
1648+ // byte will never be read for the allocated table);
1649+ //
1650+ // * Also, even if `RawTableInner` is not already allocated, `ProbeSeq.pos` will
1651+ // always return "0" (zero), so Group::load will read unaligned `Group::static_empty()`
1652+ // bytes, which is safe (see RawTableInner::new_in).
16331653 let group = unsafe { Group :: load ( self . ctrl ( probe_seq. pos ) ) } ;
16341654
16351655 for bit in group. match_byte ( h2_hash) {
1656+ // This is the same as `(probe_seq.pos + bit) % self.buckets()` because the number
1657+ // of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
16361658 let index = ( probe_seq. pos + bit) & self . bucket_mask ;
16371659
16381660 if likely ( eq ( index) ) {
0 commit comments