Rework operator interfaces

[Pull request](https://github.com/carbon-language/carbon-lang/pull/1178

Table of contents

Problem

Our operator interface names need to be updated to match the decision in #1058. Further, we are missing a description of the interfaces used to overload comparison operators, and the rules are not up to date with the decision in #710.

Background

See the two leads issues for background and discussion of options.

Proposal

See changes to the design.

Details

Beyond establishing names for interfaces, this proposal also establishes:

  • We will have high-level interfaces for equality and relational comparison. The equality interface provides both == and !=. The relational comparison interface provides all of <, <=, >, and >=.
  • Following the convention established for arithmetic operators, we provide both a heterogeneous comparison interface and a homogeneous constraint. For example, T is EqWith(T) is equivalent to T is Eq.
  • The high-level interfaces always return bool.
  • The high-level interfaces have expected semantics associated with them.

It is intended that we also provide low-level interfaces, to directly control individual operators and to allow a result type other than bool. These are not included in this proposal, as it’s not yet clear how they should be specified, and it’s more important to get the high-level interfaces decided at this point.

Rationale

  • Language tools and ecosystem
    • High-level semantics allow tools to reason about the intended meaning of Carbon code. For example, a tool could statically or dynamically determine that an implementation of Ordered doesn’t satisfy the expected rules and produce a warning.
  • Performance-critical software
    • We expect == and ordering to be customized separately, in order to avoid cases where a suboptimal == is constructed in terms of an ordering. See C++ committee paper P1190R0 for details on the problem.
  • Code that is easy to read, understand, and write
    • Combining all comparison operators of the same kind – equality or relational – into a single interface makes it both easier to implement them and easier to write a generic constraint for them. This approach is also expected to be easy to teach, with the low-level interfaces only explained to a more advanced audience.
  • Practical safety and testing mechanisms
    • While there are rules for the comparison interfaces, violating those rules does not result in immediate unbounded undefined behavior. However, implementations should still attempt to detect violations of these rules and report them where that is feasible.
  • Interoperability with and migration from existing C++ code
    • The intent to provide a low-level interface for individual operators is directly motivated by the desire to provide strong interoperability with operators defined in C++. While this functionality is not part of this proposal, it’s expected to follow once the interactions with generics are worked out.

Alternatives considered

Use ComparableWith instead of OrderedWith

We could use the term “comparable” for relational comparisons instead of “ordered”. There is existing practice for both: for example, Rust and Haskell use Ord, and Swift uses Comparable.

The main argument for using “ordered” instead of “comparable” is that == and != are also a form of comparison but aren’t part of OrderedWith, and the word “ordered” distinguishes relational comparison from equality comparison.