@@ -771,13 +771,11 @@ pub trait RangeBounds<T: ?Sized> {
771771/// # Examples 
772772/// 
773773/// ``` 
774- /// # fn main() { 
775774/// use std::ops::Bound::*; 
776775/// use std::ops::RangeBounds; 
777776/// 
778777/// assert_eq!((..10).start_bound(), Unbounded); 
779778/// assert_eq!((3..10).start_bound(), Included(&3)); 
780- /// # } 
781779/// ``` 
782780#[ stable( feature = "collections_range" ,  since = "1.28.0" ) ]  
783781    fn  start_bound ( & self )  -> Bound < & T > ; 
@@ -789,13 +787,11 @@ pub trait RangeBounds<T: ?Sized> {
789787/// # Examples 
790788/// 
791789/// ``` 
792- /// # fn main() { 
793790/// use std::ops::Bound::*; 
794791/// use std::ops::RangeBounds; 
795792/// 
796793/// assert_eq!((3..).end_bound(), Unbounded); 
797794/// assert_eq!((3..10).end_bound(), Excluded(&10)); 
798- /// # } 
799795/// ``` 
800796#[ stable( feature = "collections_range" ,  since = "1.28.0" ) ]  
801797    fn  end_bound ( & self )  -> Bound < & T > ; 
@@ -829,6 +825,71 @@ pub trait RangeBounds<T: ?Sized> {
829825            Unbounded  => true , 
830826        } ) 
831827    } 
828+ 
829+     /// Returns `true` if the range contains no items. 
830+ /// One-sided ranges (`RangeFrom`, etc) always return `true`. 
831+ /// 
832+ /// # Examples 
833+ /// 
834+ /// ``` 
835+ /// #![feature(range_bounds_is_empty)] 
836+ /// use std::ops::RangeBounds; 
837+ /// 
838+ /// assert!(!(3..).is_empty()); 
839+ /// assert!(!(..2).is_empty()); 
840+ /// assert!(!RangeBounds::is_empty(&(3..5))); 
841+ /// assert!( RangeBounds::is_empty(&(3..3))); 
842+ /// assert!( RangeBounds::is_empty(&(3..2))); 
843+ /// ``` 
844+ /// 
845+ /// The range is empty if either side is incomparable: 
846+ /// 
847+ /// ``` 
848+ /// #![feature(range_bounds_is_empty)] 
849+ /// use std::ops::RangeBounds; 
850+ /// 
851+ /// assert!(!RangeBounds::is_empty(&(3.0..5.0))); 
852+ /// assert!( RangeBounds::is_empty(&(3.0..f32::NAN))); 
853+ /// assert!( RangeBounds::is_empty(&(f32::NAN..5.0))); 
854+ /// ``` 
855+ /// 
856+ /// But never empty is either side is unbounded: 
857+ /// 
858+ /// ``` 
859+ /// #![feature(range_bounds_is_empty)] 
860+ /// use std::ops::RangeBounds; 
861+ /// 
862+ /// assert!(!(..0).is_empty()); 
863+ /// assert!(!(i32::MAX..).is_empty()); 
864+ /// assert!(!RangeBounds::<u8>::is_empty(&(..))); 
865+ /// ``` 
866+ /// 
867+ /// `(Excluded(a), Excluded(b))` is only empty if `a >= b`: 
868+ /// 
869+ /// ``` 
870+ /// #![feature(range_bounds_is_empty)] 
871+ /// use std::ops::Bound::*; 
872+ /// use std::ops::RangeBounds; 
873+ /// 
874+ /// assert!(!(Excluded(1), Excluded(3)).is_empty()); 
875+ /// assert!(!(Excluded(1), Excluded(2)).is_empty()); 
876+ /// assert!( (Excluded(1), Excluded(1)).is_empty()); 
877+ /// assert!( (Excluded(2), Excluded(1)).is_empty()); 
878+ /// assert!( (Excluded(3), Excluded(1)).is_empty()); 
879+ /// ``` 
880+ #[ unstable( feature = "range_bounds_is_empty" ,  issue = "137300" ) ]  
881+     fn  is_empty ( & self )  -> bool 
882+     where 
883+         T :  PartialOrd , 
884+     { 
885+         !match  ( self . start_bound ( ) ,  self . end_bound ( ) )  { 
886+             ( Unbounded ,  _)  | ( _,  Unbounded )  => true , 
887+             ( Included ( start) ,  Excluded ( end) ) 
888+             | ( Excluded ( start) ,  Included ( end) ) 
889+             | ( Excluded ( start) ,  Excluded ( end) )  => start < end, 
890+             ( Included ( start) ,  Included ( end) )  => start <= end, 
891+         } 
892+     } 
832893} 
833894
834895/// Used to convert a range into start and end bounds, consuming the 
@@ -845,14 +906,83 @@ pub trait IntoBounds<T>: RangeBounds<T> {
845906/// 
846907/// ``` 
847908/// #![feature(range_into_bounds)] 
848- /// 
849909/// use std::ops::Bound::*; 
850910/// use std::ops::IntoBounds; 
851911/// 
852912/// assert_eq!((0..5).into_bounds(), (Included(0), Excluded(5))); 
853913/// assert_eq!((..=7).into_bounds(), (Unbounded, Included(7))); 
854914/// ``` 
855915fn  into_bounds ( self )  -> ( Bound < T > ,  Bound < T > ) ; 
916+ 
917+     /// Compute the intersection of  `self` and `other`. 
918+ /// 
919+ /// # Examples 
920+ /// 
921+ /// ``` 
922+ /// #![feature(range_into_bounds)] 
923+ /// use std::ops::Bound::*; 
924+ /// use std::ops::IntoBounds; 
925+ /// 
926+ /// assert_eq!((3..).intersect(..5), (Included(3), Excluded(5))); 
927+ /// assert_eq!((-12..387).intersect(0..256), (Included(0), Excluded(256))); 
928+ /// assert_eq!((1..5).intersect(..), (Included(1), Excluded(5))); 
929+ /// assert_eq!((1..=9).intersect(0..10), (Included(1), Included(9))); 
930+ /// assert_eq!((7..=13).intersect(8..13), (Included(8), Excluded(13))); 
931+ /// ``` 
932+ /// 
933+ /// Combine with `is_empty` to determine if two ranges overlap. 
934+ /// 
935+ /// ``` 
936+ /// #![feature(range_into_bounds)] 
937+ /// #![feature(range_bounds_is_empty)] 
938+ /// use std::ops::{RangeBounds, IntoBounds}; 
939+ /// 
940+ /// assert!(!(3..).intersect(..5).is_empty()); 
941+ /// assert!(!(-12..387).intersect(0..256).is_empty()); 
942+ /// assert!((1..5).intersect(6..).is_empty()); 
943+ /// ``` 
944+ fn  intersect < R > ( self ,  other :  R )  -> ( Bound < T > ,  Bound < T > ) 
945+     where 
946+         Self :  Sized , 
947+         T :  Ord , 
948+         R :  Sized  + IntoBounds < T > , 
949+     { 
950+         let  ( self_start,  self_end)  = IntoBounds :: into_bounds ( self ) ; 
951+         let  ( other_start,  other_end)  = IntoBounds :: into_bounds ( other) ; 
952+ 
953+         let  start = match  ( self_start,  other_start)  { 
954+             ( Included ( a) ,  Included ( b) )  => Included ( Ord :: max ( a,  b) ) , 
955+             ( Excluded ( a) ,  Excluded ( b) )  => Excluded ( Ord :: max ( a,  b) ) , 
956+             ( Unbounded ,  Unbounded )  => Unbounded , 
957+ 
958+             ( x,  Unbounded )  | ( Unbounded ,  x)  => x, 
959+ 
960+             ( Included ( i) ,  Excluded ( e) )  | ( Excluded ( e) ,  Included ( i) )  => { 
961+                 if  i > e { 
962+                     Included ( i) 
963+                 }  else  { 
964+                     Excluded ( e) 
965+                 } 
966+             } 
967+         } ; 
968+         let  end = match  ( self_end,  other_end)  { 
969+             ( Included ( a) ,  Included ( b) )  => Included ( Ord :: min ( a,  b) ) , 
970+             ( Excluded ( a) ,  Excluded ( b) )  => Excluded ( Ord :: min ( a,  b) ) , 
971+             ( Unbounded ,  Unbounded )  => Unbounded , 
972+ 
973+             ( x,  Unbounded )  | ( Unbounded ,  x)  => x, 
974+ 
975+             ( Included ( i) ,  Excluded ( e) )  | ( Excluded ( e) ,  Included ( i) )  => { 
976+                 if  i < e { 
977+                     Included ( i) 
978+                 }  else  { 
979+                     Excluded ( e) 
980+                 } 
981+             } 
982+         } ; 
983+ 
984+         ( start,  end) 
985+     } 
856986} 
857987
858988use  self :: Bound :: { Excluded ,  Included ,  Unbounded } ; 
0 commit comments