[External] : Re: Primitive type patterns
Brian Goetz
brian.goetz at oracle.com
Mon Feb 28 18:08:07 UTC 2022
>
> So *of course* there's an obvious definition of how `int x`
> matches against Integer, and its not a question of whether we
> "define" it that way, its a question of whether we expose the
> obvious meaning, or suppress it. I think the arguments in favor
> of suppression are pretty weak.
>
>
> The strong argument is that instanceof/switch case is about subtyping
> relationship while assignment is about assignment conversions, trying
> to blur the lines between the two has already been tried in the past
> and it results in pain (see below).
This is pretty much assuming your conclusion, and then stating it as
justification :)
I get it; you would prefer that pattern matching be *only* about
subtyping. I understand why you prefer that. But I think this is
mostly a "retreat to the comfort zone" thing.
>
> What about ?
>
> Object o =...
> if (o instanceof byte) { ... }
>
> Does it means that o can be a Long ?
>
This is a good question. (But I know it's also a trap.) We first have
to ask about (static) applicability: is the pattern `byte b` applicable
to Object? If not, we'll get a compilation error.
My earlier message said:
- A primitive type pattern `P p` should be applicable to a reference
target T if T unboxes to P, or T unboxes to a primitive type that can be
widened to P [ or if T unboxes to a primitive type that can be narrowed
to P. ]
Does Object unbox to byte? No.
Does Object unbox to a primitive type that can be widened to byte? No.
[brackets] Does Object unbox to a primitive type than can be narrowed to
byte? No.
How does this square with assignments? I cannot assign
byte b = anObject
| incompatible types: java.lang.Object cannot be converted to byte
If I try this with casting:
Object o = 0L
byte b = (byte) o
I get a CCE, because the cast will only convert from Byte.
Now, what if instead of Object, we start with Long?
Long l = 0L
if (l instanceof byte b) { ... }
First, applicability: does Long unbox to a primitive type that can be
narrowed to byte? Yes! Long unboxes to long, and long can be narrowed
to byte.
Then: matching: if the RHS is not null, we unbox, and do a range check.
(The rules in my previous mail probably didn't get this case perfectly
right), but 0L will match, and 0xffff will not -- as we would expect.
We could consider pushing this farther, if we liked, but there's a risk
of pushing it too far, and I think we're already on the cusp of
diminishing returns. We could consider `case byte b` against Object to
match a Byte. We discussed this, in fact, a few years ago when we
talked about "what does `case 0` mean" when we were considering constant
patterns. (And we concluded in that discussion that the step where we
basically treat Long as narrowable to Integer was taking it way too
far.) So I think the rules I've specified capture (a) the right set of
tradeoffs of how loose we want to be with regard to boxing/unboxing
combined with narrowing/widening, subject to (b) the existing decisions
we've made about assignments.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20220228/08840b56/attachment-0001.htm>
More information about the amber-spec-experts
mailing list