1 /*
   2  * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import jdk.incubator.code.Reflect;
  25 
  26 /*
  27  * @test
  28  * @modules jdk.incubator.code
  29  * @enablePreview
  30  * @build SwitchExpressionTest2
  31  * @build CodeReflectionTester
  32  * @run main CodeReflectionTester SwitchExpressionTest2
  33  */
  34 public class SwitchExpressionTest2 {
  35 
  36     @IR("""
  37             func @"caseConstantRuleExpression" (%0 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
  38                 %1 : Var<java.type:"java.lang.String"> = var %0 @"r";
  39                 %2 : java.type:"java.lang.String" = var.load %1;
  40                 %3 : java.type:"java.lang.String" = java.switch.expression %2
  41                     (%4 : java.type:"java.lang.String")java.type:"boolean" -> {
  42                         %5 : java.type:"java.lang.String" = constant @"FOO";
  43                         %6 : java.type:"boolean" = invoke %4 %5 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
  44                         yield %6;
  45                     }
  46                     ()java.type:"java.lang.String" -> {
  47                         %7 : java.type:"java.lang.String" = constant @"BAR";
  48                         yield %7;
  49                     }
  50                     (%8 : java.type:"java.lang.String")java.type:"boolean" -> {
  51                         %9 : java.type:"java.lang.String" = constant @"BAR";
  52                         %10 : java.type:"boolean" = invoke %8 %9 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
  53                         yield %10;
  54                     }
  55                     ()java.type:"java.lang.String" -> {
  56                         %11 : java.type:"java.lang.String" = constant @"BAZ";
  57                         yield %11;
  58                     }
  59                     (%12 : java.type:"java.lang.String")java.type:"boolean" -> {
  60                         %13 : java.type:"java.lang.String" = constant @"BAZ";
  61                         %14 : java.type:"boolean" = invoke %12 %13 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
  62                         yield %14;
  63                     }
  64                     ()java.type:"java.lang.String" -> {
  65                         %15 : java.type:"java.lang.String" = constant @"FOO";
  66                         yield %15;
  67                     }
  68                     ()java.type:"boolean" -> {
  69                         %16 : java.type:"boolean" = constant @true;
  70                         yield %16;
  71                     }
  72                     ()java.type:"java.lang.String" -> {
  73                         %17 : java.type:"java.lang.String" = constant @"";
  74                         yield %17;
  75                     };
  76                 return %3;
  77             };
  78             """)
  79     @Reflect
  80     public static String caseConstantRuleExpression(String r) {
  81         return switch (r) {
  82             case "FOO" -> "BAR";
  83             case "BAR" -> "BAZ";
  84             case "BAZ" -> "FOO";
  85             default -> "";
  86         };
  87     }
  88 
  89     @IR("""
  90             func @"caseConstantRuleBlock" (%0 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
  91                 %1 : Var<java.type:"java.lang.String"> = var %0 @"r";
  92                 %2 : java.type:"java.lang.String" = var.load %1;
  93                 %3 : java.type:"java.lang.String" = java.switch.expression %2
  94                     (%4 : java.type:"java.lang.String")java.type:"boolean" -> {
  95                         %5 : java.type:"java.lang.String" = constant @"FOO";
  96                         %6 : java.type:"boolean" = invoke %4 %5 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
  97                         yield %6;
  98                     }
  99                     ()java.type:"java.lang.String" -> {
 100                         %7 : java.type:"java.lang.String" = constant @"BAR";
 101                         java.yield %7;
 102                     }
 103                     (%8 : java.type:"java.lang.String")java.type:"boolean" -> {
 104                         %9 : java.type:"java.lang.String" = constant @"BAR";
 105                         %10 : java.type:"boolean" = invoke %8 %9 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
 106                         yield %10;
 107                     }
 108                     ()java.type:"java.lang.String" -> {
 109                         %11 : java.type:"java.lang.String" = constant @"BAZ";
 110                         java.yield %11;
 111                     }
 112                     (%12 : java.type:"java.lang.String")java.type:"boolean" -> {
 113                         %13 : java.type:"java.lang.String" = constant @"BAZ";
 114                         %14 : java.type:"boolean" = invoke %12 %13 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
 115                         yield %14;
 116                     }
 117                     ()java.type:"java.lang.String" -> {
 118                         %15 : java.type:"java.lang.String" = constant @"FOO";
 119                         java.yield %15;
 120                     }
 121                     ()java.type:"boolean" -> {
 122                         %16 : java.type:"boolean" = constant @true;
 123                         yield %16;
 124                     }
 125                     ()java.type:"java.lang.String" -> {
 126                         %17 : java.type:"java.lang.String" = constant @"";
 127                         java.yield %17;
 128                     };
 129                 return %3;
 130             };
 131             """)
 132     @Reflect
 133     public static String caseConstantRuleBlock(String r) {
 134         return switch (r) {
 135             case "FOO" -> {
 136                 yield "BAR";
 137             }
 138             case "BAR" -> {
 139                 yield "BAZ";
 140             }
 141             case "BAZ" -> {
 142                 yield "FOO";
 143             }
 144             default -> {
 145                 yield "";
 146             }
 147         };
 148     }
 149 
 150     @IR("""
 151             func @"caseConstantStatement" (%0 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
 152                 %1 : Var<java.type:"java.lang.String"> = var %0 @"s";
 153                 %2 : java.type:"java.lang.String" = var.load %1;
 154                 %3 : java.type:"java.lang.String" = java.switch.expression %2
 155                     (%4 : java.type:"java.lang.String")java.type:"boolean" -> {
 156                         %5 : java.type:"java.lang.String" = constant @"FOO";
 157                         %6 : java.type:"boolean" = invoke %4 %5 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
 158                         yield %6;
 159                     }
 160                     ()java.type:"java.lang.String" -> {
 161                         %7 : java.type:"java.lang.String" = constant @"BAR";
 162                         java.yield %7;
 163                     }
 164                     (%8 : java.type:"java.lang.String")java.type:"boolean" -> {
 165                         %9 : java.type:"java.lang.String" = constant @"BAR";
 166                         %10 : java.type:"boolean" = invoke %8 %9 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
 167                         yield %10;
 168                     }
 169                     ()java.type:"java.lang.String" -> {
 170                         %11 : java.type:"java.lang.String" = constant @"BAZ";
 171                         java.yield %11;
 172                     }
 173                     (%12 : java.type:"java.lang.String")java.type:"boolean" -> {
 174                         %13 : java.type:"java.lang.String" = constant @"BAZ";
 175                         %14 : java.type:"boolean" = invoke %12 %13 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
 176                         yield %14;
 177                     }
 178                     ()java.type:"java.lang.String" -> {
 179                         %15 : java.type:"java.lang.String" = constant @"FOO";
 180                         java.yield %15;
 181                     }
 182                     ()java.type:"boolean" -> {
 183                         %16 : java.type:"boolean" = constant @true;
 184                         yield %16;
 185                     }
 186                     ()java.type:"java.lang.String" -> {
 187                         %17 : java.type:"java.lang.String" = constant @"";
 188                         java.yield %17;
 189                     };
 190                 return %3;
 191             };
 192             """)
 193     @Reflect
 194     private static String caseConstantStatement(String s) {
 195         return switch (s) {
 196             case "FOO": yield "BAR";
 197             case "BAR": yield "BAZ";
 198             case "BAZ": yield "FOO";
 199             default: yield "";
 200         };
 201     }
 202 
 203     @IR("""
 204             func @"caseConstantMultiLabels" (%0 : java.type:"char")java.type:"java.lang.String" -> {
 205                 %1 : Var<java.type:"char"> = var %0 @"c";
 206                 %2 : java.type:"char" = var.load %1;
 207                 %3 : java.type:"char" = invoke %2 @java.ref:"java.lang.Character::toLowerCase(char):char";
 208                 %4 : java.type:"java.lang.String" = java.switch.expression %3
 209                     (%5 : java.type:"char")java.type:"boolean" -> {
 210                         %6 : java.type:"boolean" = java.cor
 211                             ()java.type:"boolean" -> {
 212                                 %7 : java.type:"char" = constant @'a';
 213                                 %8 : java.type:"boolean" = eq %5 %7;
 214                                 yield %8;
 215                             }
 216                             ()java.type:"boolean" -> {
 217                                 %9 : java.type:"char" = constant @'e';
 218                                 %10 : java.type:"boolean" = eq %5 %9;
 219                                 yield %10;
 220                             }
 221                             ()java.type:"boolean" -> {
 222                                 %11 : java.type:"char" = constant @'i';
 223                                 %12 : java.type:"boolean" = eq %5 %11;
 224                                 yield %12;
 225                             }
 226                             ()java.type:"boolean" -> {
 227                                 %13 : java.type:"char" = constant @'o';
 228                                 %14 : java.type:"boolean" = eq %5 %13;
 229                                 yield %14;
 230                             }
 231                             ()java.type:"boolean" -> {
 232                                 %15 : java.type:"char" = constant @'u';
 233                                 %16 : java.type:"boolean" = eq %5 %15;
 234                                 yield %16;
 235                             };
 236                         yield %6;
 237                     }
 238                     ()java.type:"java.lang.String" -> {
 239                         %17 : java.type:"java.lang.String" = constant @"vowel";
 240                         java.yield %17;
 241                     }
 242                     ()java.type:"boolean" -> {
 243                         %18 : java.type:"boolean" = constant @true;
 244                         yield %18;
 245                     }
 246                     ()java.type:"java.lang.String" -> {
 247                         %19 : java.type:"java.lang.String" = constant @"consonant";
 248                         java.yield %19;
 249                     };
 250                 return %4;
 251             };
 252             """)
 253     @Reflect
 254     private static String caseConstantMultiLabels(char c) {
 255         return switch (Character.toLowerCase(c)) {
 256             case 'a', 'e', 'i', 'o', 'u': yield "vowel";
 257             default: yield "consonant";
 258         };
 259     }
 260 
 261     @IR("""
 262             func @"casePatternMultiLabel" (%0 : java.type:"java.lang.Object")java.type:"java.lang.String" -> {
 263                 %1 : Var<java.type:"java.lang.Object"> = var %0 @"o";
 264                 %2 : java.type:"java.lang.Object" = var.load %1;
 265                 %3 : Var<java.type:"java.lang.Integer"> = var;
 266                 %4 : Var<java.type:"java.lang.Long"> = var;
 267                 %5 : Var<java.type:"java.lang.Character"> = var;
 268                 %6 : Var<java.type:"java.lang.Byte"> = var;
 269                 %7 : Var<java.type:"java.lang.Short"> = var;
 270                 %8 : java.type:"java.lang.String" = java.switch.expression %2
 271                     (%9 : java.type:"java.lang.Object")java.type:"boolean" -> {
 272                         %10 : java.type:"boolean" = java.cor
 273                             ()java.type:"boolean" -> {
 274                                 %11 : java.type:"boolean" = pattern.match %9
 275                                     ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Integer>" -> {
 276                                         %12 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Integer>" = pattern.type;
 277                                         yield %12;
 278                                     }
 279                                     (%13 : java.type:"java.lang.Integer")java.type:"void" -> {
 280                                         var.store %3 %13;
 281                                         yield;
 282                                     };
 283                                 yield %11;
 284                             }
 285                             ()java.type:"boolean" -> {
 286                                 %14 : java.type:"boolean" = pattern.match %9
 287                                     ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Long>" -> {
 288                                         %15 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Long>" = pattern.type;
 289                                         yield %15;
 290                                     }
 291                                     (%16 : java.type:"java.lang.Long")java.type:"void" -> {
 292                                         var.store %4 %16;
 293                                         yield;
 294                                     };
 295                                 yield %14;
 296                             }
 297                             ()java.type:"boolean" -> {
 298                                 %17 : java.type:"boolean" = pattern.match %9
 299                                     ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Character>" -> {
 300                                         %18 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Character>" = pattern.type;
 301                                         yield %18;
 302                                     }
 303                                     (%19 : java.type:"java.lang.Character")java.type:"void" -> {
 304                                         var.store %5 %19;
 305                                         yield;
 306                                     };
 307                                 yield %17;
 308                             }
 309                             ()java.type:"boolean" -> {
 310                                 %20 : java.type:"boolean" = pattern.match %9
 311                                     ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Byte>" -> {
 312                                         %21 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Byte>" = pattern.type;
 313                                         yield %21;
 314                                     }
 315                                     (%22 : java.type:"java.lang.Byte")java.type:"void" -> {
 316                                         var.store %6 %22;
 317                                         yield;
 318                                     };
 319                                 yield %20;
 320                             }
 321                             ()java.type:"boolean" -> {
 322                                 %23 : java.type:"boolean" = pattern.match %9
 323                                     ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Short>" -> {
 324                                         %24 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Short>" = pattern.type;
 325                                         yield %24;
 326                                     }
 327                                     (%25 : java.type:"java.lang.Short")java.type:"void" -> {
 328                                         var.store %7 %25;
 329                                         yield;
 330                                     };
 331                                 yield %23;
 332                             };
 333                         yield %10;
 334                     }
 335                     ()java.type:"java.lang.String" -> {
 336                         %26 : java.type:"java.lang.String" = constant @"integral type";
 337                         yield %26;
 338                     }
 339                     ()java.type:"boolean" -> {
 340                         %27 : java.type:"boolean" = constant @true;
 341                         yield %27;
 342                     }
 343                     ()java.type:"java.lang.String" -> {
 344                         %28 : java.type:"java.lang.String" = constant @"non integral type";
 345                         yield %28;
 346                     };
 347                 return %8;
 348             };
 349             """)
 350     @Reflect
 351     private static String casePatternMultiLabel(Object o) {
 352         return switch (o) {
 353             case Integer _, Long _, Character _, Byte _, Short _-> "integral type";
 354             default -> "non integral type";
 355         };
 356     }
 357 
 358     @IR("""
 359             func @"casePatternGuardedMultiLabel" (%0 : java.type:"java.lang.Object")java.type:"java.lang.String" -> {
 360                 %1 : Var<java.type:"java.lang.Object"> = var %0 @"o";
 361                 %2 : java.type:"java.lang.Object" = var.load %1;
 362                 %3 : Var<java.type:"java.lang.Integer"> = var;
 363                 %4 : Var<java.type:"java.lang.Long"> = var;
 364                 %5 : Var<java.type:"java.lang.Byte"> = var;
 365                 %6 : Var<java.type:"java.lang.Short"> = var;
 366                 %7 : java.type:"java.lang.String" = java.switch.expression %2
 367                     (%8 : java.type:"java.lang.Object")java.type:"boolean" -> {
 368                         %9 : java.type:"boolean" = java.cand
 369                             ()java.type:"boolean" -> {
 370                                 %10 : java.type:"boolean" = java.cor
 371                                     ()java.type:"boolean" -> {
 372                                         %11 : java.type:"boolean" = pattern.match %8
 373                                             ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Integer>" -> {
 374                                                 %12 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Integer>" = pattern.type;
 375                                                 yield %12;
 376                                             }
 377                                             (%13 : java.type:"java.lang.Integer")java.type:"void" -> {
 378                                                 var.store %3 %13;
 379                                                 yield;
 380                                             };
 381                                         yield %11;
 382                                     }
 383                                     ()java.type:"boolean" -> {
 384                                         %14 : java.type:"boolean" = pattern.match %8
 385                                             ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Long>" -> {
 386                                                 %15 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Long>" = pattern.type;
 387                                                 yield %15;
 388                                             }
 389                                             (%16 : java.type:"java.lang.Long")java.type:"void" -> {
 390                                                 var.store %4 %16;
 391                                                 yield;
 392                                             };
 393                                         yield %14;
 394                                     }
 395                                     ()java.type:"boolean" -> {
 396                                         %17 : java.type:"boolean" = pattern.match %8
 397                                             ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Byte>" -> {
 398                                                 %18 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Byte>" = pattern.type;
 399                                                 yield %18;
 400                                             }
 401                                             (%19 : java.type:"java.lang.Byte")java.type:"void" -> {
 402                                                 var.store %5 %19;
 403                                                 yield;
 404                                             };
 405                                         yield %17;
 406                                     }
 407                                     ()java.type:"boolean" -> {
 408                                         %20 : java.type:"boolean" = pattern.match %8
 409                                             ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Short>" -> {
 410                                                 %21 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Short>" = pattern.type;
 411                                                 yield %21;
 412                                             }
 413                                             (%22 : java.type:"java.lang.Short")java.type:"void" -> {
 414                                                 var.store %6 %22;
 415                                                 yield;
 416                                             };
 417                                         yield %20;
 418                                     };
 419                                 yield %10;
 420                             }
 421                             ()java.type:"boolean" -> {
 422                                 %23 : java.type:"java.lang.Object" = var.load %1;
 423                                 %24 : java.type:"java.lang.Number" = cast %23 @java.type:"java.lang.Number";
 424                                 %25 : java.type:"int" = invoke %24 @java.ref:"java.lang.Number::intValue():int";
 425                                 %26 : java.type:"int" = constant @0;
 426                                 %27 : java.type:"boolean" = gt %25 %26;
 427                                 yield %27;
 428                             };
 429                         yield %9;
 430                     }
 431                     ()java.type:"java.lang.String" -> {
 432                         %28 : java.type:"java.lang.String" = constant @"integral type";
 433                         yield %28;
 434                     }
 435                     ()java.type:"boolean" -> {
 436                         %29 : java.type:"boolean" = constant @true;
 437                         yield %29;
 438                     }
 439                     ()java.type:"java.lang.String" -> {
 440                         %30 : java.type:"java.lang.String" = constant @"non integral type";
 441                         yield %30;
 442                     };
 443                 return %7;
 444             };
 445             """)
 446     @Reflect
 447     private static String casePatternGuardedMultiLabel(Object o) {
 448         return switch (o) {
 449             case Integer _, Long _, Byte _, Short _ when ((Number)o).intValue() > 0 -> "integral type";
 450             default -> "non integral type";
 451         };
 452     }
 453 
 454     @IR("""
 455             func @"caseConstantThrow" (%0 : java.type:"java.lang.Integer")java.type:"java.lang.String" -> {
 456                 %1 : Var<java.type:"java.lang.Integer"> = var %0 @"i";
 457                 %2 : java.type:"java.lang.Integer" = var.load %1;
 458                 %3 : java.type:"java.lang.String" = java.switch.expression %2
 459                     (%4 : java.type:"java.lang.Integer")java.type:"boolean" -> {
 460                         %5 : java.type:"int" = invoke %4 @java.ref:"java.lang.Integer::intValue():int";
 461                         %6 : java.type:"int" = constant @8;
 462                         %7 : java.type:"boolean" = eq %5 %6;
 463                         yield %7;
 464                     }
 465                     ()java.type:"java.lang.String" -> {
 466                         %8 : java.type:"java.lang.IllegalArgumentException" = new @java.ref:"java.lang.IllegalArgumentException::()";
 467                         throw %8;
 468                     }
 469                     (%9 : java.type:"java.lang.Integer")java.type:"boolean" -> {
 470                         %10 : java.type:"int" = invoke %9 @java.ref:"java.lang.Integer::intValue():int";
 471                         %11 : java.type:"int" = constant @9;
 472                         %12 : java.type:"boolean" = eq %10 %11;
 473                         yield %12;
 474                     }
 475                     ()java.type:"java.lang.String" -> {
 476                         %13 : java.type:"java.lang.String" = constant @"NINE";
 477                         yield %13;
 478                     }
 479                     ()java.type:"boolean" -> {
 480                         %14 : java.type:"boolean" = constant @true;
 481                         yield %14;
 482                     }
 483                     ()java.type:"java.lang.String" -> {
 484                         %15 : java.type:"java.lang.String" = constant @"An integer";
 485                         yield %15;
 486                     };
 487                 return %3;
 488             };
 489             """)
 490     @Reflect
 491     private static String caseConstantThrow(Integer i) {
 492         return switch (i) {
 493             case 8 -> throw new IllegalArgumentException();
 494             case 9 -> "NINE";
 495             default -> "An integer";
 496         };
 497     }
 498 
 499     @IR("""
 500             func @"caseConstantNullLabel" (%0 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
 501                 %1 : Var<java.type:"java.lang.String"> = var %0 @"s";
 502                 %2 : java.type:"java.lang.String" = var.load %1;
 503                 %3 : java.type:"java.lang.String" = java.switch.expression %2 @switch.handle.nulls=true
 504                     (%4 : java.type:"java.lang.String")java.type:"boolean" -> {
 505                         %5 : java.type:"java.lang.Object" = constant @null;
 506                         %6 : java.type:"boolean" = invoke %4 %5 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
 507                         yield %6;
 508                     }
 509                     ()java.type:"java.lang.String" -> {
 510                         %7 : java.type:"java.lang.String" = constant @"null";
 511                         yield %7;
 512                     }
 513                     ()java.type:"boolean" -> {
 514                         %8 : java.type:"boolean" = constant @true;
 515                         yield %8;
 516                     }
 517                     ()java.type:"java.lang.String" -> {
 518                         %9 : java.type:"java.lang.String" = constant @"non null";
 519                         yield %9;
 520                     };
 521                 return %3;
 522             };
 523             """)
 524     @Reflect
 525     private static String caseConstantNullLabel(String s) {
 526         return switch (s) {
 527             case null -> "null";
 528             default -> "non null";
 529         };
 530     }
 531 
 532     @IR("""
 533             func @"caseConstantNullAndDefault" (%0 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
 534                 %1 : Var<java.type:"java.lang.String"> = var %0 @"s";
 535                 %2 : java.type:"java.lang.String" = var.load %1;
 536                 %3 : java.type:"java.lang.String" = java.switch.expression %2 @switch.handle.nulls=true
 537                     (%4 : java.type:"java.lang.String")java.type:"boolean" -> {
 538                         %5 : java.type:"java.lang.String" = constant @"abc";
 539                         %6 : java.type:"boolean" = invoke %4 %5 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
 540                         yield %6;
 541                     }
 542                     ()java.type:"java.lang.String" -> {
 543                         %7 : java.type:"java.lang.String" = constant @"alphabet";
 544                         yield %7;
 545                     }
 546                     ()java.type:"boolean" -> {
 547                         %8 : java.type:"boolean" = constant @true;
 548                         yield %8;
 549                     }
 550                     ()java.type:"java.lang.String" -> {
 551                         %9 : java.type:"java.lang.String" = constant @"null or default";
 552                         yield %9;
 553                     };
 554                 return %3;
 555             };
 556             """)
 557     @Reflect
 558     private static String caseConstantNullAndDefault(String s) {
 559         return switch (s) {
 560             case "abc" -> "alphabet";
 561             case null, default -> "null or default";
 562         };
 563     }
 564 
 565     @IR("""
 566             func @"caseConstantFallThrough" (%0 : java.type:"char")java.type:"java.lang.String" -> {
 567                 %1 : Var<java.type:"char"> = var %0 @"c";
 568                 %2 : java.type:"char" = var.load %1;
 569                 %3 : java.type:"java.lang.String" = java.switch.expression %2
 570                     (%4 : java.type:"char")java.type:"boolean" -> {
 571                         %5 : java.type:"char" = constant @'A';
 572                         %6 : java.type:"boolean" = eq %4 %5;
 573                         yield %6;
 574                     }
 575                     ()java.type:"java.lang.String" -> {
 576                         java.switch.fallthrough;
 577                     }
 578                     (%7 : java.type:"char")java.type:"boolean" -> {
 579                         %8 : java.type:"char" = constant @'B';
 580                         %9 : java.type:"boolean" = eq %7 %8;
 581                         yield %9;
 582                     }
 583                     ()java.type:"java.lang.String" -> {
 584                         %10 : java.type:"java.lang.String" = constant @"A or B";
 585                         java.yield %10;
 586                     }
 587                     ()java.type:"boolean" -> {
 588                         %11 : java.type:"boolean" = constant @true;
 589                         yield %11;
 590                     }
 591                     ()java.type:"java.lang.String" -> {
 592                         %12 : java.type:"java.lang.String" = constant @"Neither A nor B";
 593                         java.yield %12;
 594                     };
 595                 return %3;
 596             };
 597             """)
 598     @Reflect
 599     private static String caseConstantFallThrough(char c) {
 600         return switch (c) {
 601             case 'A':
 602             case 'B':
 603                 yield "A or B";
 604             default:
 605                 yield "Neither A nor B";
 606         };
 607     }
 608 
 609     enum Day {
 610         MON, TUE, WED, THU, FRI, SAT, SUN
 611     }
 612     @IR("""
 613             func @"caseConstantEnum" (%0 : java.type:"SwitchExpressionTest2$Day")java.type:"int" -> {
 614                 %1 : Var<java.type:"SwitchExpressionTest2$Day"> = var %0 @"d";
 615                 %2 : java.type:"SwitchExpressionTest2$Day" = var.load %1;
 616                 %3 : java.type:"int" = java.switch.expression %2
 617                     (%4 : java.type:"SwitchExpressionTest2$Day")java.type:"boolean" -> {
 618                         %5 : java.type:"boolean" = java.cor
 619                             ()java.type:"boolean" -> {
 620                                 %6 : java.type:"SwitchExpressionTest2$Day" = field.load @java.ref:"SwitchExpressionTest2$Day::MON:SwitchExpressionTest2$Day";
 621                                 %7 : java.type:"boolean" = eq %4 %6;
 622                                 yield %7;
 623                             }
 624                             ()java.type:"boolean" -> {
 625                                 %8 : java.type:"SwitchExpressionTest2$Day" = field.load @java.ref:"SwitchExpressionTest2$Day::FRI:SwitchExpressionTest2$Day";
 626                                 %9 : java.type:"boolean" = eq %4 %8;
 627                                 yield %9;
 628                             }
 629                             ()java.type:"boolean" -> {
 630                                 %10 : java.type:"SwitchExpressionTest2$Day" = field.load @java.ref:"SwitchExpressionTest2$Day::SUN:SwitchExpressionTest2$Day";
 631                                 %11 : java.type:"boolean" = eq %4 %10;
 632                                 yield %11;
 633                             };
 634                         yield %5;
 635                     }
 636                     ()java.type:"int" -> {
 637                         %12 : java.type:"int" = constant @6;
 638                         yield %12;
 639                     }
 640                     (%13 : java.type:"SwitchExpressionTest2$Day")java.type:"boolean" -> {
 641                         %14 : java.type:"SwitchExpressionTest2$Day" = field.load @java.ref:"SwitchExpressionTest2$Day::TUE:SwitchExpressionTest2$Day";
 642                         %15 : java.type:"boolean" = eq %13 %14;
 643                         yield %15;
 644                     }
 645                     ()java.type:"int" -> {
 646                         %16 : java.type:"int" = constant @7;
 647                         yield %16;
 648                     }
 649                     (%17 : java.type:"SwitchExpressionTest2$Day")java.type:"boolean" -> {
 650                         %18 : java.type:"boolean" = java.cor
 651                             ()java.type:"boolean" -> {
 652                                 %19 : java.type:"SwitchExpressionTest2$Day" = field.load @java.ref:"SwitchExpressionTest2$Day::THU:SwitchExpressionTest2$Day";
 653                                 %20 : java.type:"boolean" = eq %17 %19;
 654                                 yield %20;
 655                             }
 656                             ()java.type:"boolean" -> {
 657                                 %21 : java.type:"SwitchExpressionTest2$Day" = field.load @java.ref:"SwitchExpressionTest2$Day::SAT:SwitchExpressionTest2$Day";
 658                                 %22 : java.type:"boolean" = eq %17 %21;
 659                                 yield %22;
 660                             };
 661                         yield %18;
 662                     }
 663                     ()java.type:"int" -> {
 664                         %23 : java.type:"int" = constant @8;
 665                         yield %23;
 666                     }
 667                     (%24 : java.type:"SwitchExpressionTest2$Day")java.type:"boolean" -> {
 668                         %25 : java.type:"SwitchExpressionTest2$Day" = field.load @java.ref:"SwitchExpressionTest2$Day::WED:SwitchExpressionTest2$Day";
 669                         %26 : java.type:"boolean" = eq %24 %25;
 670                         yield %26;
 671                     }
 672                     ()java.type:"int" -> {
 673                         %27 : java.type:"int" = constant @9;
 674                         yield %27;
 675                     }
 676                     ()java.type:"boolean" -> {
 677                         %28 : java.type:"boolean" = constant @true;
 678                         yield %28;
 679                     }
 680                     ()java.type:"int" -> {
 681                         %29 : java.type:"java.lang.String" = constant @null;
 682                         %30 : java.type:"java.lang.Throwable" = constant @null;
 683                         %31 : java.type:"java.lang.MatchException" = new %29 %30 @java.ref:"java.lang.MatchException::(java.lang.String, java.lang.Throwable)";
 684                         throw %31;
 685                     };
 686                 return %3;
 687             };
 688             """)
 689     @Reflect
 690     private static int caseConstantEnum(Day d) {
 691         return switch (d) {
 692             case MON, FRI, SUN -> 6;
 693             case TUE -> 7;
 694             case THU, SAT -> 8;
 695             case WED -> 9;
 696         };
 697     }
 698 
 699     static class Constants {
 700         static final int c1 = 12;
 701     }
 702     @IR("""
 703             func @"caseConstantOtherKindsOfExpr" (%0 : java.type:"int")java.type:"java.lang.String" -> {
 704                 %1 : Var<java.type:"int"> = var %0 @"i";
 705                 %2 : java.type:"int" = constant @11;
 706                 %3 : java.type:"int" = var.load %1;
 707                 %4 : java.type:"java.lang.String" = java.switch.expression %3
 708                     (%5 : java.type:"int")java.type:"boolean" -> {
 709                         %6 : java.type:"int" = constant @1;
 710                         %7 : java.type:"boolean" = eq %5 %6;
 711                         yield %7;
 712                     }
 713                     ()java.type:"java.lang.String" -> {
 714                         %8 : java.type:"java.lang.String" = constant @"1";
 715                         yield %8;
 716                     }
 717                     (%9 : java.type:"int")java.type:"boolean" -> {
 718                         %10 : java.type:"int" = constant @2;
 719                         %11 : java.type:"boolean" = eq %9 %10;
 720                         yield %11;
 721                     }
 722                     ()java.type:"java.lang.String" -> {
 723                         %12 : java.type:"java.lang.String" = constant @"2";
 724                         yield %12;
 725                     }
 726                     (%13 : java.type:"int")java.type:"boolean" -> {
 727                         %14 : java.type:"int" = constant @3;
 728                         %15 : java.type:"boolean" = eq %13 %14;
 729                         yield %15;
 730                     }
 731                     ()java.type:"java.lang.String" -> {
 732                         %16 : java.type:"java.lang.String" = constant @"3";
 733                         yield %16;
 734                     }
 735                     (%17 : java.type:"int")java.type:"boolean" -> {
 736                         %18 : java.type:"int" = constant @4;
 737                         %19 : java.type:"boolean" = eq %17 %18;
 738                         yield %19;
 739                     }
 740                     ()java.type:"java.lang.String" -> {
 741                         %20 : java.type:"java.lang.String" = constant @"4";
 742                         yield %20;
 743                     }
 744                     (%21 : java.type:"int")java.type:"boolean" -> {
 745                         %22 : java.type:"int" = constant @5;
 746                         %23 : java.type:"boolean" = eq %21 %22;
 747                         yield %23;
 748                     }
 749                     ()java.type:"java.lang.String" -> {
 750                         %24 : java.type:"java.lang.String" = constant @"5";
 751                         yield %24;
 752                     }
 753                     (%25 : java.type:"int")java.type:"boolean" -> {
 754                         %26 : java.type:"int" = constant @6;
 755                         %27 : java.type:"boolean" = eq %25 %26;
 756                         yield %27;
 757                     }
 758                     ()java.type:"java.lang.String" -> {
 759                         %28 : java.type:"java.lang.String" = constant @"6";
 760                         yield %28;
 761                     }
 762                     (%29 : java.type:"int")java.type:"boolean" -> {
 763                         %30 : java.type:"int" = constant @7;
 764                         %31 : java.type:"boolean" = eq %29 %30;
 765                         yield %31;
 766                     }
 767                     ()java.type:"java.lang.String" -> {
 768                         %32 : java.type:"java.lang.String" = constant @"7";
 769                         yield %32;
 770                     }
 771                     (%33 : java.type:"int")java.type:"boolean" -> {
 772                         %34 : java.type:"int" = constant @8;
 773                         %35 : java.type:"boolean" = eq %33 %34;
 774                         yield %35;
 775                     }
 776                     ()java.type:"java.lang.String" -> {
 777                         %36 : java.type:"java.lang.String" = constant @"8";
 778                         yield %36;
 779                     }
 780                     (%37 : java.type:"int")java.type:"boolean" -> {
 781                         %38 : java.type:"int" = constant @9;
 782                         %39 : java.type:"boolean" = eq %37 %38;
 783                         yield %39;
 784                     }
 785                     ()java.type:"java.lang.String" -> {
 786                         %40 : java.type:"java.lang.String" = constant @"9";
 787                         yield %40;
 788                     }
 789                     (%41 : java.type:"int")java.type:"boolean" -> {
 790                         %42 : java.type:"int" = constant @10;
 791                         %43 : java.type:"boolean" = eq %41 %42;
 792                         yield %43;
 793                     }
 794                     ()java.type:"java.lang.String" -> {
 795                         %44 : java.type:"java.lang.String" = constant @"10";
 796                         yield %44;
 797                     }
 798                     (%45 : java.type:"int")java.type:"boolean" -> {
 799                         %46 : java.type:"int" = constant @11;
 800                         %47 : java.type:"boolean" = eq %45 %46;
 801                         yield %47;
 802                     }
 803                     ()java.type:"java.lang.String" -> {
 804                         %48 : java.type:"java.lang.String" = constant @"11";
 805                         yield %48;
 806                     }
 807                     (%49 : java.type:"int")java.type:"boolean" -> {
 808                         %50 : java.type:"int" = constant @12;
 809                         %51 : java.type:"boolean" = eq %49 %50;
 810                         yield %51;
 811                     }
 812                     ()java.type:"java.lang.String" -> {
 813                         %52 : java.type:"int" = constant @12;
 814                         %53 : java.type:"java.lang.String" = invoke %52 @java.ref:"java.lang.String::valueOf(int):java.lang.String";
 815                         yield %53;
 816                     }
 817                     (%54 : java.type:"int")java.type:"boolean" -> {
 818                         %55 : java.type:"int" = constant @13;
 819                         %56 : java.type:"boolean" = eq %54 %55;
 820                         yield %56;
 821                     }
 822                     ()java.type:"java.lang.String" -> {
 823                         %57 : java.type:"java.lang.String" = constant @"13";
 824                         yield %57;
 825                     }
 826                     ()java.type:"boolean" -> {
 827                         %58 : java.type:"boolean" = constant @true;
 828                         yield %58;
 829                     }
 830                     ()java.type:"java.lang.String" -> {
 831                         %59 : java.type:"java.lang.String" = constant @"an int";
 832                         yield %59;
 833                     };
 834                 return %4;
 835             };
 836             """)
 837     @Reflect
 838     private static String caseConstantOtherKindsOfExpr(int i) {
 839         final int eleven = 11;
 840         return switch (i) {
 841             case 1 & 0xF -> "1";
 842             case 4>>1 -> "2";
 843             case (int) 3L -> "3";
 844             case 2<<1 -> "4";
 845             case 10 / 2 -> "5";
 846             case 12 - 6 -> "6";
 847             case 3 + 4 -> "7";
 848             case 2 * 2 * 2 -> "8";
 849             case 8 | 1 -> "9";
 850             case (10) -> "10";
 851             case eleven -> "11";
 852             case Constants.c1 -> String.valueOf(Constants.c1);
 853             case 1 > 0 ? 13 : 133 -> "13";
 854             default -> "an int";
 855         };
 856     }
 857 
 858     // these are the conversions that applies in switch
 859 
 860     @IR("""
 861             func @"caseConstantConv" (%0 : java.type:"short")java.type:"java.lang.String" -> {
 862                 %1 : Var<java.type:"short"> = var %0 @"a";
 863                 %2 : java.type:"int" = constant @1;
 864                 %3 : java.type:"short" = conv %2;
 865                 %4 : java.type:"int" = constant @2;
 866                 %5 : java.type:"byte" = conv %4;
 867                 %6 : java.type:"short" = var.load %1;
 868                 %7 : java.type:"java.lang.String" = java.switch.expression %6
 869                     (%8 : java.type:"short")java.type:"boolean" -> {
 870                         %9 : java.type:"short" = constant @1;
 871                         %10 : java.type:"boolean" = eq %8 %9;
 872                         yield %10;
 873                     }
 874                     ()java.type:"java.lang.String" -> {
 875                         %11 : java.type:"java.lang.String" = constant @"one";
 876                         yield %11;
 877                     }
 878                     (%12 : java.type:"short")java.type:"boolean" -> {
 879                         %13 : java.type:"short" = constant @2;
 880                         %14 : java.type:"boolean" = eq %12 %13;
 881                         yield %14;
 882                     }
 883                     ()java.type:"java.lang.String" -> {
 884                         %15 : java.type:"java.lang.String" = constant @"three";
 885                         yield %15;
 886                     }
 887                     (%16 : java.type:"short")java.type:"boolean" -> {
 888                         %17 : java.type:"short" = constant @3;
 889                         %18 : java.type:"boolean" = eq %16 %17;
 890                         yield %18;
 891                     }
 892                     ()java.type:"java.lang.String" -> {
 893                         %19 : java.type:"java.lang.String" = constant @"two";
 894                         yield %19;
 895                     }
 896                     ()java.type:"boolean" -> {
 897                         %20 : java.type:"boolean" = constant @true;
 898                         yield %20;
 899                     }
 900                     ()java.type:"java.lang.String" -> {
 901                         %21 : java.type:"java.lang.String" = constant @"default";
 902                         yield %21;
 903                     };
 904                 return %7;
 905             };
 906             """)
 907     @Reflect
 908     static String caseConstantConv(short a) {
 909         final short s = 1;
 910         final byte b = 2;
 911         return switch (a) {
 912             case s -> "one"; // identity
 913             case b -> "three"; // widening primitive conversion
 914             case 3 -> "two"; // narrowing primitive conversion
 915             default -> "default";
 916         };
 917     }
 918 
 919     @IR("""
 920             func @"caseConstantConv2" (%0 : java.type:"java.lang.Byte")java.type:"java.lang.String" -> {
 921                 %1 : Var<java.type:"java.lang.Byte"> = var %0 @"a";
 922                 %2 : java.type:"int" = constant @2;
 923                 %3 : java.type:"byte" = conv %2;
 924                 %4 : java.type:"java.lang.Byte" = var.load %1;
 925                 %5 : java.type:"java.lang.String" = java.switch.expression %4
 926                     (%6 : java.type:"java.lang.Byte")java.type:"boolean" -> {
 927                         %7 : java.type:"byte" = invoke %6 @java.ref:"java.lang.Byte::byteValue():byte";
 928                         %8 : java.type:"byte" = constant @1;
 929                         %9 : java.type:"boolean" = eq %7 %8;
 930                         yield %9;
 931                     }
 932                     ()java.type:"java.lang.String" -> {
 933                         %10 : java.type:"java.lang.String" = constant @"one";
 934                         yield %10;
 935                     }
 936                     (%11 : java.type:"java.lang.Byte")java.type:"boolean" -> {
 937                         %12 : java.type:"byte" = invoke %11 @java.ref:"java.lang.Byte::byteValue():byte";
 938                         %13 : java.type:"byte" = constant @2;
 939                         %14 : java.type:"boolean" = eq %12 %13;
 940                         yield %14;
 941                     }
 942                     ()java.type:"java.lang.String" -> {
 943                         %15 : java.type:"java.lang.String" = constant @"two";
 944                         yield %15;
 945                     }
 946                     ()java.type:"boolean" -> {
 947                         %16 : java.type:"boolean" = constant @true;
 948                         yield %16;
 949                     }
 950                     ()java.type:"java.lang.String" -> {
 951                         %17 : java.type:"java.lang.String" = constant @"default";
 952                         yield %17;
 953                     };
 954                 return %5;
 955             };
 956             """)
 957     @Reflect
 958     static String caseConstantConv2(Byte a) {
 959         final byte b = 2;
 960         return switch (a) {
 961             // narrowing conv is missing in the code model
 962             case 1 -> "one"; // narrowing primitive conversion followed by a boxing conversion
 963             case b -> "two"; // boxing
 964             default -> "default";
 965         };
 966     }
 967 
 968     enum E { F, G }
 969     @IR("""
 970             func @"noDefaultLabelEnum" (%0 : java.type:"SwitchExpressionTest2$E")java.type:"java.lang.String" -> {
 971                 %1 : Var<java.type:"SwitchExpressionTest2$E"> = var %0 @"e";
 972                 %2 : java.type:"SwitchExpressionTest2$E" = var.load %1;
 973                 %3 : java.type:"java.lang.String" = java.switch.expression %2
 974                     (%4 : java.type:"SwitchExpressionTest2$E")java.type:"boolean" -> {
 975                         %5 : java.type:"SwitchExpressionTest2$E" = field.load @java.ref:"SwitchExpressionTest2$E::F:SwitchExpressionTest2$E";
 976                         %6 : java.type:"boolean" = eq %4 %5;
 977                         yield %6;
 978                     }
 979                     ()java.type:"java.lang.String" -> {
 980                         %7 : java.type:"java.lang.String" = constant @"f";
 981                         yield %7;
 982                     }
 983                     (%8 : java.type:"SwitchExpressionTest2$E")java.type:"boolean" -> {
 984                         %9 : java.type:"SwitchExpressionTest2$E" = field.load @java.ref:"SwitchExpressionTest2$E::G:SwitchExpressionTest2$E";
 985                         %10 : java.type:"boolean" = eq %8 %9;
 986                         yield %10;
 987                     }
 988                     ()java.type:"java.lang.String" -> {
 989                         %11 : java.type:"java.lang.String" = constant @"g";
 990                         yield %11;
 991                     }
 992                     ()java.type:"boolean" -> {
 993                         %12 : java.type:"boolean" = constant @true;
 994                         yield %12;
 995                     }
 996                     ()java.type:"java.lang.String" -> {
 997                         %13 : java.type:"java.lang.String" = constant @null;
 998                         %14 : java.type:"java.lang.Throwable" = constant @null;
 999                         %15 : java.type:"java.lang.MatchException" = new %13 %14 @java.ref:"java.lang.MatchException::(java.lang.String, java.lang.Throwable)";
1000                         throw %15;
1001                     };
1002                 return %3;
1003             };
1004             """)
1005     @Reflect
1006     static String noDefaultLabelEnum(E e) {
1007         return switch (e) {
1008             case F -> "f";
1009             case G -> "g";
1010         };
1011     }
1012 
1013     @IR("""
1014             func @"unconditionalPattern" (%0 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
1015                 %1 : Var<java.type:"java.lang.String"> = var %0 @"s";
1016                 %2 : java.type:"java.lang.String" = var.load %1;
1017                 %3 : Var<java.type:"java.lang.Object"> = var @"o";
1018                 %4 : java.type:"java.lang.String" = java.switch.expression %2
1019                     (%5 : java.type:"java.lang.String")java.type:"boolean" -> {
1020                         %6 : java.type:"java.lang.String" = constant @"A";
1021                         %7 : java.type:"boolean" = invoke %5 %6 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
1022                         yield %7;
1023                     }
1024                     ()java.type:"java.lang.String" -> {
1025                         %8 : java.type:"java.lang.String" = constant @"Alphabet";
1026                         yield %8;
1027                     }
1028                     (%9 : java.type:"java.lang.String")java.type:"boolean" -> {
1029                         %10 : java.type:"boolean" = pattern.match %9
1030                             ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Object>" -> {
1031                                 %11 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Object>" = pattern.type @"o";
1032                                 yield %11;
1033                             }
1034                             (%12 : java.type:"java.lang.Object")java.type:"void" -> {
1035                                 var.store %3 %12;
1036                                 yield;
1037                             };
1038                         yield %10;
1039                     }
1040                     ()java.type:"java.lang.String" -> {
1041                         %13 : java.type:"java.lang.String" = constant @"default";
1042                         yield %13;
1043                     };
1044                 return %4;
1045             };
1046             """)
1047     @Reflect
1048     static String unconditionalPattern(String s) {
1049         return switch (s) {
1050             case "A" -> "Alphabet";
1051             case Object o -> "default";
1052         };
1053     }
1054 
1055     sealed interface A permits B, C {}
1056     record B() implements A {}
1057     final class C implements A {}
1058     @IR("""
1059             func @"noDefault" (%0 : java.type:"SwitchExpressionTest2$A")java.type:"java.lang.String" -> {
1060                 %1 : Var<java.type:"SwitchExpressionTest2$A"> = var %0 @"a";
1061                 %2 : java.type:"SwitchExpressionTest2$A" = var.load %1;
1062                 %3 : Var<java.type:"SwitchExpressionTest2$B"> = var @"b";
1063                 %4 : Var<java.type:"SwitchExpressionTest2::C"> = var @"c";
1064                 %5 : java.type:"java.lang.String" = java.switch.expression %2
1065                     (%6 : java.type:"SwitchExpressionTest2$A")java.type:"boolean" -> {
1066                         %7 : java.type:"boolean" = pattern.match %6
1067                             ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<SwitchExpressionTest2$B>" -> {
1068                                 %8 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<SwitchExpressionTest2$B>" = pattern.type @"b";
1069                                 yield %8;
1070                             }
1071                             (%9 : java.type:"SwitchExpressionTest2$B")java.type:"void" -> {
1072                                 var.store %3 %9;
1073                                 yield;
1074                             };
1075                         yield %7;
1076                     }
1077                     ()java.type:"java.lang.String" -> {
1078                         %10 : java.type:"java.lang.String" = constant @"B";
1079                         yield %10;
1080                     }
1081                     (%11 : java.type:"SwitchExpressionTest2$A")java.type:"boolean" -> {
1082                         %12 : java.type:"boolean" = pattern.match %11
1083                             ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<SwitchExpressionTest2::C>" -> {
1084                                 %13 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<SwitchExpressionTest2::C>" = pattern.type @"c";
1085                                 yield %13;
1086                             }
1087                             (%14 : java.type:"SwitchExpressionTest2::C")java.type:"void" -> {
1088                                 var.store %4 %14;
1089                                 yield;
1090                             };
1091                         yield %12;
1092                     }
1093                     ()java.type:"java.lang.String" -> {
1094                         %15 : java.type:"java.lang.String" = constant @"C";
1095                         yield %15;
1096                     }
1097                     ()java.type:"boolean" -> {
1098                         %16 : java.type:"boolean" = constant @true;
1099                         yield %16;
1100                     }
1101                     ()java.type:"java.lang.String" -> {
1102                         %17 : java.type:"java.lang.String" = constant @null;
1103                         %18 : java.type:"java.lang.Throwable" = constant @null;
1104                         %19 : java.type:"java.lang.MatchException" = new %17 %18 @java.ref:"java.lang.MatchException::(java.lang.String, java.lang.Throwable)";
1105                         throw %19;
1106                     };
1107                 return %5;
1108             };
1109             """)
1110     @Reflect
1111     static String noDefault(A a) {
1112         return switch (a) {
1113             case B b -> "B";
1114             case C c -> "C";
1115         };
1116     }
1117 
1118     @IR("""
1119             func @"defaultNotTheLastLabel" (%0 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
1120                 %1 : Var<java.type:"java.lang.String"> = var %0 @"s";
1121                 %2 : java.type:"java.lang.String" = var.load %1;
1122                 %3 : java.type:"java.lang.String" = java.switch.expression %2
1123                     ()java.type:"boolean" -> {
1124                         %12 : java.type:"boolean" = constant @true;
1125                         yield %12;
1126                     }
1127                     ()java.type:"java.lang.String" -> {
1128                         %13 : java.type:"java.lang.String" = constant @"else";
1129                         yield %13;
1130                     }
1131                     (%4 : java.type:"java.lang.String")java.type:"boolean" -> {
1132                         %5 : java.type:"java.lang.String" = constant @"M";
1133                         %6 : java.type:"boolean" = invoke %4 %5 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
1134                         yield %6;
1135                     }
1136                     ()java.type:"java.lang.String" -> {
1137                         %7 : java.type:"java.lang.String" = constant @"Mow";
1138                         yield %7;
1139                     }
1140                     (%8 : java.type:"java.lang.String")java.type:"boolean" -> {
1141                         %9 : java.type:"java.lang.String" = constant @"A";
1142                         %10 : java.type:"boolean" = invoke %8 %9 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
1143                         yield %10;
1144                     }
1145                     ()java.type:"java.lang.String" -> {
1146                         %11 : java.type:"java.lang.String" = constant @"Aow";
1147                         yield %11;
1148                     };
1149                 return %3;
1150             };
1151             """)
1152     @Reflect
1153     static String defaultNotTheLastLabel(String s) {
1154         return switch (s) {
1155             default -> "else";
1156             case "M" -> "Mow";
1157             case "A" -> "Aow";
1158         };
1159     }
1160 
1161     @IR("""
1162             func @"caseConstantPrimitiveWrapperSelector" (%0 : java.type:"java.lang.Integer")java.type:"java.lang.String" -> {
1163                   %1 : Var<java.type:"java.lang.Integer"> = var %0 @"i";
1164                   %2 : java.type:"java.lang.Integer" = var.load %1;
1165                   %3 : java.type:"java.lang.String" = java.switch.expression %2
1166                       (%4 : java.type:"java.lang.Integer")java.type:"boolean" -> {
1167                           %5 : java.type:"int" = invoke %4 @java.ref:"java.lang.Integer::intValue():int";
1168                           %6 : java.type:"int" = constant @1;
1169                           %7 : java.type:"boolean" = eq %5 %6;
1170                           yield %7;
1171                       }
1172                       ()java.type:"java.lang.String" -> {
1173                           %8 : java.type:"java.lang.String" = constant @"one";
1174                           yield %8;
1175                       }
1176                       (%9 : java.type:"java.lang.Integer")java.type:"boolean" -> {
1177                           %10 : java.type:"boolean" = java.cor
1178                               ()java.type:"boolean" -> {
1179                                   %11 : java.type:"int" = invoke %9 @java.ref:"java.lang.Integer::intValue():int";
1180                                   %12 : java.type:"int" = constant @2;
1181                                   %13 : java.type:"boolean" = eq %11 %12;
1182                                   yield %13;
1183                               }
1184                               ()java.type:"boolean" -> {
1185                                   %14 : java.type:"int" = invoke %9 @java.ref:"java.lang.Integer::intValue():int";
1186                                   %15 : java.type:"int" = constant @3;
1187                                   %16 : java.type:"boolean" = eq %14 %15;
1188                                   yield %16;
1189                               };
1190                           yield %10;
1191                       }
1192                       ()java.type:"java.lang.String" -> {
1193                           %17 : java.type:"java.lang.String" = constant @"two or three";
1194                           yield %17;
1195                       }
1196                       ()java.type:"boolean" -> {
1197                           %18 : java.type:"boolean" = constant @true;
1198                           yield %18;
1199                       }
1200                       ()java.type:"java.lang.String" -> {
1201                           %19 : java.type:"java.lang.String" = constant @"else";
1202                           yield %19;
1203                       };
1204                   return %3;
1205             };
1206             """)
1207     @Reflect
1208     static String caseConstantPrimitiveWrapperSelector(Integer i) {
1209         return switch (i) {
1210             case 1 -> "one";
1211             case 2, 3 -> "two or three";
1212             default -> "else";
1213         };
1214     }
1215 
1216     @IR("""
1217             func @"constantLabelCasted" (%0 : java.type:"int")java.type:"java.lang.String" -> {
1218                 %1 : Var<java.type:"int"> = var %0 @"i";
1219                 %2 : java.type:"int" = var.load %1;
1220                 %3 : java.type:"java.lang.String" = java.switch.expression %2
1221                     (%4 : java.type:"int")java.type:"boolean" -> {
1222                         %5 : java.type:"int" = constant @1;
1223                         %6 : java.type:"boolean" = eq %4 %5;
1224                         yield %6;
1225                     }
1226                     ()java.type:"java.lang.String" -> {
1227                         %7 : java.type:"java.lang.String" = constant @"one";
1228                         yield %7;
1229                     }
1230                     ()java.type:"boolean" -> {
1231                         %8 : java.type:"boolean" = constant @true;
1232                         yield %8;
1233                     }
1234                     ()java.type:"java.lang.String" -> {
1235                         %9 : java.type:"java.lang.String" = constant @"not one";
1236                         yield %9;
1237                     };
1238                 return %3;
1239             };
1240             """)
1241     @Reflect
1242     static String constantLabelCasted(int i) {
1243         return switch (i) {
1244             case (byte) 1 -> "one";
1245             default -> "not one";
1246         };
1247     }
1248 
1249     @IR("""
1250             func @"caseConstantStringLiteral" (%0 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
1251                   %1 : Var<java.type:"java.lang.String"> = var %0 @"s";
1252                   %2 : java.type:"java.lang.String" = var.load %1;
1253                   %3 : java.type:"java.lang.String" = java.switch.expression %2
1254                       (%4 : java.type:"java.lang.String")java.type:"boolean" -> {
1255                           %5 : java.type:"java.lang.String" = constant @"1";
1256                           %6 : java.type:"boolean" = invoke %4 %5 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
1257                           yield %6;
1258                       }
1259                       ()java.type:"java.lang.String" -> {
1260                           %7 : java.type:"java.lang.String" = constant @"one";
1261                           yield %7;
1262                       }
1263                       (%8 : java.type:"java.lang.String")java.type:"boolean" -> {
1264                           %9 : java.type:"boolean" = java.cor
1265                               ()java.type:"boolean" -> {
1266                                   %10 : java.type:"java.lang.String" = constant @"2";
1267                                   %11 : java.type:"boolean" = invoke %8 %10 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
1268                                   yield %11;
1269                               }
1270                               ()java.type:"boolean" -> {
1271                                   %12 : java.type:"java.lang.String" = constant @"3";
1272                                   %13 : java.type:"boolean" = invoke %8 %12 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
1273                                   yield %13;
1274                               };
1275                           yield %9;
1276                       }
1277                       ()java.type:"java.lang.String" -> {
1278                           %14 : java.type:"java.lang.String" = constant @"two or three";
1279                           yield %14;
1280                       }
1281                       ()java.type:"boolean" -> {
1282                           %15 : java.type:"boolean" = constant @true;
1283                           yield %15;
1284                       }
1285                       ()java.type:"java.lang.String" -> {
1286                           %16 : java.type:"java.lang.String" = constant @"else";
1287                           yield %16;
1288                       };
1289                   return %3;
1290               };
1291             """)
1292     @Reflect
1293     static String caseConstantStringLiteral(String s) {
1294         return switch (s) {
1295             case "1" -> "one";
1296             case "2", "3" -> "two or three";
1297             default -> "else";
1298         };
1299     }
1300 
1301     @IR("""
1302             func @"casePatternWithCaseConstant" (%0 : java.type:"int")java.type:"java.lang.String" -> {
1303                 %1 : Var<java.type:"int"> = var %0 @"i";
1304                 %2 : java.type:"int" = var.load %1;
1305                 %3 : Var<java.type:"java.lang.Integer"> = var @"j";
1306                 %4 : Var<java.type:"java.lang.Integer"> = var;
1307                 %5 : java.type:"java.lang.String" = java.switch.expression %2
1308                     (%6 : java.type:"int")java.type:"boolean" -> {
1309                         %7 : java.type:"int" = constant @0;
1310                         %8 : java.type:"boolean" = eq %6 %7;
1311                         yield %8;
1312                     }
1313                     ()java.type:"java.lang.String" -> {
1314                         %9 : java.type:"java.lang.String" = constant @"zero";
1315                         yield %9;
1316                     }
1317                     (%10 : java.type:"int")java.type:"boolean" -> {
1318                         %11 : java.type:"boolean" = java.cand
1319                             ()java.type:"boolean" -> {
1320                                 %12 : java.type:"java.lang.Integer" = invoke %10 @java.ref:"java.lang.Integer::valueOf(int):java.lang.Integer";
1321                                 %13 : java.type:"boolean" = pattern.match %12
1322                                     ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Integer>" -> {
1323                                         %14 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Integer>" = pattern.type @"j";
1324                                         yield %14;
1325                                     }
1326                                     (%15 : java.type:"java.lang.Integer")java.type:"void" -> {
1327                                         var.store %3 %15;
1328                                         yield;
1329                                     };
1330                                 yield %13;
1331                             }
1332                             ()java.type:"boolean" -> {
1333                                 %16 : java.type:"java.lang.Integer" = var.load %3;
1334                                 %17 : java.type:"int" = invoke %16 @java.ref:"java.lang.Integer::intValue():int";
1335                                 %18 : java.type:"int" = constant @0;
1336                                 %19 : java.type:"boolean" = gt %17 %18;
1337                                 yield %19;
1338                             };
1339                         yield %11;
1340                     }
1341                     ()java.type:"java.lang.String" -> {
1342                         %20 : java.type:"java.lang.String" = constant @"positive";
1343                         yield %20;
1344                     }
1345                     (%21 : java.type:"int")java.type:"boolean" -> {
1346                         %22 : java.type:"java.lang.Integer" = invoke %21 @java.ref:"java.lang.Integer::valueOf(int):java.lang.Integer";
1347                         %23 : java.type:"boolean" = pattern.match %22
1348                             ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Integer>" -> {
1349                                 %24 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Integer>" = pattern.type;
1350                                 yield %24;
1351                             }
1352                             (%25 : java.type:"java.lang.Integer")java.type:"void" -> {
1353                                 var.store %4 %25;
1354                                 yield;
1355                             };
1356                         yield %23;
1357                     }
1358                     ()java.type:"java.lang.String" -> {
1359                         %26 : java.type:"java.lang.String" = constant @"negative";
1360                         yield %26;
1361                     };
1362                 return %5;
1363             };
1364             """)
1365     @Reflect
1366     static String casePatternWithCaseConstant(int i) {
1367         return switch (i) {
1368             case 0 -> "zero";
1369             case Integer j when j > 0 -> "positive";
1370             case Integer _ -> "negative";
1371         };
1372     }
1373 }