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.



Reply via email to