I'm for Option, given Option 2 is not a real Option 2, see below. 
It's unfortunate that the behavior inside nested patterns is different from the 
behavior of the switch. As you said, it's the expected semantics and i think 
it's not a big deal if we do not allow destructuring inside a match ( new 
Box(t) matches Box(Object o)). 

I believe the old switch and the new switch should work the same way. 
it will be surprising if a kind of switch allow to declare a case null and 
another kind do not allow it. 

Also about having to put the case null at the top because of the dominance 
analysis, the compiler can easily recognize case 'null' and remove it from the 
dominance analysis meaning it can be put an any positions, or we can choose by 
example that if 'default' as to be the last pattern, case null as to be the one 
just before. 

As far as a understand, your Option 2 is just 1.b, i.e. the semantics is the 
same as Option 1 and you introduce a specific behavior if the match is detected 
as being a type restatement. 
In my opinion, there is a more general question first, do we want to allow type 
restatement ?, and if the option is yes, then we can decide if we want the null 
behavior to be the one you propose or not. 

I'm not sure it's a good idea to allow type restatement in switch 
- transforming a switch to an if true seems arcane, if we want a type 
restatement syntax, why use switch and not another construction (let expression 
?), it will be more clear. 
- it goes in the opposite direction of the introduction of 'var' in the 
language, 'var' hides the type but here we introduce a feature to change the 
type (more or less) for a part of the code, this make the code harder to read 
for a feature which seems too arcane. 

regards, 
Rémi 

> De: "Gavin Bierman" <gavin.bier...@oracle.com>
> À: "amber-spec-experts" <amber-spec-experts@openjdk.java.net>
> Envoyé: Vendredi 3 Novembre 2017 11:46:10
> Objet: Patterns design question: Nulls

> Nulls and pattern matching

> The null value is treated somewhat inconsistently in Java; unfortunately 
> pattern
> matching places a fresh focus on these inconsistences. Consider a local
> variable, String s=null; . Currently s instanceof String returns false; 
> whereas
> (String)s succeeds; and further switch (s){ case "Hello": ... } throws a NPE.
> Unfortunately, we need to maintain these behaviours whilst providing a
> consistent story for patterns.

> So far, we have essentially two choices on the table. One based on what might 
> be
> called a pragmatic navigation of existing choices; and another more
> sophisticated one based on static type information. (In what follows, we 
> assume
> a declaration T t = null; is in scope.) Option 1.

> Matches t matches Object o . To keep it consistent with instanceof this must
> return false .

> Switch switch is retconned to not throw a NPE when given a null . However, all
> switches with reference-typed selector expressions are considered to have an
> implicit case null: throw new NullPointerException(); clause as the first
> clause in the switch. If the user supplies a null clause (which means it must
> be a pattern-matching switch ) then this replaces the implicit clause. [An
> alternative to this is to introduce non-null type tests, which we fear would
> quickly become unwieldy.]

> Note that this addresses a problem that has been brought up on the external
> mailing list. Currently:
> static void testSwitchInteger(Integer i) {
>     switch(i) {
>         case 1:  System.out.println("One");   break;
>         default: System.out.println("Other"); break;
>     }
> }
> static void testSwitchNumber(Number i) {
>     switch(i) {
>         case 1:  System.out.println("One");   break;
>         default: System.out.println("Other"); break;
>     }
> }
> testSwitchNumber(null);  // prints "Other"
> testSwitchInteger(null); // NPE

> The Integer case is an old-style switch, so throws an NPE. The Number case is 
> a
> pattern matching case, so without the insertion of an implicit null clause, it
> would actually match the default clause (this is the behaviour of the current
> prototype).

> ASIDE Adding a null clause has an impact on the dominance analysis in pattern
> matching. A null pattern must appear before a type test pattern.

> Nested/Destructuring patterns As discussed earlier, t matches Object o returns
> false. But unfortunately new Box(t) matches Box(Object o) really ought to
> return true. (Both because this is what we feel would be expected, but also to
> be consistent with expected semantics of extractors.) In other words, the
> semantics of matching against null is not compositional. Note also that the
> null value never matches against a nested pattern.

> We might expect a translation to proceed something like the following.
> e matches Box(Object o)
> -> e matches Box &&
>        (e.contents matches null as o || e.contents matches Object o)
> -> e instance Box &&
>        (e.contents == null || e.contents instanceof Object)

> (Note the rarely seen as pattern in the intermediate pattern.) Option 2.

> We can use the static type information to classify pattern matches, which
> ultimately determines how the matching is translated.

> For example:
> if (t matches U u) { // where T <: U
>     ...
> }

> Notice here that the pattern match is guaranteed to succeed as T is a subtype 
> of
> U . We can classify this as a type restatement pattern, and compile it
> essentially to the following
> if (true) {
>     U u = t;
>     ...
> }

> In other words, the expression (o matches U u) succeeds depending on the 
> static
> type of o : if the static type of o is a subtype of U then it evaluates to 
> true
> , even for the value of null . If it is not statically a subtype of U then its
> runtime type is tested as normally, and null would fail.

> ASIDE The choice of null matching also impacts on our reachability analysis. 
> For
> example:
> Integer i = ...;
> switch (i) {
>     case Integer j: {
>         System.out.println(j);
>         break;
>     }
>     default: System.out.println("Something else");
> }
> Is the default case reachable? If the type test matches null then it is
> unreachable, otherwise it is reachable.

Reply via email to