Skip to content

Commit 7c03be7

Browse files
committed
Address comments.
1. Use next_back for last. 2. Use slices for computing nth. It might be possible to use the same code for both the mut/const case but I don't know how that will play with compiler optimizations.
1 parent de8c79a commit 7c03be7

File tree

1 file changed

+42
-42
lines changed

1 file changed

+42
-42
lines changed

src/libcore/slice.rs

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -674,51 +674,13 @@ macro_rules! iterator {
674674

675675
#[inline]
676676
fn nth(&mut self, n: usize) -> Option<$elem> {
677-
// could be implemented with slices, but this avoids bounds checks
678-
unsafe {
679-
::intrinsics::assume(!self.ptr.is_null());
680-
::intrinsics::assume(!self.end.is_null());
681-
// There should be some way to use offset and optimize this to LEA but I don't
682-
// know how to do that AND detect overflow...
683-
let size = mem::size_of::<T>();
684-
if size == 0 {
685-
if let Some(new_ptr) = (self.ptr as usize).checked_add(n) {
686-
if new_ptr < (self.end as usize) {
687-
self.ptr = transmute(new_ptr + 1);
688-
return Some(&mut *(1 as *mut _))
689-
}
690-
}
691-
} else {
692-
if let Some(new_ptr) = n.checked_mul(size).and_then(|offset| {
693-
(self.ptr as usize).checked_add(offset)
694-
}) {
695-
if new_ptr < (self.end as usize) {
696-
self.ptr = transmute(new_ptr + size);
697-
return Some(transmute(new_ptr))
698-
}
699-
}
700-
}
701-
None
702-
}
677+
// Call helper method. Can't put the definition here because mut versus const.
678+
self.iter_nth(n)
703679
}
704680

705681
#[inline]
706-
fn last(self) -> Option<$elem> {
707-
// We could just call next_back but this avoids the memory write.
708-
unsafe {
709-
::intrinsics::assume(!self.ptr.is_null());
710-
::intrinsics::assume(!self.end.is_null());
711-
if self.end == self.ptr {
712-
None
713-
} else {
714-
if mem::size_of::<T>() == 0 {
715-
// Use a non-null pointer value
716-
Some(&mut *(1 as *mut _))
717-
} else {
718-
Some(transmute(self.end.offset(-1)))
719-
}
720-
}
721-
}
682+
fn last(mut self) -> Option<$elem> {
683+
self.next_back()
722684
}
723685
}
724686

@@ -839,6 +801,25 @@ impl<'a, T> Iter<'a, T> {
839801
pub fn as_slice(&self) -> &'a [T] {
840802
make_slice!(T => &'a [T]: self.ptr, self.end)
841803
}
804+
805+
// Helper function for Iter::nth
806+
fn iter_nth(&mut self, n: usize) -> Option<&'a T> {
807+
unsafe {
808+
match self.as_slice().get(n) {
809+
Some(elem_ref) => if mem::size_of::<T>() == 0 {
810+
self.ptr = transmute((elem_ref as *const T) as usize + 1);
811+
Some(& *(1 as *const T))
812+
} else {
813+
self.ptr = (elem_ref as *const T).offset(1);
814+
Some(elem_ref)
815+
},
816+
None => {
817+
self.ptr = self.end;
818+
None
819+
}
820+
}
821+
}
822+
}
842823
}
843824

844825
iterator!{struct Iter -> *const T, &'a T}
@@ -968,6 +949,25 @@ impl<'a, T> IterMut<'a, T> {
968949
pub fn into_slice(self) -> &'a mut [T] {
969950
make_mut_slice!(T => &'a mut [T]: self.ptr, self.end)
970951
}
952+
953+
// Helper function for IterMut::nth
954+
fn iter_nth(&mut self, n: usize) -> Option<&'a mut T> {
955+
unsafe {
956+
match make_mut_slice!(T => &'a mut [T]: self.ptr, self.end).get_mut(n) {
957+
Some(elem_ref) => if mem::size_of::<T>() == 0 {
958+
self.ptr = transmute((elem_ref as *mut T) as usize + 1);
959+
Some(&mut *(1 as *mut T))
960+
} else {
961+
self.ptr = (elem_ref as *mut T).offset(1);
962+
Some(elem_ref)
963+
},
964+
None => {
965+
self.ptr = self.end;
966+
None
967+
}
968+
}
969+
}
970+
}
971971
}
972972

973973
iterator!{struct IterMut -> *mut T, &'a mut T}

0 commit comments

Comments
 (0)