> From: "Brian Goetz" <brian.go...@oracle.com>
> To: "Gavin Bierman" <gavin.bier...@oracle.com>
> Cc: "amber-spec-experts" <amber-spec-experts@openjdk.java.net>
> Sent: Vendredi 1 Octobre 2021 00:25:26
> Subject: Re: Pattern Matching for switch (Second Preview)

> [ moving to a-s-e ]

> I get the concern that a type pattern is no longer "just a variable
> declaration"; that was a nice part of the "patterns aren't really so hard to
> understand" story. But I think the usability is likely to be not very good.
> Take this example:

> sealed interface Node<T> { }
> record AddNode<T>(Node<T> left, Node<T> right) extends Node<T> { }
> ...

> Node<int> ni = ...
> switch (ni) {
> case AddNode(Node left, Node right) -> ...

> There's no instantiation of Node possible here *other than* Node<int>. Which
> means we are forcing users to either redundantly type out the instantiation
> (which can get big), or use casts inside the body when they pull things out of
> left and right. (And patterns were supposed to make casts go away.) There's
> almost no case where someone wants a raw type here.

> We faced this in method references; when referring to Foo::m, we use the 
> target
> type to infer the right parameterization of m. Raw types are a migration
> compatibility thing, but there was no migration compatibility concern with
> method references, nor is there with patterns, since these are new linguistic
> forms.

> What's different here is that we have more type information -- the type of the
> switch target. So we can refine the type pattern with additional information
> from the target. And I can't conceive of a case where the user wouldn't thank
> us for this.
I fully agree with Brian. 

The pattern matching syntax can be visually quite heavy, if we can make the 
pattern part simpler/lighter visually, it's a win. 
If a new syntax does not introduce a new way to declare raw types (which does 
not play well with inference), it's a win. 

Rémi 

> On 9/30/2021 8:25 AM, Gavin Bierman wrote:

>>> 2. Inference for type patterns. This one may be a little controversial, 
>>> because
>>> we already let this ship sail with type patterns in instanceof, but I'm 
>>> pretty
>>> convinced that what we're doing right now is wrong. Currently, if we are
>>> switching on a List<String>, we disallow a type pattern for ArrayList<Frog>,
>>> because this would require an unchecked conversion. This is right. But if we
>>> have a `case ArrayList a`, the type of `a` is not ArrayList<String>, but raw
>>> ArrayList. This is almost always not what the user wants; there's no 
>>> migration
>>> compatibility here where the switch target was generified but the case 
>>> labels
>>> are not. Like we do with method references, we should infer a reasonable
>>> parameterization of ArrayList from the match target when a "naked" type 
>>> shows
>>> up in a type pattern. (If the user really wants a raw ArrayList, they can
>>> switch on a raw List.)

>>> Fixing this for switch is no problem, as it is in preview, but fixing this 
>>> in
>>> instanceof requires more care, since there may be production code out there.
>>> However, we've generally held that it is OK to infer _more_ specific types 
>>> than
>>> have previously been inferred; I doubt much code would be impacted -- more
>>> likely, some silly casts would go away, since users no longer have to cast 
>>> to
>>> ArrayList<String>.

>> I’m still unsure about this. Type patterns are treated like variable
>> declarations - indeed we went to *a lot* of effort to harmonise all 
>> treatments
>> in the JLS regarding variable declarations. What we got to was very pleasing 
>> -
>> even if I say so myself - pattern variable declarations are just variable
>> declarations with a special treatment for scope. This proposal will break 
>> that
>> because now when a user declares a pattern variable of type ArrayList they 
>> get
>> something else. Would we not prefer some sort of indication from the user 
>> that
>> they want inference here? What if they do want the raw type?

Reply via email to