From 8e8fd02b272bf8ca8e4c8f4d20552ca26a468a80 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Thu, 27 Oct 2022 13:40:45 +0100 Subject: [PATCH] Specialize PartialEq for Option and Option --- library/core/src/option.rs | 68 ++++++++++++++++++++++++++- src/test/codegen/option-nonzero-eq.rs | 34 ++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 src/test/codegen/option-nonzero-eq.rs diff --git a/library/core/src/option.rs b/library/core/src/option.rs index a81dbc6924f..e462f840fda 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -512,7 +512,7 @@ }; /// The `Option` type. See [the module level documentation](self) for more. -#[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] +#[derive(Copy, PartialOrd, Eq, Ord, Debug, Hash)] #[rustc_diagnostic_item = "Option"] #[stable(feature = "rust1", since = "1.0.0")] pub enum Option { @@ -2035,6 +2035,72 @@ fn from(o: &'a mut Option) -> Option<&'a mut T> { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl crate::marker::StructuralPartialEq for Option {} +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for Option { + #[inline] + fn eq(&self, other: &Self) -> bool { + SpecOptionPartialEq::eq(self, other) + } +} + +#[unstable(feature = "spec_option_partial_eq", issue = "none")] +#[doc(hidden)] +pub trait SpecOptionPartialEq: Sized { + fn eq(l: &Option, other: &Option) -> bool; +} + +#[unstable(feature = "spec_option_partial_eq", issue = "none")] +impl SpecOptionPartialEq for T { + #[inline] + default fn eq(l: &Option, r: &Option) -> bool { + match (l, r) { + (Some(l), Some(r)) => *l == *r, + (None, None) => true, + _ => false, + } + } +} + +macro_rules! non_zero_option { + ( $( #[$stability: meta] $NZ:ty; )+ ) => { + $( + #[$stability] + impl SpecOptionPartialEq for $NZ { + #[inline] + fn eq(l: &Option, r: &Option) -> bool { + l.map(Self::get).unwrap_or(0) == r.map(Self::get).unwrap_or(0) + } + } + )+ + }; +} + +non_zero_option! { + #[stable(feature = "nonzero", since = "1.28.0")] crate::num::NonZeroU8; + #[stable(feature = "nonzero", since = "1.28.0")] crate::num::NonZeroU16; + #[stable(feature = "nonzero", since = "1.28.0")] crate::num::NonZeroU32; + #[stable(feature = "nonzero", since = "1.28.0")] crate::num::NonZeroU64; + #[stable(feature = "nonzero", since = "1.28.0")] crate::num::NonZeroU128; + #[stable(feature = "nonzero", since = "1.28.0")] crate::num::NonZeroUsize; + #[stable(feature = "signed_nonzero", since = "1.34.0")] crate::num::NonZeroI8; + #[stable(feature = "signed_nonzero", since = "1.34.0")] crate::num::NonZeroI16; + #[stable(feature = "signed_nonzero", since = "1.34.0")] crate::num::NonZeroI32; + #[stable(feature = "signed_nonzero", since = "1.34.0")] crate::num::NonZeroI64; + #[stable(feature = "signed_nonzero", since = "1.34.0")] crate::num::NonZeroI128; + #[stable(feature = "signed_nonzero", since = "1.34.0")] crate::num::NonZeroIsize; +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl SpecOptionPartialEq for crate::ptr::NonNull { + #[inline] + fn eq(l: &Option, r: &Option) -> bool { + l.map(Self::as_ptr).unwrap_or_else(|| crate::ptr::null_mut()) + == r.map(Self::as_ptr).unwrap_or_else(|| crate::ptr::null_mut()) + } +} + ///////////////////////////////////////////////////////////////////////////// // The Option Iterators ///////////////////////////////////////////////////////////////////////////// diff --git a/src/test/codegen/option-nonzero-eq.rs b/src/test/codegen/option-nonzero-eq.rs new file mode 100644 index 00000000000..598dcc19b49 --- /dev/null +++ b/src/test/codegen/option-nonzero-eq.rs @@ -0,0 +1,34 @@ +// compile-flags: -O -Zmerge-functions=disabled + +#![crate_type = "lib"] + +extern crate core; +use core::num::{NonZeroU32, NonZeroI64}; +use core::ptr::NonNull; + +// CHECK-lABEL: @non_zero_eq +#[no_mangle] +pub fn non_zero_eq(l: Option, r: Option) -> bool { + // CHECK: start: + // CHECK-NEXT: icmp eq i32 + // CHECK-NEXT: ret i1 + l == r +} + +// CHECK-lABEL: @non_zero_signed_eq +#[no_mangle] +pub fn non_zero_signed_eq(l: Option, r: Option) -> bool { + // CHECK: start: + // CHECK-NEXT: icmp eq i64 + // CHECK-NEXT: ret i1 + l == r +} + +// CHECK-lABEL: @non_null_eq +#[no_mangle] +pub fn non_null_eq(l: Option>, r: Option>) -> bool { + // CHECK: start: + // CHECK-NEXT: icmp eq {{(i8\*|ptr)}} + // CHECK-NEXT: ret i1 + l == r +}