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