@@ -631,8 +631,14 @@ fn size_from_ptr<T>(_: *const T) -> usize {
631631}
632632
633633
634- // Use macro to be generic over const/mut
635- macro_rules! slice_offset {
634+ // Use macros to be generic over const/mut
635+ //
636+ // They require non-negative `$by` because otherwise the expression
637+ // `(ptr as usize + $by)` would interpret `-1` as `usize::MAX` (and
638+ // thus trigger a panic when overflow checks are on).
639+
640+ // Use this to do `$ptr + $by`, where `$by` is non-negative.
641+ macro_rules! slice_add_offset {
636642 ( $ptr: expr, $by: expr) => { {
637643 let ptr = $ptr;
638644 if size_from_ptr( ptr) == 0 {
@@ -643,6 +649,18 @@ macro_rules! slice_offset {
643649 } } ;
644650}
645651
652+ // Use this to do `$ptr - $by`, where `$by` is non-negative.
653+ macro_rules! slice_sub_offset {
654+ ( $ptr: expr, $by: expr) => { {
655+ let ptr = $ptr;
656+ if size_from_ptr( ptr) == 0 {
657+ transmute( ptr as usize - $by)
658+ } else {
659+ ptr. offset( -$by)
660+ }
661+ } } ;
662+ }
663+
646664macro_rules! slice_ref {
647665 ( $ptr: expr) => { {
648666 let ptr = $ptr;
@@ -672,7 +690,7 @@ macro_rules! iterator {
672690 None
673691 } else {
674692 let old = self . ptr;
675- self . ptr = slice_offset !( self . ptr, 1 ) ;
693+ self . ptr = slice_add_offset !( self . ptr, 1 ) ;
676694 Some ( slice_ref!( old) )
677695 }
678696 }
@@ -714,7 +732,7 @@ macro_rules! iterator {
714732 if self . end == self . ptr {
715733 None
716734 } else {
717- self . end = slice_offset !( self . end, - 1 ) ;
735+ self . end = slice_sub_offset !( self . end, 1 ) ;
718736 Some ( slice_ref!( self . end) )
719737 }
720738 }
@@ -816,7 +834,7 @@ impl<'a, T> Iter<'a, T> {
816834 fn iter_nth ( & mut self , n : usize ) -> Option < & ' a T > {
817835 match self . as_slice ( ) . get ( n) {
818836 Some ( elem_ref) => unsafe {
819- self . ptr = slice_offset ! ( elem_ref as * const _, 1 ) ;
837+ self . ptr = slice_add_offset ! ( elem_ref as * const _, 1 ) ;
820838 Some ( slice_ref ! ( elem_ref) )
821839 } ,
822840 None => {
@@ -959,7 +977,7 @@ impl<'a, T> IterMut<'a, T> {
959977 fn iter_nth ( & mut self , n : usize ) -> Option < & ' a mut T > {
960978 match make_mut_slice ! ( T => & ' a mut [ T ] : self . ptr, self . end) . get_mut ( n) {
961979 Some ( elem_ref) => unsafe {
962- self . ptr = slice_offset ! ( elem_ref as * mut _, 1 ) ;
980+ self . ptr = slice_add_offset ! ( elem_ref as * mut _, 1 ) ;
963981 Some ( slice_ref ! ( elem_ref) )
964982 } ,
965983 None => {
0 commit comments