@@ -2788,13 +2788,12 @@ impl<T> [T] {
27882788 F : FnMut ( & ' a T ) -> Ordering ,
27892789 {
27902790 // INVARIANTS:
2791- // - 0 <= left <= left + size = right <= self.len()
2791+ // - 0 <= left <= left + size <= self.len()
27922792 // - f returns Less for everything in self[..left]
2793- // - f returns Greater for everything in self[right ..]
2793+ // - f returns Greater for everything in self[left + size ..]
27942794 let mut size = self . len ( ) ;
27952795 let mut left = 0 ;
2796- let mut right = size;
2797- while left < right {
2796+ while size > 1 {
27982797 let mid = left + size / 2 ;
27992798
28002799 // SAFETY: the while condition means `size` is strictly positive, so
@@ -2807,21 +2806,24 @@ impl<T> [T] {
28072806 // fewer branches and instructions than if/else or matching on
28082807 // cmp::Ordering.
28092808 // This is x86 asm for u8: https://rust.godbolt.org/z/698eYffTx.
2810- left = if cmp == Less { mid + 1 } else { left } ;
2811- right = if cmp == Greater { mid } else { right } ;
2809+
2810+ left = if cmp == Less { mid } else { left } ;
2811+ size = if cmp == Greater { size / 2 } else { size - size / 2 } ;
28122812 if cmp == Equal {
28132813 // SAFETY: same as the `get_unchecked` above
28142814 unsafe { hint:: assert_unchecked ( mid < self . len ( ) ) } ;
28152815 return Ok ( mid) ;
28162816 }
2817-
2818- size = right - left;
28192817 }
28202818
2821- // SAFETY: directly true from the overall invariant.
2822- // Note that this is `<=`, unlike the assume in the `Ok` path.
2823- unsafe { hint:: assert_unchecked ( left <= self . len ( ) ) } ;
2824- Err ( left)
2819+ if size == 0 {
2820+ Err ( left)
2821+ } else {
2822+ // SAFETY: allowed per the invariants
2823+ let cmp = f ( unsafe { self . get_unchecked ( left) } ) ;
2824+ let res_idx = if cmp == Less { left + 1 } else { left } ;
2825+ if cmp == Equal { Ok ( res_idx) } else { Err ( res_idx) }
2826+ }
28252827 }
28262828
28272829 /// Binary searches this slice with a key extraction function.
0 commit comments