@@ -558,17 +558,16 @@ use crate::panicking::{panic, panic_str};
558558use crate :: pin:: Pin ;
559559use crate :: {
560560 cmp, convert, hint, mem,
561- num:: NonZero ,
562561 ops:: { self , ControlFlow , Deref , DerefMut } ,
563562 slice,
564563} ;
565564
566565/// The `Option` type. See [the module level documentation](self) for more.
567- #[ derive( Copy , PartialOrd , Eq , Ord , Debug , Hash ) ]
566+ #[ derive( Copy , Eq , Debug , Hash ) ]
568567#[ rustc_diagnostic_item = "Option" ]
569568#[ lang = "Option" ]
570569#[ stable( feature = "rust1" , since = "1.0.0" ) ]
571- #[ allow( clippy:: derived_hash_with_manual_eq) ] // PartialEq is specialized
570+ #[ allow( clippy:: derived_hash_with_manual_eq) ] // PartialEq is manually implemented equivalently
572571pub enum Option < T > {
573572 /// No value.
574573 #[ lang = "None" ]
@@ -2146,83 +2145,52 @@ impl<'a, T> From<&'a mut Option<T>> for Option<&'a mut T> {
21462145 }
21472146}
21482147
2148+ // Ideally, LLVM should be able to optimize our derive code to this.
2149+ // Once https://github.com/llvm/llvm-project/issues/52622 is fixed, we can
2150+ // go back to deriving `PartialEq`.
21492151#[ stable( feature = "rust1" , since = "1.0.0" ) ]
21502152impl < T > crate :: marker:: StructuralPartialEq for Option < T > { }
21512153#[ stable( feature = "rust1" , since = "1.0.0" ) ]
21522154impl < T : PartialEq > PartialEq for Option < T > {
21532155 #[ inline]
21542156 fn eq ( & self , other : & Self ) -> bool {
2155- SpecOptionPartialEq :: eq ( self , other)
2156- }
2157- }
2158-
2159- /// This specialization trait is a workaround for LLVM not currently (2023-01)
2160- /// being able to optimize this itself, even though Alive confirms that it would
2161- /// be legal to do so: <https://github.com/llvm/llvm-project/issues/52622>
2162- ///
2163- /// Once that's fixed, `Option` should go back to deriving `PartialEq`, as
2164- /// it used to do before <https://github.com/rust-lang/rust/pull/103556>.
2165- #[ unstable( feature = "spec_option_partial_eq" , issue = "none" , reason = "exposed only for rustc" ) ]
2166- #[ doc( hidden) ]
2167- pub trait SpecOptionPartialEq : Sized {
2168- fn eq ( l : & Option < Self > , other : & Option < Self > ) -> bool ;
2169- }
2170-
2171- #[ unstable( feature = "spec_option_partial_eq" , issue = "none" , reason = "exposed only for rustc" ) ]
2172- impl < T : PartialEq > SpecOptionPartialEq for T {
2173- #[ inline]
2174- default fn eq ( l : & Option < T > , r : & Option < T > ) -> bool {
2175- match ( l, r) {
2157+ // Spelling out the cases explicitly optimizes better than
2158+ // `_ => false`
2159+ match ( self , other) {
21762160 ( Some ( l) , Some ( r) ) => * l == * r,
2161+ ( Some ( _) , None ) => false ,
2162+ ( None , Some ( _) ) => false ,
21772163 ( None , None ) => true ,
2178- _ => false ,
21792164 }
21802165 }
21812166}
21822167
2183- macro_rules! non_zero_option {
2184- ( $( #[ $stability: meta] $NZ: ty; ) + ) => {
2185- $(
2186- #[ $stability]
2187- impl SpecOptionPartialEq for $NZ {
2188- #[ inline]
2189- fn eq( l: & Option <Self >, r: & Option <Self >) -> bool {
2190- l. map( Self :: get) . unwrap_or( 0 ) == r. map( Self :: get) . unwrap_or( 0 )
2191- }
2192- }
2193- ) +
2194- } ;
2195- }
2196-
2197- non_zero_option ! {
2198- #[ stable( feature = "nonzero" , since = "1.28.0" ) ] NonZero <u8 >;
2199- #[ stable( feature = "nonzero" , since = "1.28.0" ) ] NonZero <u16 >;
2200- #[ stable( feature = "nonzero" , since = "1.28.0" ) ] NonZero <u32 >;
2201- #[ stable( feature = "nonzero" , since = "1.28.0" ) ] NonZero <u64 >;
2202- #[ stable( feature = "nonzero" , since = "1.28.0" ) ] NonZero <u128 >;
2203- #[ stable( feature = "nonzero" , since = "1.28.0" ) ] NonZero <usize >;
2204- #[ stable( feature = "signed_nonzero" , since = "1.34.0" ) ] NonZero <i8 >;
2205- #[ stable( feature = "signed_nonzero" , since = "1.34.0" ) ] NonZero <i16 >;
2206- #[ stable( feature = "signed_nonzero" , since = "1.34.0" ) ] NonZero <i32 >;
2207- #[ stable( feature = "signed_nonzero" , since = "1.34.0" ) ] NonZero <i64 >;
2208- #[ stable( feature = "signed_nonzero" , since = "1.34.0" ) ] NonZero <i128 >;
2209- #[ stable( feature = "signed_nonzero" , since = "1.34.0" ) ] NonZero <isize >;
2210- }
2211-
2212- #[ stable( feature = "nonnull" , since = "1.25.0" ) ]
2213- impl < T > SpecOptionPartialEq for crate :: ptr:: NonNull < T > {
2168+ // Manually implementing here somewhat improves codegen for
2169+ // https://github.com/rust-lang/rust/issues/49892, although still
2170+ // not optimal.
2171+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
2172+ impl < T : PartialOrd > PartialOrd for Option < T > {
22142173 #[ inline]
2215- fn eq ( l : & Option < Self > , r : & Option < Self > ) -> bool {
2216- l. map ( Self :: as_ptr) . unwrap_or_else ( || crate :: ptr:: null_mut ( ) )
2217- == r. map ( Self :: as_ptr) . unwrap_or_else ( || crate :: ptr:: null_mut ( ) )
2174+ fn partial_cmp ( & self , other : & Self ) -> Option < cmp:: Ordering > {
2175+ match ( self , other) {
2176+ ( Some ( l) , Some ( r) ) => l. partial_cmp ( r) ,
2177+ ( Some ( _) , None ) => Some ( cmp:: Ordering :: Greater ) ,
2178+ ( None , Some ( _) ) => Some ( cmp:: Ordering :: Less ) ,
2179+ ( None , None ) => Some ( cmp:: Ordering :: Equal ) ,
2180+ }
22182181 }
22192182}
22202183
22212184#[ stable( feature = "rust1" , since = "1.0.0" ) ]
2222- impl SpecOptionPartialEq for cmp :: Ordering {
2185+ impl < T : Ord > Ord for Option < T > {
22232186 #[ inline]
2224- fn eq ( l : & Option < Self > , r : & Option < Self > ) -> bool {
2225- l. map_or ( 2 , |x| x as i8 ) == r. map_or ( 2 , |x| x as i8 )
2187+ fn cmp ( & self , other : & Self ) -> cmp:: Ordering {
2188+ match ( self , other) {
2189+ ( Some ( l) , Some ( r) ) => l. cmp ( r) ,
2190+ ( Some ( _) , None ) => cmp:: Ordering :: Greater ,
2191+ ( None , Some ( _) ) => cmp:: Ordering :: Less ,
2192+ ( None , None ) => cmp:: Ordering :: Equal ,
2193+ }
22262194 }
22272195}
22282196
0 commit comments