@@ -2787,14 +2787,16 @@ impl<T> [T] {
2787
2787
where
2788
2788
F : FnMut ( & ' a T ) -> Ordering ,
2789
2789
{
2790
+ if self . len ( ) == 0 {
2791
+ return Err ( 0 ) ;
2792
+ }
2790
2793
// INVARIANTS:
2791
- // - 0 <= left <= left + size = right <= self.len()
2794
+ // - 0 <= left <= left + size <= self.len()
2792
2795
// - f returns Less for everything in self[..left]
2793
- // - f returns Greater for everything in self[right ..]
2796
+ // - f returns Greater for everything in self[left + size ..]
2794
2797
let mut size = self . len ( ) ;
2795
2798
let mut left = 0 ;
2796
- let mut right = size;
2797
- while left < right {
2799
+ while size > 1 {
2798
2800
let mid = left + size / 2 ;
2799
2801
2800
2802
// SAFETY: the while condition means `size` is strictly positive, so
@@ -2807,21 +2809,21 @@ impl<T> [T] {
2807
2809
// fewer branches and instructions than if/else or matching on
2808
2810
// cmp::Ordering.
2809
2811
// 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 } ;
2812
+
2813
+ left = if cmp == Less { mid } else { left } ;
2814
+ size = if cmp == Greater { size / 2 } else { size - size / 2 } ;
2812
2815
if cmp == Equal {
2813
2816
// SAFETY: same as the `get_unchecked` above
2814
2817
unsafe { hint:: assert_unchecked ( mid < self . len ( ) ) } ;
2815
2818
return Ok ( mid) ;
2816
2819
}
2817
-
2818
- size = right - left;
2819
2820
}
2820
-
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)
2821
+ // SAFETY: allowed per the invariants
2822
+ let cmp = f ( unsafe { self . get_unchecked ( left) } ) ;
2823
+ let res_idx = if cmp == Less { left + 1 } else { left } ;
2824
+ // SAFETY: invariants guarantee that this is in bounds
2825
+ unsafe { hint:: assert_unchecked ( res_idx <= self . len ( ) ) } ;
2826
+ if cmp == Equal { Ok ( res_idx) } else { Err ( res_idx) }
2825
2827
}
2826
2828
2827
2829
/// Binary searches this slice with a key extraction function.
0 commit comments