@@ -45,6 +45,8 @@ impl IndexEntry {
4545 const FREE : Self = Self ( -1 ) ;
4646 const DUMMY : Self = Self ( -2 ) ;
4747
48+ /// # Safety
49+ /// idx must not be one of FREE or DUMMY
4850 unsafe fn from_index_unchecked ( idx : usize ) -> Self {
4951 debug_assert ! ( ( idx as isize ) >= 0 ) ;
5052 Self ( idx as i64 )
@@ -164,7 +166,9 @@ impl<T> DictInner<T> {
164166 loop {
165167 let index_index = idxs. next ( ) ;
166168 unsafe {
167- // index is always valid here
169+ // Safety: index is always valid here
170+ // index_index is generated by idxs
171+ // entry_idx is saved one
168172 let idx = self . indices . get_unchecked_mut ( index_index) ;
169173 if * idx == IndexEntry :: FREE {
170174 * idx = IndexEntry :: from_index_unchecked ( entry_idx) ;
@@ -196,7 +200,11 @@ impl<T> DictInner<T> {
196200 } ;
197201 let entry_index = self . entries . len ( ) ;
198202 self . entries . push ( Some ( entry) ) ;
199- self . indices [ index] = unsafe { IndexEntry :: from_index_unchecked ( entry_index) } ;
203+ self . indices [ index] = unsafe {
204+ // SAFETY: entry_index is self.entries.len(). it never can
205+ // grow to `usize-2` because hash tables cannot full its index
206+ IndexEntry :: from_index_unchecked ( entry_index)
207+ } ;
200208 self . used += 1 ;
201209 if let IndexEntry :: FREE = index_entry {
202210 self . filled += 1 ;
@@ -540,7 +548,10 @@ impl<T: Clone> Dict<T> {
540548 } ) ;
541549 loop {
542550 let index_index = idxs. next ( ) ;
543- let index_entry = * unsafe { inner. indices . get_unchecked ( index_index) } ;
551+ let index_entry = * unsafe {
552+ // Safety: index_index is generated
553+ inner. indices . get_unchecked ( index_index)
554+ } ;
544555 match index_entry {
545556 IndexEntry :: DUMMY => {
546557 if free_slot. is_none ( ) {
@@ -556,7 +567,7 @@ impl<T: Clone> Dict<T> {
556567 }
557568 idx => {
558569 let entry = unsafe {
559- // DUMMY and FREE are already handled above.
570+ // Safety: DUMMY and FREE are already handled above.
560571 // i is always valid and entry always exists.
561572 let i = idx. index ( ) . unwrap_unchecked ( ) ;
562573 inner. entries . get_unchecked ( i) . as_ref ( ) . unwrap_unchecked ( )
@@ -619,7 +630,10 @@ impl<T: Clone> Dict<T> {
619630 // The dict was changed since we did lookup. Let's try again.
620631 _ => return Ok ( ControlFlow :: Continue ( ( ) ) ) ,
621632 }
622- * unsafe { inner. indices . get_unchecked_mut ( index_index) } = IndexEntry :: DUMMY ;
633+ * unsafe {
634+ // index_index is result of lookup
635+ inner. indices . get_unchecked_mut ( index_index)
636+ } = IndexEntry :: DUMMY ;
623637 inner. used -= 1 ;
624638 let removed = slot. take ( ) ;
625639 Ok ( ControlFlow :: Break ( removed) )
@@ -647,7 +661,10 @@ impl<T: Clone> Dict<T> {
647661 }
648662 } ;
649663 inner. used -= 1 ;
650- * unsafe { inner. indices . get_unchecked_mut ( entry. index ) } = IndexEntry :: DUMMY ;
664+ * unsafe {
665+ // entry.index always refers valid index
666+ inner. indices . get_unchecked_mut ( entry. index )
667+ } = IndexEntry :: DUMMY ;
651668 Some ( ( entry. key , entry. value ) )
652669 }
653670
0 commit comments