<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <font size="4"><font face="monospace">The way I would interpret this
        is "Great, you just made == slightly more reliable, but *still
        unreliable*.  Now people will be even more likely to make
        mistakes with it."  Right?<br>
        <br>
        The basic problem stems from that fact that users want to think
        in terms of an `eq` operation, and the language needs a
        "primitive" equals which gets used at the base of the tower of
        overloaded equals() methods, but the language has given the good
        name to the thing that users usually don't want.  (Javascript
        bit the bullet and introduced `===` for this reason, though they
        had managed to bork up equality much more dramatically before
        they pulled this ripcord.)<br>
        <br>
        Let's also observe that there is currently not just one `==`
        operation, but nine; there is one for object references, and one
        for each primitive type, each with its own ad-hoc meaning.  If
        Valhalla is to deliver on the promise of "programmable
        primitives", not being able to compare "new primitives" with
        `==` doesn't feel like "works like an int."  <br>
        <br>
        The obvious first counter-argument here is "then let me overload
        `==` for primitives, because otherwise, I can't even write
        classes like `float` which treat 0.00 as == to -0.00.  To which
        I might say "I agree, we need to address operator overloading,
        at least for user-definable numerics, anyway", at which point
        the current `==` is just the default for classes that don't
        override `==`.  <br>
        <br>
        At which point you counter again with "Great, so I can do that
        for identity classes too?"  At which point we have to face the
        real problem.  <br>
        <br>
        The root problem of `==` and `.equals()` is that *Object::equals
        was fundamentally the wrong design.*  Josh spends half a dozen
        Items in EJ about "how not to shoot your foot with equals".  And
        this comes from two roots: equals never should have been an
        instance method in the first place, and we want to be able to
        say that instances of C can sometimes be equals to instances of
        subclasses of C, under the right conditions.  This is not a
        stable design.  (An example of a more stable design is where
        equality is a witness to `Eq t`, where both sides have to agree
        on the definition before they can be compared.)  But that runs
        into the desire for equality across subclasses.  The design for
        equality, in the context of extensible classes, is on a
        collision course with reality.  <br>
        <br>
        What this says is that `==` for identity classes will remain a
        permanent toxic waste zone, but it can be made to behave well --
        in fact, the way people want -- for values.  Which is truly a
        glass half everything; the fact that we can get what we want on
        one side, makes it more galling that we can never get what we
        want on the other side.  <br>
        <br>
        We can choose to drain the glass preemptively to avoid regret,
        or fill the glass halfway with something good now (and better
        later), with the understanding that this glass will not be fully
        filled.  Both choices suck.  (As does papering over both with
        `===`.)  <br>
        <br>
        How's your day going?<br>
        <br>
        <br>
        <br>
        <br>
      </font></font><br>
    <div class="moz-cite-prefix">On 6/15/2022 1:51 PM, Kevin Bourrillion
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:CAGKkBktQ7ndHAvvZ_v+HA7RO6K0EuZGBLo+RosrX2s-ihFMdXA@mail.gmail.com">
      
      <div dir="ltr">What I think I understand so far:
        <div><br>
        </div>
        <div>The current plan for `==` for all bucket 2+ types (except
          the 8 _primitive_ types, as I still use the word) is to have
          it perform a fieldwise `==` comparison: identity equality for
          bucket 1 fields, what it's always done for primitive fields,
          and of course recurse for the rest.</div>
        <div><br>
        </div>
        <div>If we consider that the broadest meaning of `a == b` has
          always been "a and b are definitely absolutely
          indistinguishable no matter what", then this plan seems to
          compatibly preserve that, which makes sense for purposes of
          transition.</div>
        <div><br>
        </div>
        <div>What concerns me:</div>
        <div><br>
        </div>
        <div>It's good for transition, at least on the surface, but it's
          a bad long-term outcome.</div>
        <div><br>
        </div>
        <div>Users hunger for a shorter way to write `.equals()`, and
          they will think this is it. I would not underestimate the
          pushback they will experience to writing it out the long way
          in cases where `==` at least *seems* to do the right thing.
          Because in some number of cases, it *will* do the same thing;
          specifically, if you can recurse through your fields and never
          hit a type that overrides equals().</div>
        <div><br>
        </div>
        <div>This is extremely fragile. A legitimate change to one type
          can break these expectations for all the types directly or
          indirectly depending on it, no matter how far away.</div>
        <div><br>
        </div>
        <div>In supporting our Java users here, there's no good stance
          we can take on it: if we forbid this practice and require them
          to call `.equals`, we're being overzealous. If we try to help
          them use it carefully, at best users will stop seeing
          `Object==Object` as a code smell (as we have spent years
          training them to do) and then will start misusing it even for
          reference types again.</div>
        <div><br>
        </div>
        <div>btw, why did I say it's good for transition "on the
          surface"? Because for any class a user might migrate to bucket
          2+, any existing calls to `==` in the wild are extremely
          suspect and *should* be revisited anyway; this is no less true
          here than it is for existing synchronization etc. code.</div>
        <div><br>
        </div>
        <div>What's an alternative?:</div>
        <div><br>
        </div>
        <div>I'm sure what I propose is flawed, but I hope the core
          arguments are compelling enough to at least help me fix it.</div>
        <div><br>
        </div>
        <div>The problem is that while we <i>can</i> retcon `==` as
          described above, it's not behavior anyone  really <i>wants</i>.
          So instead we double down on the idea that non-primitive `==`
          has always been about identity and must continue to be. That
          means it has to be invalid for bucket 2+ (at compile-time for
          the .val type; failing later otherwise?).</div>
        <div><br>
        </div>
        <div>This would break some usages, but again, only at sites that
          deserve to be reconsidered anyway. Some bugs will get fixed in
          the process. And at least it's not the language upgrade itself
          that breaks them, only the specific decision to move some type
          to new bucket. Lastly, we don't need to break anyone abruptly;
          we can roll out warnings as I proposed in the email "We need
          help to migrate from bucket 1 to 2".</div>
        <div><br>
        </div>
        <div>A non-record class that forgets to override equals() from
          Object even upon migrating to bucket 2+ is also suspect. If
          nothing special is done, it would fail at runtime just like
          any other usage of `Foo.ref==Foo.ref`, and maybe that's fine.</div>
        <div><br>
        </div>
        <div>Again, I'm probably missing things, maybe even big things,
          but I'm just trying to start a discussion. And if this can't
          happen I am just searching for a solid understanding of why.</div>
        <div><br>
        </div>
      </div>
    </blockquote>
    <br>
  </body>
</html>