<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Windows-1252">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: "Segoe UI", "Segoe UI Web (West European)", "Helvetica Neue", sans-serif; font-size: 11pt; color: rgb(0, 0, 0);" class="elementToProof">
That section defines the runtime semantics of switch label selection indeed. </div>
<div style="font-family: "Segoe UI", "Segoe UI Web (West European)", "Helvetica Neue", sans-serif; font-size: 11pt; color: rgb(0, 0, 0);" class="elementToProof">
<div><br>
</div>
<div>What is also important is the kind of types that can be "allowed" to reach this point. The permitted case constant associations are shown in 14.11.1 Switch Blocks where we split (add) the new kinds of constants separately.
</div>
<div>if T is one of char, byte, short, int, Character, Byte, Short, Integer, or String, the constant is assignment compatible with T.</div>
<div><br>
</div>
<div>if T is one of long, float, double, boolean, Long, Float, Double, Boolean, the constant is the same type:</div>
<div><br>
</div>
<div>with T if T is a primitive type, or</div>
<div>with T' where T' is T after unboxing conversion, otherwise.</div>
<div>That second bullet essentially says that a selector of a float type can match only float constant labels and so on and so forth.
</div>
<div><br>
</div>
<div>While comparing y to 1 (the integer one) is crystal clear, there are other occasions that this is not. Consider this:</div>
<div><br>
</div>
<div>jshell> float f = 16777216 // 224 and that can be represented exactly into a float</div>
<div>f ==> 1.6777216E7</div>
<div><br>
</div>
<div>jshell> f == 16777217 // 224+1 that cannot be represented exactly because the bits of the mantissa do not suffice, so the RHS constant maps also to 1.6777216E7</div>
<div>$7 ==> true</div>
<div><br>
</div>
<div>As result the following switch is not permitted:</div>
<div><br>
</div>
<div>    void test(float f) {</div>
<div>        switch (f) {</div>
<div>            case 16777216:</div>
<div>                break;</div>
<div>            case 16777217:</div>
<div>                break;</div>
<div>            default:</div>
<div>                break;</div>
<div>        }</div>
<div>    }</div>
<div><br>
</div>
both labels map to the same float while the two labels are clearly, representationally different (among them). That would lead to great confusion.<br>
</div>
<div id="appendonsend"></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> amber-dev <amber-dev-retn@openjdk.org> on behalf of Ella Ananeva <ella.ananeva@oracle.com><br>
<b>Sent:</b> 19 October 2023 19:01<br>
<b>To:</b> amber-dev@openjdk.org <amber-dev@openjdk.org><br>
<b>Subject:</b> Float to byte and back in switch</font>
<div> </div>
</div>
<style>
<!--
@font-face
        {font-family:"Cambria Math"}
@font-face
        {font-family:Calibri}
@font-face
        {font-family:Menlo}
p.x_MsoNormal, li.x_MsoNormal, div.x_MsoNormal
        {margin:0in;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif}
a:link, span.x_MsoHyperlink
        {color:#0563C1;
        text-decoration:underline}
code
        {font-family:"Courier New"}
p.x_p1, li.x_p1, div.x_p1
        {margin:0in;
        font-size:8.5pt;
        font-family:Menlo;
        color:black}
span.x_s1
        {}
.x_MsoChpDefault
        {font-size:10.0pt;
        font-family:"Calibri",sans-serif}
@page WordSection1
        {margin:1.0in 1.0in 1.0in 1.0in}
div.x_WordSection1
        {}
-->
</style>
<div lang="EN-US" link="#0563C1" vlink="#954F72" style="word-wrap:break-word">
<div class="x_WordSection1">
<p>Hi team,</p>
<p>When we match labels in switch with primitive types, the spec defines the behavior for integral types and for floating-point types.
</p>
<p><span style="font-family:Symbol">·</span>  <strong><span style="font-family:"Calibri",sans-serif">If
</span></strong><em><b><span style="font-family:"Calibri",sans-serif">T</span></b></em><strong><span style="font-family:"Calibri",sans-serif"> is a primitive type, then a</span></strong> 
<code><span style="font-size:10.0pt">case</span></code> label with a <code><span style="font-size:10.0pt">case</span></code> constant
<em><span style="font-family:"Calibri",sans-serif">c</span></em> applies to a value that is of type
<code><span style="font-size:10.0pt">char</span></code>, <code><span style="font-size:10.0pt">byte</span></code>,
<code><span style="font-size:10.0pt">short</span></code>, <code><span style="font-size:10.0pt">int</span></code>, 
<code><b><span style="font-size:10.0pt">long</span></b></code><strong><span style="font-family:"Calibri",sans-serif">,
</span></strong><code><b><span style="font-size:10.0pt">float</span></b></code><strong><span style="font-family:"Calibri",sans-serif">,
</span></strong><code><b><span style="font-size:10.0pt">double</span></b></code><strong><span style="font-family:"Calibri",sans-serif">,
</span></strong><code><b><span style="font-size:10.0pt">boolean</span></b></code><strong><span style="font-family:"Calibri",sans-serif">,</span></strong>
<code><span style="font-size:10.0pt">String</span></code> or an enum type if the constant
<em><span style="font-family:"Calibri",sans-serif">c</span></em> is equal to the value.</p>
<p>Equality is defined in terms of the <code><span style="font-size:10.0pt">==</span></code> operator
<strong><span style="font-family:"Calibri",sans-serif">(<a href="https://docs.oracle.com/javase/specs/jls/se21/html/jls-15.html#jls-15.21">15.21</a>) for the integral types and the boolean type, and in terms of representation equivalence (<a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Double.html#repEquivalence">java.lang.Double</a>)
 for the floating-point types.</span></strong>  <strong><span style="font-family:"Calibri",sans-serif">If</span></strong> the value is a
<code><span style="font-size:10.0pt">String</span></code>,  equality is defined in terms of the
<code><span style="font-size:10.0pt">equals</span></code> method of class <code><span style="font-size:10.0pt">String</span></code>.</p>
<p> </p>
<p>What should be the behavior, though, when we try to match an integral type to a floating-point type?</p>
<p>e.g., In this scenario:</p>
<p class="x_p1"><span style="font-size:10.0pt; font-family:"Courier New"; color:#0033B3">private static void
</span><span style="font-size:10.0pt; font-family:"Courier New"; color:#00627A">testSwitch</span><span style="font-size:10.0pt; font-family:"Courier New"; color:#080808">(</span><span style="font-size:10.0pt; font-family:"Courier New"; color:#0033B3">float
</span><span style="font-size:10.0pt; font-family:"Courier New"; color:#080808">y) {<br>
    </span><span style="font-size:10.0pt; font-family:"Courier New"">System</span><span style="font-size:10.0pt; font-family:"Courier New"; color:#080808">.</span><i><span style="font-size:10.0pt; font-family:"Courier New"; color:#871094">out</span></i><span style="font-size:10.0pt; font-family:"Courier New"; color:#080808">.println(y
 == </span><span style="font-size:10.0pt; font-family:"Courier New"; color:#1750EB">1</span><span style="font-size:10.0pt; font-family:"Courier New"; color:#080808">);     //prints true<br>
    </span><span style="font-size:10.0pt; font-family:"Courier New"; color:#0033B3">switch
</span><span style="font-size:10.0pt; font-family:"Courier New"; color:#080808">(y) {<br>
        </span><span style="font-size:10.0pt; font-family:"Courier New"; color:#0033B3">case
</span><span style="font-size:10.0pt; font-family:"Courier New"; color:#1750EB">1
</span><span style="font-size:10.0pt; font-family:"Courier New"; color:#080808">-> {
</span><span style="font-size:10.0pt; font-family:"Courier New"">System</span><span style="font-size:10.0pt; font-family:"Courier New"; color:#080808">.</span><i><span style="font-size:10.0pt; font-family:"Courier New"; color:#871094">out</span></i><span style="font-size:10.0pt; font-family:"Courier New"; color:#080808">.println(y
 == </span><span style="font-size:10.0pt; font-family:"Courier New"; color:#1750EB">1</span><span style="font-size:10.0pt; font-family:"Courier New"; color:#080808">);}//throws a compile-time error:
</span><span class="x_s1">constant label of type int is not compatible with switch selector type float</span></p>
<p class="x_MsoNormal" style="background:white"><span style="font-size:10.0pt; font-family:"Courier New"; color:#080808"><br>
        </span><span style="font-size:10.0pt; font-family:"Courier New"; color:#0033B3">default
</span><span style="font-size:10.0pt; font-family:"Courier New"; color:#080808">-> { }<br>
    }<br>
}</span></p>
<p class="x_MsoNormal"> </p>
<p class="x_MsoNormal">I would expect the compiler to be able to handle this situation: since int can be converted to float and the equality operator returns true, the label should be chosen.</p>
<p class="x_MsoNormal"> </p>
<p class="x_MsoNormal">The opposite situation with narrowing conversion, when we try to convert float to int may be trickier, but shouldn’t it also be accepted?</p>
<p class="x_MsoNormal"> </p>
<p class="x_MsoNormal">Thank you,</p>
<p class="x_MsoNormal">Ella Ananeva</p>
<p class="x_MsoNormal"> </p>
<p class="x_MsoNormal"> </p>
</div>
</div>
</body>
</html>