Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
reduce repetition with macros
  • Loading branch information
hkBst committed Sep 17, 2025
commit fbc5eeb9629aa79bdc422203455221a59527432c
270 changes: 89 additions & 181 deletions library/core/src/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2069,193 +2069,101 @@ mod impls {
}
}

// & pointers
// reference types

#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<A: PointeeSized, B: PointeeSized> const PartialEq<&B> for &A
where
A: [const] PartialEq<B>,
{
#[inline]
fn eq(&self, other: &&B) -> bool {
PartialEq::eq(*self, *other)
}
// if <A as PartialEq<B>>::ne uses inline assembly or FFI, then
// this forwarding impl may be more efficient than the default impl
#[inline]
fn ne(&self, other: &&B) -> bool {
PartialEq::ne(*self, *other)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<A: PointeeSized, B: PointeeSized> const PartialOrd<&B> for &A
where
A: [const] PartialOrd<B>,
{
#[inline]
fn partial_cmp(&self, other: &&B) -> Option<Ordering> {
PartialOrd::partial_cmp(*self, *other)
}
#[inline]
fn lt(&self, other: &&B) -> bool {
PartialOrd::lt(*self, *other)
}
#[inline]
fn le(&self, other: &&B) -> bool {
PartialOrd::le(*self, *other)
}
#[inline]
fn gt(&self, other: &&B) -> bool {
PartialOrd::gt(*self, *other)
}
#[inline]
fn ge(&self, other: &&B) -> bool {
PartialOrd::ge(*self, *other)
}
#[inline]
fn __chaining_lt(&self, other: &&B) -> ControlFlow<bool> {
PartialOrd::__chaining_lt(*self, *other)
}
#[inline]
fn __chaining_le(&self, other: &&B) -> ControlFlow<bool> {
PartialOrd::__chaining_le(*self, *other)
}
#[inline]
fn __chaining_gt(&self, other: &&B) -> ControlFlow<bool> {
PartialOrd::__chaining_gt(*self, *other)
}
#[inline]
fn __chaining_ge(&self, other: &&B) -> ControlFlow<bool> {
PartialOrd::__chaining_ge(*self, *other)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<A: PointeeSized> const Ord for &A
where
A: [const] Ord,
{
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(*self, *other)
}
macro_rules! partial_eq_impl {
($(($ref_A:ty => $A:ident, $ref_B:ty => $B:ident))*) => ($(
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<$A, $B> const PartialEq<$ref_B> for $ref_A
where
$A: [const] PartialEq<$B> + PointeeSized,
$B: PointeeSized,
{
#[inline]
fn eq(&self, other: &$ref_B) -> bool {
PartialEq::eq(*self, *other)
}
// if <A as PartialEq<B>>::ne uses inline assembly or FFI, then
// this forwarding impl may be more efficient than the default impl
#[inline]
fn ne(&self, other: &$ref_B) -> bool {
PartialEq::ne(*self, *other)
}
}
)*)
}
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<A: PointeeSized> const Eq for &A where A: [const] Eq {}

// &mut pointers
partial_eq_impl!((&A => A, &B => B) (&A => A, &mut B => B) (&mut A => A, &B => B) (&mut A => A, &mut B => B));

#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<A: PointeeSized, B: PointeeSized> const PartialEq<&mut B> for &mut A
where
A: [const] PartialEq<B>,
{
#[inline]
fn eq(&self, other: &&mut B) -> bool {
PartialEq::eq(*self, *other)
}
// if <A as PartialEq<B>>::ne uses inline assembly or FFI, then
// this forwarding impl may be more efficient than the default impl
#[inline]
fn ne(&self, other: &&mut B) -> bool {
PartialEq::ne(*self, *other)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<A: PointeeSized, B: PointeeSized> const PartialOrd<&mut B> for &mut A
where
A: [const] PartialOrd<B>,
{
#[inline]
fn partial_cmp(&self, other: &&mut B) -> Option<Ordering> {
PartialOrd::partial_cmp(*self, *other)
}
#[inline]
fn lt(&self, other: &&mut B) -> bool {
PartialOrd::lt(*self, *other)
}
#[inline]
fn le(&self, other: &&mut B) -> bool {
PartialOrd::le(*self, *other)
}
#[inline]
fn gt(&self, other: &&mut B) -> bool {
PartialOrd::gt(*self, *other)
}
#[inline]
fn ge(&self, other: &&mut B) -> bool {
PartialOrd::ge(*self, *other)
}
#[inline]
fn __chaining_lt(&self, other: &&mut B) -> ControlFlow<bool> {
PartialOrd::__chaining_lt(*self, *other)
}
#[inline]
fn __chaining_le(&self, other: &&mut B) -> ControlFlow<bool> {
PartialOrd::__chaining_le(*self, *other)
}
#[inline]
fn __chaining_gt(&self, other: &&mut B) -> ControlFlow<bool> {
PartialOrd::__chaining_gt(*self, *other)
}
#[inline]
fn __chaining_ge(&self, other: &&mut B) -> ControlFlow<bool> {
PartialOrd::__chaining_ge(*self, *other)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<A: PointeeSized> const Ord for &mut A
where
A: [const] Ord,
{
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(*self, *other)
}
macro_rules! partial_ord_impl {
($(($ref_A:ty => $A:ident, $ref_B:ty => $B:ident))*) => ($(
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<$A, $B> const PartialOrd<$ref_B> for $ref_A
where
$A: [const] PartialOrd<$B> + PointeeSized,
$B: PointeeSized,
{
#[inline]
fn partial_cmp(&self, other: &$ref_B) -> Option<Ordering> {
PartialOrd::partial_cmp(*self, *other)
}
#[inline]
fn lt(&self, other: &$ref_B) -> bool {
PartialOrd::lt(*self, *other)
}
#[inline]
fn le(&self, other: &$ref_B) -> bool {
PartialOrd::le(*self, *other)
}
#[inline]
fn gt(&self, other: &$ref_B) -> bool {
PartialOrd::gt(*self, *other)
}
#[inline]
fn ge(&self, other: &$ref_B) -> bool {
PartialOrd::ge(*self, *other)
}
#[inline]
fn __chaining_lt(&self, other: &$ref_B) -> ControlFlow<bool> {
PartialOrd::__chaining_lt(*self, *other)
}
#[inline]
fn __chaining_le(&self, other: &$ref_B) -> ControlFlow<bool> {
PartialOrd::__chaining_le(*self, *other)
}
#[inline]
fn __chaining_gt(&self, other: &$ref_B) -> ControlFlow<bool> {
PartialOrd::__chaining_gt(*self, *other)
}
#[inline]
fn __chaining_ge(&self, other: &$ref_B) -> ControlFlow<bool> {
PartialOrd::__chaining_ge(*self, *other)
}
}
)*)
}
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<A: PointeeSized> const Eq for &mut A where A: [const] Eq {}

#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<A: PointeeSized, B: PointeeSized> const PartialEq<&mut B> for &A
where
A: [const] PartialEq<B>,
{
#[inline]
fn eq(&self, other: &&mut B) -> bool {
PartialEq::eq(*self, *other)
}
// if <A as PartialEq<B>>::ne uses inline assembly or FFI, then
// this forwarding impl may be more efficient than the default impl
#[inline]
fn ne(&self, other: &&mut B) -> bool {
PartialEq::ne(*self, *other)
}
}
partial_ord_impl!((&A => A, &B => B) /*(&A => A, &mut B => B) (&mut A => A, &B => B)*/ (&mut A => A, &mut B => B));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My primary objection with macros is I find deducing their invented syntax, like this, to often be confounding, unless it is a simple listing of things. I broadly prefer it when the "argument" continues to look like Rust code, and am actually willing to tolerate a more complex macro if it continues looking like Rust code. It also is nice if a span actually consistently points to the trait definition instead of a macro invocation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The following oversimplified example is valid to do:

trait Something {
    fn stuff();
    fn thingy();
}

macro_rules! something_body {
    () => {
        fn stuff() {
            ()
        }
        fn thingy() {
            ()
        }
    }
}

impl Something for u8 {
    something_body!();
}

I would somewhat prefer it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for these comments. I agree that the current invented syntax is not optimal. I'll see if I can do better.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the syntax to be more rust-like. Let me know if it helps.

@rustbot ready

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just happened across https://github.com/rust-lang/rust/blob/master/library/std/src/path.rs#L3594-L3685 which does things very similarly to my current proposal.


#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<A: PointeeSized, B: PointeeSized> const PartialEq<&B> for &mut A
where
A: [const] PartialEq<B>,
{
#[inline]
fn eq(&self, other: &&B) -> bool {
PartialEq::eq(*self, *other)
}
// if <A as PartialEq<B>>::ne uses inline assembly or FFI, then
// this forwarding impl may be more efficient than the default impl
#[inline]
fn ne(&self, other: &&B) -> bool {
PartialEq::ne(*self, *other)
}
macro_rules! ord_eq_impl {
($($ref_A:ty => $A:ident),*) => ($(
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<$A: [const] Ord + PointeeSized> const Ord for $ref_A
{
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(*self, *other)
}
}

#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<$A: [const] Eq + PointeeSized> const Eq for $ref_A {}
)*)
}

ord_eq_impl!(&A => A, &mut A => A);
}