fix issues pointed out in review

This commit is contained in:
The8472 2021-07-13 23:13:27 +02:00
parent 6654a0bbdc
commit ffd7ade203
3 changed files with 41 additions and 18 deletions

View File

@ -164,18 +164,19 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
#[inline] #[inline]
fn advance_by(&mut self, n: usize) -> Result<(), usize> { fn advance_by(&mut self, n: usize) -> Result<(), usize> {
let step_size = self.len().min(n); let step_size = self.len().min(n);
let to_drop = ptr::slice_from_raw_parts_mut(self.ptr as *mut T, step_size);
if mem::size_of::<T>() == 0 { if mem::size_of::<T>() == 0 {
// SAFETY: due to unchecked casts of unsigned amounts to signed offsets the wraparound // SAFETY: due to unchecked casts of unsigned amounts to signed offsets the wraparound
// effectively results in unsigned pointers representing positions 0..usize::MAX, // effectively results in unsigned pointers representing positions 0..usize::MAX,
// which is valid for ZSTs. // which is valid for ZSTs.
self.ptr = unsafe { arith_offset(self.ptr as *const i8, step_size as isize) as *mut T } self.ptr = unsafe { arith_offset(self.ptr as *const i8, step_size as isize) as *mut T }
} else { } else {
let to_drop = ptr::slice_from_raw_parts_mut(self.ptr as *mut T, step_size);
// SAFETY: the min() above ensures that step_size is in bounds // SAFETY: the min() above ensures that step_size is in bounds
unsafe { self.ptr = unsafe { self.ptr.add(step_size) };
self.ptr = self.ptr.add(step_size); }
ptr::drop_in_place(to_drop); // SAFETY: the min() above ensures that step_size is in bounds
} unsafe {
ptr::drop_in_place(to_drop);
} }
if step_size < n { if step_size < n {
return Err(step_size); return Err(step_size);
@ -237,11 +238,11 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
} else { } else {
// SAFETY: same as for advance_by() // SAFETY: same as for advance_by()
self.end = unsafe { self.end.offset(step_size.wrapping_neg() as isize) }; self.end = unsafe { self.end.offset(step_size.wrapping_neg() as isize) };
let to_drop = ptr::slice_from_raw_parts_mut(self.end as *mut T, step_size); }
// SAFETY: same as for advance_by() let to_drop = ptr::slice_from_raw_parts_mut(self.end as *mut T, step_size);
unsafe { // SAFETY: same as for advance_by()
ptr::drop_in_place(to_drop); unsafe {
} ptr::drop_in_place(to_drop);
} }
if step_size < n { if step_size < n {
return Err(step_size); return Err(step_size);

View File

@ -412,8 +412,9 @@ where
self.frontiter = None; self.frontiter = None;
if let Some(ref mut back) = self.backiter { if let Some(ref mut back) = self.backiter {
if let Err(advanced) = back.advance_by(rem) { match back.advance_by(rem) {
rem -= advanced ret @ Ok(_) => return ret,
Err(advanced) => rem -= advanced,
} }
} }

View File

@ -116,14 +116,35 @@ where
} }
#[inline] #[inline]
#[rustc_inherit_overflow_checks]
fn advance_by(&mut self, n: usize) -> Result<(), usize> { fn advance_by(&mut self, n: usize) -> Result<(), usize> {
if self.n >= n { let mut rem = n;
self.n -= n;
return Ok(()); let step_one = self.n.saturating_add(rem);
match self.iter.advance_by(step_one) {
Ok(_) => {
rem -= step_one - self.n;
self.n = 0;
}
Err(advanced) => {
let advanced_without_skip = advanced.saturating_sub(self.n);
self.n = self.n.saturating_sub(advanced);
return Err(advanced_without_skip);
}
} }
let rem = n - self.n;
self.n = 0; // step_one calculation may have saturated
self.iter.advance_by(rem) if unlikely(rem > 0) {
return match self.iter.advance_by(rem) {
ret @ Ok(_) => ret,
Err(advanced) => {
rem -= advanced;
Err(n - rem)
}
};
}
Ok(())
} }
} }