<html><body><div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000"><div><br></div><div><br></div><hr id="zwchr" data-marker="__DIVIDER__"><div data-marker="__HEADERS__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>From: </b>"Kevin Bourrillion" <kevinb9n@gmail.com><br><b>To: </b>"Maurizio Cimadamore" <maurizio.cimadamore@oracle.com><br><b>Cc: </b>"Tagir Valeev" <amaembo@gmail.com>, "Brian Goetz" <brian.goetz@oracle.com>, "Remi Forax" <forax@univ-mlv.fr>, "amber-spec-experts" <amber-spec-experts@openjdk.java.net><br><b>Sent: </b>Tuesday, February 4, 2025 6:14:53 PM<br><b>Subject: </b>Re: Pattern matching on primitive types mxied with instanceof is a footgun<br></blockquote></div><div data-marker="__QUOTED_TEXT__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div dir="ltr"><div dir="ltr">On Tue, Feb 4, 2025 at 8:55 AM Maurizio Cimadamore <<a href="mailto:maurizio.cimadamore@oracle.com" target="_blank">maurizio.cimadamore@oracle.com</a>> wrote:</div><div class="gmail_quote gmail_quote_container"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div>
<p>This seems consistent. So the question is: what is the "mistake"
we're talking about here? The user thinking it was a
_unconditional_ match where in reality that's not the case? While
in the case of instanceof unconditionality is harder to spot, if
this was a switch, the compiler would have immediately asked the
user to provide a default?</p>
<p>It seems to me that the reasoning here implies that developers
will use "if" + "instanceof" _without an "else" just for the
purpose of extract some data, and then complain when the thing
doesn't match (because they have no "else", and so their code will
fail). It seems like our best weapon in this case is education,
rather that introducing arbitrary restrictions and asymmetries in
the language?</p>
<p>(Or, perhaps, in the future have a way to perform an
_unconditional_ extraction without an "if", in which case the
compiler will bark if the pattern is not unconditional.)</p></div></blockquote><div>In some cases this will be relevant, but in <i>this </i>particular example we're looping over Spaceship and then checking for AlienSpaceship, so, no help.</div><br><div>I think it is fair to acknowledge that this is a weakness of the feature design. How to mitigate it? We can try to evangelize always preferring `var` for nested type patterns that are expected to be unconditional. That's an unfortunate readability trade-off, though. And a static analyzer can't know whether you expected it to be unconditional or not, so there might not be much it can do to help.</div><div><br></div><div>I am not even sure what language change could be considered here. Note that this problem is not specific to primitive types, it's just that primitive types are currently the only ones that support "value conversion" so we're encountering this issue with them first. Post-Valhalla, other types might support value conversion too.</div></div></div></blockquote><div><br></div><div>For me it's more about the conversion being implicit vs explicit.<br data-mce-bogus="1"></div><div>Here, we have an implicit conversion while the conversion does not always succeed.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>I believe such conversions, the one that may not always succeed, should be explicit not implicit.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>regards,<br data-mce-bogus="1"></div><div>Rémi<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>@Brian, i'm more worry about a TA with more than 10 years of experience having trouble to find a bug in a student project written in Java.<br></div><div>@Tagir, i'm not sure usin floating point values is the issue here, you can have the same kind of bug between a character and an int.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div dir="ltr"><div class="gmail_quote gmail_quote_container"><br><br><br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div>On 04/02/2025 16:00, Tagir Valeev
wrote:<br>
</div>
<blockquote>
<div dir="ltr">
<div>Hello!</div>
<div><br>
</div>
Well, I would say that Remi has a point. This is a silent
mistake that can be made. You don't see the declaration, as it's
in another file so you may forget about original types and
assume that they are ints. The code compiles and doesn't even
throw an exception, it just works incorrectly. It would be
justified if such code pattern (converting from double to int
only when double fits the int) was common, so conditional
narrowing could be useful in many other places. But the fact is
that it's highly uncommon. Nobody does this. Many other pattern
matching features are nice. E.g., I often see the code which can
be migrated to pattern switch (we are still on Java 17) and I
really want to use it. However, I never see the code which can
be migrated to a narrowing primitive pattern.
<div><br>
</div>
<div>I don't agree that we should drop primitive patterns
completely, but we may reconsider floating point <->
integral conversions and disable them in patterns for a while
(enabling them back later will be always possible).</div>
<div><br>
</div>
<div>With best regards,</div>
<div>Tagir Valeev</div>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Tue, Feb 4, 2025 at
12:45 PM Brian Goetz <<a href="mailto:brian.goetz@oracle.com" target="_blank">brian.goetz@oracle.com</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Wow,
that was pretty amazing. You went from “one student, who was
never taught about how this works, was confused by it” to “
let’s pull the whole feature “ in one breath. <br>
<br>
> On Feb 4, 2025, at 11:33 AM, Remi Forax <<a href="mailto:forax@univ-mlv.fr" target="_blank">forax@univ-mlv.fr</a>>
wrote:<br>
> <br>
> Last week,<br>
> one of the TA for the course "OOP using Java" was grading
student projects,<br>
> the subject of the project can be summarize to "you are
alone in space and angry aliens want you to die".<br>
> <br>
> One of the project had a weird bug when displaying
aliens.<br>
> Spoiling the result of bug hunting, this is due to
students using the pattern matching on primitive without them
realizing it.<br>
> <br>
> Here is a reproducer of the bug:<br>
> <br>
> // in AlienSpaceship.java<br>
> record AlienSpaceship(double x, double y) implements
Spaceship {<br>
> ...<br>
> }<br>
> <br>
> ...<br>
> <br>
> // in a method in another class<br>
> ...<br>
> for(Spaceship spacehip : ...) {<br>
> ...<br>
> if (spaceship instanceof AlienSpaceship(int x, int y)
{<br>
> // display the alien space ship at (x, y)<br>
> }<br>
> ...<br>
> }<br>
> <br>
> The TA said she was about to give up when she found the
issue and that the Java spec should not allow such pattern.<br>
> I agree with here, pattern matching on primitive types is
not a feature people ask for and mixed with instanceof it's a
footgun.<br>
> <br>
> This feature can be re-introduced later using method
patterns and it will be easier to understand the code,<br>
> by example with an hyphotethical method Double.asInt<br>
> <br>
> if (spaceship instanceof AlienSpaceship(Double.asInt(int
x), Double.asInt(int y)) {<br>
> ...<br>
> <br>
> regards,<br>
> Rémi<br>
</blockquote>
</div>
</blockquote>
</div>
</blockquote></div></div><br></blockquote></div></div></body></html>