Skip to content

Document "latent requirements" of PartialOrd  #50230

Closed
@gnzlbg

Description

@gnzlbg

The PartialOrd docs do not document what is de facto required of trait implementors in order for data structures to work correctly. We should update them!

Per @RalfJung's comment below:

FWIW our conclusion was that we basically already require < to be irreflexive, since that is the only way the following equivalences can be upheld:

  • x < y iff x.partial_cmp(y) == Some(Less)
  • x == y iff x.partial_cmp(y) == Some(Equal)
  • x > y iff x.partial_cmp(y) == Some(Greater)

The docs are not explicitly stating that these equivalences must hold, but it seems very much against the spirit of this trait to allow violations of these equivalences. The fact that PartialOrd: PartialEq is very useful here as it makes the 2nd axiom well-defined.

This post used to say something different. Here is the original post

Why doesn't PartialOrd require irreflexivity !(a < a) over < ? AFAICT PartialOrd does not actually express any kind of ordering relation for <. For:

  • a strict partial order on <: we need PartialOrd + Irreflexivity
  • non-strict partial order on <=: we need PartialOrd + Eq since == must be reflexive.
  • total order: we needPartialOrd + Eq + Total

Is this an oversight? If not, we should document that PartialOrd requires:

  • irreflexivity: !(a < a)

as well. That would make PartialOrd's < denote a strict partial order on <.

AFAICT this is actually what was intended, since all the discussions I can find online about PartialOrd talk about floats, and floats are strictly partially ordered under <, but not non-strictly partially ordered under <=, which would fit our current model that floats don't implement Eq.


Also, the docs of PartialOrd do not say what le (<=) and ge (>=) actually mean. AFAICT they mean nothing for PartialOrd in isolation. From reading the source the default implementation is a < b || a == b, which would denote a non-strict total ordering over <= when Eq is implemented. But since Eq is not required for PartialOrd, I'd guess that those overriding these implementations are allowed to do something else as long as they don't implement Eq. It is unclear to me what that "something else" might mean, but the docs should probably say something about this.


Also, I haven't been able to find any document explaining why things are the way they are, but the fact that PartialOrd requires PartialEq makes no sense to me, and it doesn't make much sense either that PartialOrd exposes le (<=) and ge (>=) methods, since as mentioned above, without Eq, le and ge do not express any meaningful ordering relation. It seems that these traits, like all other "operators" traits, mix operator overloading with mathematical semantics: in some cases they are used to express mathematical concepts, like a strict partial ordering relation under <, and in some other cases they are used "to provide <= for floats". If anybody has any links to any discussions / documentation about why things are the way they are I'd like to read them, and maybe we should add rationale sections to the docs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-enhancementCategory: An issue proposing an enhancement or a PR with one.T-langRelevant to the language team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions