@@ -2787,15 +2787,28 @@ impl<T> [T] {
27872787 where
27882788 F : FnMut ( & ' a T ) -> Ordering ,
27892789 {
2790+ if T :: IS_ZST {
2791+ let res = if self . len ( ) == 0 {
2792+ Err ( 0 )
2793+ } else {
2794+ match f ( & self [ 0 ] ) {
2795+ Less => Err ( self . len ( ) ) ,
2796+ Equal => Ok ( 0 ) ,
2797+ Greater => Err ( 0 ) ,
2798+ }
2799+ } ;
2800+ return res;
2801+ }
27902802 // INVARIANTS:
2791- // - 0 <= left <= left + size = right <= self.len()
2803+ // - 0 <= left <= right <= self.len()
27922804 // - f returns Less for everything in self[..left]
27932805 // - f returns Greater for everything in self[right..]
2794- let mut size = self . len ( ) ;
2806+ let mut right = self . len ( ) ;
27952807 let mut left = 0 ;
2796- let mut right = size;
27972808 while left < right {
2798- let mid = left + size / 2 ;
2809+ // This is an okay way to compute the mean because left and right are
2810+ // <= isize::MAX so the addition won't overflow
2811+ let mid = ( left + right) / 2 ;
27992812
28002813 // SAFETY: the while condition means `size` is strictly positive, so
28012814 // `size/2 < size`. Thus `left + size/2 < left + size`, which
@@ -2807,19 +2820,16 @@ impl<T> [T] {
28072820 // fewer branches and instructions than if/else or matching on
28082821 // cmp::Ordering.
28092822 // This is x86 asm for u8: https://rust.godbolt.org/z/698eYffTx.
2823+
28102824 left = if cmp == Less { mid + 1 } else { left } ;
28112825 right = if cmp == Greater { mid } else { right } ;
28122826 if cmp == Equal {
28132827 // SAFETY: same as the `get_unchecked` above
28142828 unsafe { hint:: assert_unchecked ( mid < self . len ( ) ) } ;
28152829 return Ok ( mid) ;
28162830 }
2817-
2818- size = right - left;
28192831 }
2820-
2821- // SAFETY: directly true from the overall invariant.
2822- // Note that this is `<=`, unlike the assume in the `Ok` path.
2832+ // SAFETY: yolo
28232833 unsafe { hint:: assert_unchecked ( left <= self . len ( ) ) } ;
28242834 Err ( left)
28252835 }
0 commit comments