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