The motivation behind this PR is not driven by pattern matching: John Rose (the 
reporter of the JBS issue) is concerned about having safer casts that, in 
addition, can be JITted to efficient code.

But I get your point that having non-throwing tests better serves pattern 
matching. However, I’m not sure that pattern matching alone would remove the 
more general need for the proposed methods.

As for the controversial question about -0.0, as you note any proposal will 
kind of suck. With “safer” cast methods we can have two (or even more) variants.

In the context of primitive pattern matching (including the relevant material 
in the JLS), however, it would be probably much simpler to allow for matches 
between integral types on one side and for matches between floating-point types 
on the other side, but not a mix. The nuisance with -0.0 and other special 
values would disappear altogether.

Thus, while examples like
    if (anIntExpression instanceof byte b)
and
    if (aDoubleExpression instanceof float f)
make perfect sense, would an example like
    if (aDoubleExpression instanceof short s)
be pragmatically reasonable?

IIRC, the discussions about “Primitive type patterns” and “Evolving past 
reference type patterns” in the amber-spec-experts mailing list of April 2022 
don’t even mention the mixed integral/floating-point case.


Greetings
Raffaello


From: core-libs-dev <core-libs-dev-r...@openjdk.java.net> on behalf of Brian 
Goetz <brian.go...@oracle.com>
Date: Tuesday, 24 May 2022 at 00:09
To: Raffaello Giulietti <d...@openjdk.java.net>, core-libs-dev@openjdk.java.net 
<core-libs-dev@openjdk.java.net>
Subject: Re: RFR: 8279986: methods Math::asXExact for safely checked primitive 
casts
This work is quite timely as we are now paving the way for primitive
type patterns over in Project Amber, and also has a nontrivial
connection with Valhalla.  If you'll pardon a brief digression...

Instanceof and casting work together in a familiar way: before you cast,
you first ask instanceof -- but this is restricted currently to
reference types.  But the pattern is obvious: instanceof is the
precondition check for casting, which asks: "If I made this cast, would
I like the answer."  There are currently two reasons to not like the
answer: a CCE, or the operand is null (because, even though the cast
would succeed, if you tried to use it as a member of that type, you
wouldn't like the answer then.)

If we wanted to extend `instanceof` to primitive types, we are asking
the same question: if I were to cast to this type, would I like the
answer.  And casts involving primitives give us two more reasons to not
like the answer: an NPE (due to unboxing), or loss of precision.  Which
means that we have to specify in JLS 5.1 what cast with loss of
precision means.  At the very least, we will want to align this work
with that; the asXExact should be able to say "throws if the cast would
lose precision", where "lose precision" is precisely defined by the JLS.

Separately, Project Valhalla will let us define new primitive-like
types, such as HalfFloat and SuperLong. Conversions between primitives
are currently specified in a complex table in JLS 5.1.  But surely we
will want to support primitive widening conversions between HalfFloat
and float (somehow; how we do this is a separate discussion.)  Which
brings us back to pattern matching; narrowing casts are inherently
partial, and declared patterns bring partiality into the "return type",
and are the natural way (when we have it) to express things like "cast,
but fail if you can't do so safely". This is preferable to throwing
(which currently is the our choice.)  So it might be a little
unfortunate to introduce throwing toXExactly now and then have to
introduce separate patterns which signal precision loss by match
failure.  (Though that's not the end of the world if there is some
duplication.)

What this says is that the current proposal of toXExact is not the
primitive, because we probably wouldn't want to implement a pattern in
terms of the throwing version.

Converting from float/double to integral types is particularly tricky
with -0.0.  Both answers kind of suck.  (This is a familiar situation,
and these can be very difficult to resolve, as for each position,
*someone* has decided the other position is untenable.)  I understand
the rationale behind Michael H's "but its not exact", but let's not
pretend one answer is good and the other sucks -- they both suck, and
therefore the decision can be made on other factors.

So I have a few new wrinkles to add to the story:

  - We should wait until we have candidate JLS text for "cast conversion
without loss of precision", and ensure the two are consistent, before
pushing;
  - I not quite comfortable with settling the -0.0 issue just yet, there
are some other explorations to complete first;
  - We should be prepared for the fact that we will, sometime soon, have
to implement this whole set again as patterns that do not throw.








On 5/5/2022 6:18 AM, Raffaello Giulietti wrote:
> Add a family of "safe" cast methods.
>
> -------------
>
> Commit messages:
>   - 8279986: methods Math::asXExact for safely checked primitive casts
>   - 8279986: methods Math::asXExact for safely checked primitive casts
>   - 8279986: methods Math::asXExact for safely checked primitive casts
>
> Changes:https://git.openjdk.java.net/jdk/pull/8548/files
>   Webrev:https://webrevs.openjdk.java.net/?repo=jdk&pr=8548&range=00
>    Issue:https://bugs.openjdk.java.net/browse/JDK-8279986
>    Stats: 615 lines in 2 files changed: 609 ins; 0 del; 6 mod
>    Patch:https://git.openjdk.java.net/jdk/pull/8548.diff
>    Fetch: git fetchhttps://git.openjdk.java.net/jdk  pull/8548/head:pull/8548
>
> PR:https://git.openjdk.java.net/jdk/pull/8548

Reply via email to