<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0cm;
font-size:11.0pt;
font-family:"Calibri",sans-serif;}
.MsoChpDefault
{mso-style-type:export-only;}
@page WordSection1
{size:612.0pt 792.0pt;
margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.WordSection1
{page:WordSection1;}
--></style>
</head>
<body lang="NL-BE" link="blue" vlink="#954F72" style="word-wrap:break-word">
<div class="WordSection1">
<p class="MsoNormal"><span lang="EN-US">Hi folks<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">While writing a snippet to show how cool switch pattern matching is,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">I managed to conceive some of *interesting* snippets, some of which<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">fail to compile with the openjdk early access build 32, but I don't<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">see why they aren't considered valid according to the spec.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">Let's start with a normal working snippet<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">```<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">sealed interface Uber<T> permits Base, Relieve {}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">sealed interface Base<T> extends Uber<T> permits Foo, Bar, Other{}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">record Foo() implements Base<String>{}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">record Bar() implements Base<Long>{}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">record Other<T>() implements Uber<T>{}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">record Relieve() implements Uber<Integer> {}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">class Test {<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> static Uber<Integer> foo() {<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> return null;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> }<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> <o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> static Base<Integer> bar() {<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> return null;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> }<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> static String test1a(){<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> return switch (bar()){<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> case null -> "Hi";<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> case Other<Integer> o -> "Hello";<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> };<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> }<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> <o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> static String test1b(){<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> return switch (foo()){<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> case null -> "Hi";<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> case Relieve r -> "Hey";<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> case Other<Integer> o -> "Hello";<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> };<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> }<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> static String test2(){<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> return switch (bar()){<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> case Other<Integer> o -> "Hello";<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> };<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> }<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> static String test3(){<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> switch (bar()){<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> case Other<Integer> o -> {<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> return "Hello";<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> }<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> }<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> }<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">```<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">This compiles perfectly fine, however, <o:p>
</o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">things change when we remove the `other` class.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">```<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">sealed interface Uber<T> permits Base, Relieve {}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">sealed interface Base<T> extends Uber<T> permits Foo, Bar{}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">record Foo() implements Base<String>{}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">record Bar() implements Base<Long>{}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">record Relieve() implements Uber<Integer> {}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">```<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">Let's look at each method individually<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">```<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">static String test1a(){<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> return switch (bar()){<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> case null -> "Hi";<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> };<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">```<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">This fails with the following error:<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">> the switch expression does not cover all possible input values<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">This might seem obvious to some, given that there is no case<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">for `Base<Integer>`, but note `test1b`:<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">```<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">static String test1b(){<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> return switch (foo()){<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> case null -> "Hi";<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> case Relieve r -> "Hey";<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> };<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">```<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">This compiles perfectly fine, even though there is no case that<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">covers `Base<Integer>` or part of it. <o:p>
</o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">As far as I can see, the spec does not give any reason as to why<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">this version of `test1a` shouldn't compile, and disagrees with<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">the reason given by javac.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">Now for test2.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">```<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">static String test2(){<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> return switch (bar()){};<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">```<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">This is against the spec:<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">> It is a compile-time error if a switch expression has no result expressions.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">test3:<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">```<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">static String test3(){<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> switch (bar()){};<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">```<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">This one, after a bit more checking is also, illegal according
<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">to the spec, but we aren't in the clear yet. The only reason I<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">could find that `test3` was illegal is "14.22. Unreachable Statements".<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">> A switch statement whose switch block is empty [...] can complete normally.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">This means our methodblock can complete normally which isn't allowed.
<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">Note that javac complains again about the switch not covering
<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">all input values, which isn't true.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">We can fix our method however, so it is valid according to the spec.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">```<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">static String test3(){<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> String s;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> switch (bar()){};<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"> return s;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">```<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">Now this might seems crazy, but Chapter 16. Definite Assignment<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">sees the switch differently, and "realizes" that the switch<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">can not complete normally, (read: all variables are considered
<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">to be both definite unassigned and definite assigned). As a
<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">result we can read from `s` even though there are no assignments.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">This does not work however, and just adds a second error:<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">> variable s might not have been initialized<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">Greetings<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">Robbe Pincket</span></p>
</div>
</body>
</html>