Gavin reminded me that we are not finalizing patterns in switch in 19
(hard to keep track, sometimes), so we have a little bit of time to
figure out what we want here.
One thing that is potentially confusing is that patterns work indirectly
in a number of ways. For example, if we have a declared deconstruction
pattern for Point, you can't *invoke* it as you can a method; the
language runtime invokes it on your behalf under the right situations.
(In this way, a deconstructor is a little like a static initializer; it
is a body of code that you declare, but you can't invoke it directly,
the runtime invokes it for you at the right time, and that's fine.)
I had always imagined the relationship with locals being similar; a
pattern causes a local to be injected into certain scopes, but the
pattern itself is not a local variable declaration. Obviously there is
more than one way to interpret this, so we should make a more deliberate
decision.
As a confounding example that suggests that pattern variables are not
"just locals", in the past we talked about various forms of "merging":
if (t instanceof Box(String s) || t instanceof Bag(String s)) { ... }
or
case Box(String s):
case Bag(String s):
common-code;
If pattern variables could be annotated, then the language would be in
the position of deciding what happens with
case Box(@Foo(1) String s):
case Bag(@Foo(2) String s):
(This is the "annotation merging" problem, which is why annotations are
not inherited in the first place.)
I don't have an answer here, but I'm going to think about the various
issues and try to capture them in more detail before proposing an answer.
On 5/31/2022 10:49 AM, Brian Goetz wrote:
Erm... I actually thought that it was your idea to allow the 'final'
modifier on patterns. This change was introduced in Java 16 (when
patterns for instanceof were finalized). Here's the initial e-mail
from you (item 2):
https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-August/002433.html
That mail is exactly the discussion point I was thinking of. But I
never said that there should be a way to declare them as final at
all! I said it was a mistake to have made them automatically final,
and that patterns should introduce ordinary mutable locals. I wasn't
suggesting an option, just that we'd picked the wrong default (and
created a new category of complexity in the process.)
But, its an honest leap from there to "well of course me must have
meant you could declare them final." But had this been explicitly
raised, I would have not been in favor of this option, for two reasons:
- The conversation we are having now -- it was clear that eventually,
some more complex pattern would introduce variables in a way such that
there was not an obvious "local variable" declaration, and that we
would eventually be having a "for consistency" discussion;
- The value of being able to declare these things final is almost
zero; the only reason we are having this conversation at all is "for
consistency" with local variables. But if someone said "should we add
a feature to let you make pattern variables final", the "meh" would
have been deafening.
instanceof @Cartesian Point p'. It looks like I cannot do the same in
the second case, which is another asymmetry.
We definitely intended to not allow declaration annotations.
But they are allowed for type test patterns, since Java 16.
Yeah, we've got a problem.