Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Should PartialOrd provide impl for Ord to avoid boilerplate? #63104

Closed
oblitum opened this issue Jul 29, 2019 · 4 comments
Closed

Should PartialOrd provide impl for Ord to avoid boilerplate? #63104

oblitum opened this issue Jul 29, 2019 · 4 comments
Labels
C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@oblitum
Copy link

oblitum commented Jul 29, 2019

Currently std gives the following example in "How can I implement Ord?":

use std::cmp::Ordering;

#[derive(Eq)]
struct Person {
    id: u32,
    name: String,
    height: u32,
}

impl Ord for Person {
    fn cmp(&self, other: &Self) -> Ordering {
        self.height.cmp(&other.height)
    }
}

impl PartialOrd for Person {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialEq for Person {
    fn eq(&self, other: &Self) -> bool {
        self.height == other.height
    }
}

I was wondering why this boilerplate couldn't be reduced, because it seems clear that in almost all cases of Ord implementation, PartialOrd implementation can be done in terms of the former.

I suspect this is in its current state because it exists prior to specialization? If you have the following:

impl<T: Ord> PartialOrd for T {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

Am I right that the std example could be updated to:

use std::cmp::Ordering;

#[derive(Eq)]
struct Person {
    id: u32,
    name: String,
    height: u32,
}

impl Ord for Person {
    fn cmp(&self, other: &Self) -> Ordering {
        self.height.cmp(&other.height)
    }
}

impl PartialEq for Person {
    fn eq(&self, other: &Self) -> bool {
        self.height == other.height
    }
}

?

@jonas-schievink jonas-schievink added C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Jul 29, 2019
@shingtaklam1324
Copy link

shingtaklam1324 commented Jul 29, 2019

This conflicts with the existing blanket impl in core.

error[E0119]: conflicting implementations of trait `std::cmp::PartialOrd<&_>` for type `&_`:
 --> src/lib.rs:3:1
  |
3 | impl<T: Ord> PartialOrd for T {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: conflicting implementation in crate `core`:
          - impl<A, B> std::cmp::PartialOrd<&B> for &A
            where A: std::cmp::PartialOrd<B>, A: ?Sized, B: ?Sized;

(There was a previous discussion on reddit r/cpp)

The idea is a good one, since the existing method of providing custom impl of PartialOrd and Ord isn't great, with the same impl for PartialOrd for every type. ( Some(self.cmp(&other)) ). However I'm not sure this is possible right now, especially without Specialisation.

@oblitum
Copy link
Author

oblitum commented Jul 29, 2019

@shingtaklam1324 what this is basically saying is that given impl<T: Ord> is too general that it also covers references (Ord refs), and there's a impl for references already, then the two collide?

@shingtaklam1324
Copy link

shingtaklam1324 commented Jul 29, 2019

Pretty much.

Essentially what rustc is complaining about is that there are now two implementations of the same trait on the same type

PartialOrd<Rhs=Self>, so replace B with A in the error.

Consider a type A: Ord

  1. First way
    1. since Ord: PartialOrd
    2. A must impl PartialOrd
    3. impl PartialOrd<&A> for &A from core's impl<A, B> std::cmp::PartialOrd<&B> for &A where A: PartialOrd<B>
  2. Second Way
    1. impl Ord<&A> for &A from core's impl<'_, A> Ord for &'_ A
    2. impl PartialOrd<&A> for &A from your impl<T: Ord> PartialOrd for T

@scottmcm
Copy link
Member

This has been a wish for a long time (such as rust-lang/rfcs#1028). I think it's better tracked in the RFCs repo, since it depends on languages changes, and is plausibly just a requirement to be addressed in a specialization RFC. (Or a different change, which would also take an RFC.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants