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

Brian Goetz brian.goetz at oracle.com
Wed May 25 15:18:26 UTC 2022


Another way to evaluate answers here is: are we inventing new relations, 
or merely clarifying old ones?  The latter is often more desirable.

For example, we might say that x:X can be converted exactly to Y, for 
primitive X and Y, iff:

     eq( (X) (Y) x, x )

where `eq` is `==` for non-floating primitive types, and derived from 
Float::compare and Double::compare for floating point. This means we are 
not inventing any new conversions or comparisons, but merely combining 
ones we already have in the language/platform in a convenient way.

Do the toXExact methods you've defined have this characteristic?

(Though, while this is often the best starting place, it is not always a 
slam-dunk answer; sometimes there are good reasons to depart from 
existing relations, but we should be explicit about what those are.)



On 5/25/2022 9:46 AM, Raffaello Giulietti wrote:
>
> Themotivation behind this PR isnot 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 testsbetter 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-retn at openjdk.java.net> on behalf 
> of Brian Goetz <brian.goetz at oracle.com>
> *Date: *Tuesday, 24 May 2022 at 00:09
> *To: *Raffaello Giulietti <duke at openjdk.java.net>, 
> core-libs-dev at openjdk.java.net <core-libs-dev at 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
>


More information about the core-libs-dev mailing list