<html><body><div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000"><div><br></div><div><br></div><hr id="zwchr" data-marker="__DIVIDER__"><div data-marker="__HEADERS__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>De: </b>"Gavin Bierman" <gavin.bierman@oracle.com><br><b>À: </b>"Remi Forax" <forax@univ-mlv.fr><br><b>Cc: </b>"amber-spec-experts" <amber-spec-experts@openjdk.java.net><br><b>Envoyé: </b>Mercredi 9 Juin 2021 17:08:17<br><b>Objet: </b>Re: Exhaustiveness mixing sealed type and enum<br></blockquote></div><div data-marker="__QUOTED_TEXT__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;">
Ahem,
<div class=""><br class="">
</div>
<div class="">Actually, now I come to think about it - whilst your example enabled me to clean up the notions of coverage and exhaustiveness - I overlooked that your example still will not work because of the way that switch deals with case constants.</div></blockquote><div><br data-mce-bogus="1"></div><div>For whatever reason, in my mind it was Ok to mix constants and type patterns ... sorry for that.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;">
<div class=""><br class="">
</div>
<div class="">In the Java 16 spec, it says first:</div>
<div class=""><br class="">
</div>
<blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class="">
<div class="">The type of the selector expression must be char, byte, short, int, Character, Byte, Short, Integer, String, or an enum type (§8.9), or a compile-time error occurs.</div>
</blockquote>
<div class=""><br class="">
</div>
<div class="">And then:</div>
<div class=""><br class="">
</div>
<blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class="">
<div class="">
<div class="">The switch block of a switch statement or a switch expression is compatible with the type of the selector expression, T, if both of the following are true:</div>
</div>
</blockquote>
<div class="">
<ul class="">
<ul class="">
<li class="">If T is not an enum type, then every case constant associated with the switch block is assignment compatible with T (§5.2).</li><li class="">If T is an enum type, then every case constant associated with the switch block is an enum constant of type T.</li></ul>
</ul>
</div>
<div class="">The important thing to realise is that these rules are driven by the type of the selector expression, not the case constant. Whilst these have been re-jigged in the draft 17 spec, the semantic content has been preserved for compatibility reasons.</div>
<div class=""><br class="">
</div>
<div class="">Back to a simplified version of your example:</div>
<div class=""><br class="">
</div>
<div class="">List l = ...</div>
<div class="">switch(l) {</div>
<div class=""> case Nil.NIL -> ...</div>
<div class=""> default -> ...</div>
<div class="">}</div>
<div class=""><br class="">
</div>
<div class="">Using the existing rules, this has to fail as List is not an enum type. </div>
<div class=""><br class="">
</div>
<div class="">So, what to do? We could add another rule for checking compatibility of a case label with the selector expression, along the lines of:</div>
<div class=""><br class="">
</div>
<blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class="">
<div class="">- If the type of e is not an enum type, char, byte, short, int, Character, Byte, Short, Integer, or String, then e is downcast convertible to the type of c.</div></blockquote></blockquote><div><br></div><div>I don't think you should restrict the type here, i think it should also work for any static final fields by example,<br data-mce-bogus="1"></div><div>so something more like<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div> - If e is a constant, then e is downcast convertible to the type of c.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class="">
</blockquote>
<div class=""><br class="">
</div>
<div class="">But that is quite a change to Java. We’d now be able to write things like:</div>
<div class=""><br class="">
</div>
<div class="">Object o = …</div>
<div class="">switch(o) {</div>
<div class=""> case “Hello†-> ...</div>
<div class=""> case Nil.NIL -> ...</div>
<div class=""> default -> ...</div>
<div class="">}</div></blockquote><div><br></div><div>It's not that rare to have code that say, if it's this instance of that instance do that, otherwise if it's that type do this, etc.<br></div><div>By example, JSON values are a mix between the constants null, true and false and instances of classes String, Double, JSONArray, JSONObject.<br data-mce-bogus="1"></div><div><br></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;">
<div class=""><br class="">
</div>
<div class="">And code like:</div>
<div class=""><br class="">
</div>
<div class="">switch(o) {</div>
<div class=""> case Nil.NIL -> ...</div>
<div class="">}</div>
<div class=""><br class="">
</div>
<div class="">would typecheck only if o is downcast compatible to Nil but NOT if it is actually of type Nil! Confusing? Potentially!</div></blockquote><div><br></div><div>I think you mean the opposite, if o is typed Nil, because NIL is the only value of the enum Nil, the switch is correct while if o is a super type of Nil, then the switch accept more possible instances that just Nil.NIL so the switch does not typecheck without a default or a total pattern.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;">
<div class=""><br class="">
</div>
<div class="">But I think actually we need a bigger chat about constants, both on this matter and how constants and patterns should co-exist more generally. I propose we table this for the second preview of this feature.</div></blockquote><div><br></div><div>I agree.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div class=""> (But the improved definitions of coverage
and exhaustiveness stay as I stated them yesterday!)</div></blockquote><div><br></div><div>yes !<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;">
<div class=""><br class="">
</div>
<div class="">Thanks,</div>
<div class="">Gavin</div></blockquote><div><br></div><div>regards,<br data-mce-bogus="1"></div><div>Rémi<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div></div></div></body></html>