> 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?