RFR: 8279986: methods Math::asXExact for safely checked primitive casts

Brian Goetz brian.goetz at oracle.com
Mon May 23 22:08:59 UTC 2022


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


More information about the core-libs-dev mailing list