}
-// Use macro to be generic over const/mut
-macro_rules! slice_offset {
+// Use macros to be generic over const/mut
+//
+// They require non-negative `$by` because otherwise the expression
+// `(ptr as usize + $by)` would interpret `-1` as `usize::MAX` (and
+// thus trigger a panic when overflow checks are on).
+
+// Use this to do `$ptr + $by`, where `$by` is non-negative.
+macro_rules! slice_add_offset {
($ptr:expr, $by:expr) => {{
let ptr = $ptr;
if size_from_ptr(ptr) == 0 {
}};
}
+// Use this to do `$ptr - $by`, where `$by` is non-negative.
+macro_rules! slice_sub_offset {
+ ($ptr:expr, $by:expr) => {{
+ let ptr = $ptr;
+ if size_from_ptr(ptr) == 0 {
+ transmute(ptr as usize - $by)
+ } else {
+ ptr.offset(-$by)
+ }
+ }};
+}
+
macro_rules! slice_ref {
($ptr:expr) => {{
let ptr = $ptr;
None
} else {
let old = self.ptr;
- self.ptr = slice_offset!(self.ptr, 1);
+ self.ptr = slice_add_offset!(self.ptr, 1);
Some(slice_ref!(old))
}
}
if self.end == self.ptr {
None
} else {
- self.end = slice_offset!(self.end, -1);
+ self.end = slice_sub_offset!(self.end, 1);
Some(slice_ref!(self.end))
}
}
fn iter_nth(&mut self, n: usize) -> Option<&'a T> {
match self.as_slice().get(n) {
Some(elem_ref) => unsafe {
- self.ptr = slice_offset!(elem_ref as *const _, 1);
+ self.ptr = slice_add_offset!(elem_ref as *const _, 1);
Some(slice_ref!(elem_ref))
},
None => {
fn iter_nth(&mut self, n: usize) -> Option<&'a mut T> {
match make_mut_slice!(T => &'a mut [T]: self.ptr, self.end).get_mut(n) {
Some(elem_ref) => unsafe {
- self.ptr = slice_offset!(elem_ref as *mut _, 1);
+ self.ptr = slice_add_offset!(elem_ref as *mut _, 1);
Some(slice_ref!(elem_ref))
},
None => {