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 : java.type:"java.lang.Integer" = constant @null;
 266                 %4 : Var<java.type:"java.lang.Integer"> = var %3;
 267                 %5 : java.type:"java.lang.Long" = constant @null;
 268                 %6 : Var<java.type:"java.lang.Long"> = var %5;
 269                 %7 : java.type:"java.lang.Character" = constant @null;
 270                 %8 : Var<java.type:"java.lang.Character"> = var %7;
 271                 %9 : java.type:"java.lang.Byte" = constant @null;
 272                 %10 : Var<java.type:"java.lang.Byte"> = var %9;
 273                 %11 : java.type:"java.lang.Short" = constant @null;
 274                 %12 : Var<java.type:"java.lang.Short"> = var %11;
 275                 %13 : java.type:"java.lang.String" = java.switch.expression %2
 276                     (%14 : java.type:"java.lang.Object")java.type:"boolean" -> {
 277                         %15 : java.type:"boolean" = java.cor
 278                             ()java.type:"boolean" -> {
 279                                 %16 : java.type:"boolean" = pattern.match %14
 280                                     ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Integer>" -> {
 281                                         %17 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Integer>" = pattern.type;
 282                                         yield %17;
 283                                     }
 284                                     (%18 : java.type:"java.lang.Integer")java.type:"void" -> {
 285                                         var.store %4 %18;
 286                                         yield;
 287                                     };
 288                                 yield %16;
 289                             }
 290                             ()java.type:"boolean" -> {
 291                                 %19 : java.type:"boolean" = pattern.match %14
 292                                     ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Long>" -> {
 293                                         %20 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Long>" = pattern.type;
 294                                         yield %20;
 295                                     }
 296                                     (%21 : java.type:"java.lang.Long")java.type:"void" -> {
 297                                         var.store %6 %21;
 298                                         yield;
 299                                     };
 300                                 yield %19;
 301                             }
 302                             ()java.type:"boolean" -> {
 303                                 %22 : java.type:"boolean" = pattern.match %14
 304                                     ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Character>" -> {
 305                                         %23 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Character>" = pattern.type;
 306                                         yield %23;
 307                                     }
 308                                     (%24 : java.type:"java.lang.Character")java.type:"void" -> {
 309                                         var.store %8 %24;
 310                                         yield;
 311                                     };
 312                                 yield %22;
 313                             }
 314                             ()java.type:"boolean" -> {
 315                                 %25 : java.type:"boolean" = pattern.match %14
 316                                     ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Byte>" -> {
 317                                         %26 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Byte>" = pattern.type;
 318                                         yield %26;
 319                                     }
 320                                     (%27 : java.type:"java.lang.Byte")java.type:"void" -> {
 321                                         var.store %10 %27;
 322                                         yield;
 323                                     };
 324                                 yield %25;
 325                             }
 326                             ()java.type:"boolean" -> {
 327                                 %28 : java.type:"boolean" = pattern.match %14
 328                                     ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Short>" -> {
 329                                         %29 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Short>" = pattern.type;
 330                                         yield %29;
 331                                     }
 332                                     (%30 : java.type:"java.lang.Short")java.type:"void" -> {
 333                                         var.store %12 %30;
 334                                         yield;
 335                                     };
 336                                 yield %28;
 337                             };
 338                         yield %15;
 339                     }
 340                     ()java.type:"java.lang.String" -> {
 341                         %31 : java.type:"java.lang.String" = constant @"integral type";
 342                         yield %31;
 343                     }
 344                     ()java.type:"boolean" -> {
 345                         %32 : java.type:"boolean" = constant @true;
 346                         yield %32;
 347                     }
 348                     ()java.type:"java.lang.String" -> {
 349                         %33 : java.type:"java.lang.String" = constant @"non integral type";
 350                         yield %33;
 351                     };
 352                 return %13;
 353             };
 354             """)
 355     @Reflect
 356     private static String casePatternMultiLabel(Object o) {
 357         return switch (o) {
 358             case Integer _, Long _, Character _, Byte _, Short _-> "integral type";
 359             default -> "non integral type";
 360         };
 361     }
 362 
 363     @IR("""
 364             func @"casePatternGuardedMultiLabel" (%0 : java.type:"java.lang.Object")java.type:"java.lang.String" -> {
 365                 %1 : Var<java.type:"java.lang.Object"> = var %0 @"o";
 366                 %2 : java.type:"java.lang.Object" = var.load %1;
 367                 %3 : java.type:"java.lang.Integer" = constant @null;
 368                 %4 : Var<java.type:"java.lang.Integer"> = var %3;
 369                 %5 : java.type:"java.lang.Long" = constant @null;
 370                 %6 : Var<java.type:"java.lang.Long"> = var %5;
 371                 %7 : java.type:"java.lang.Byte" = constant @null;
 372                 %8 : Var<java.type:"java.lang.Byte"> = var %7;
 373                 %9 : java.type:"java.lang.Short" = constant @null;
 374                 %10 : Var<java.type:"java.lang.Short"> = var %9;
 375                 %11 : java.type:"java.lang.String" = java.switch.expression %2
 376                     (%12 : java.type:"java.lang.Object")java.type:"boolean" -> {
 377                         %13 : java.type:"boolean" = java.cand
 378                             ()java.type:"boolean" -> {
 379                                 %14 : java.type:"boolean" = java.cor
 380                                     ()java.type:"boolean" -> {
 381                                         %15 : java.type:"boolean" = pattern.match %12
 382                                             ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Integer>" -> {
 383                                                 %16 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Integer>" = pattern.type;
 384                                                 yield %16;
 385                                             }
 386                                             (%17 : java.type:"java.lang.Integer")java.type:"void" -> {
 387                                                 var.store %4 %17;
 388                                                 yield;
 389                                             };
 390                                         yield %15;
 391                                     }
 392                                     ()java.type:"boolean" -> {
 393                                         %18 : java.type:"boolean" = pattern.match %12
 394                                             ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Long>" -> {
 395                                                 %19 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Long>" = pattern.type;
 396                                                 yield %19;
 397                                             }
 398                                             (%20 : java.type:"java.lang.Long")java.type:"void" -> {
 399                                                 var.store %6 %20;
 400                                                 yield;
 401                                             };
 402                                         yield %18;
 403                                     }
 404                                     ()java.type:"boolean" -> {
 405                                         %21 : java.type:"boolean" = pattern.match %12
 406                                             ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Byte>" -> {
 407                                                 %22 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Byte>" = pattern.type;
 408                                                 yield %22;
 409                                             }
 410                                             (%23 : java.type:"java.lang.Byte")java.type:"void" -> {
 411                                                 var.store %8 %23;
 412                                                 yield;
 413                                             };
 414                                         yield %21;
 415                                     }
 416                                     ()java.type:"boolean" -> {
 417                                         %24 : java.type:"boolean" = pattern.match %12
 418                                             ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Short>" -> {
 419                                                 %25 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Short>" = pattern.type;
 420                                                 yield %25;
 421                                             }
 422                                             (%26 : java.type:"java.lang.Short")java.type:"void" -> {
 423                                                 var.store %10 %26;
 424                                                 yield;
 425                                             };
 426                                         yield %24;
 427                                     };
 428                                 yield %14;
 429                             }
 430                             ()java.type:"boolean" -> {
 431                                 %27 : java.type:"java.lang.Object" = var.load %1;
 432                                 %28 : java.type:"java.lang.Number" = cast %27 @java.type:"java.lang.Number";
 433                                 %29 : java.type:"int" = invoke %28 @java.ref:"java.lang.Number::intValue():int";
 434                                 %30 : java.type:"int" = constant @0;
 435                                 %31 : java.type:"boolean" = gt %29 %30;
 436                                 yield %31;
 437                             };
 438                         yield %13;
 439                     }
 440                     ()java.type:"java.lang.String" -> {
 441                         %32 : java.type:"java.lang.String" = constant @"integral type";
 442                         yield %32;
 443                     }
 444                     ()java.type:"boolean" -> {
 445                         %33 : java.type:"boolean" = constant @true;
 446                         yield %33;
 447                     }
 448                     ()java.type:"java.lang.String" -> {
 449                         %34 : java.type:"java.lang.String" = constant @"non integral type";
 450                         yield %34;
 451                     };
 452                 return %11;
 453             };
 454             """)
 455     @Reflect
 456     private static String casePatternGuardedMultiLabel(Object o) {
 457         return switch (o) {
 458             case Integer _, Long _, Byte _, Short _ when ((Number)o).intValue() > 0 -> "integral type";
 459             default -> "non integral type";
 460         };
 461     }
 462 
 463     @IR("""
 464             func @"caseConstantThrow" (%0 : java.type:"java.lang.Integer")java.type:"java.lang.String" -> {
 465                 %1 : Var<java.type:"java.lang.Integer"> = var %0 @"i";
 466                 %2 : java.type:"java.lang.Integer" = var.load %1;
 467                 %3 : java.type:"java.lang.String" = java.switch.expression %2
 468                     (%4 : java.type:"java.lang.Integer")java.type:"boolean" -> {
 469                         %5 : java.type:"int" = invoke %4 @java.ref:"java.lang.Integer::intValue():int";
 470                         %6 : java.type:"int" = constant @8;
 471                         %7 : java.type:"boolean" = eq %5 %6;
 472                         yield %7;
 473                     }
 474                     ()java.type:"java.lang.String" -> {
 475                         %8 : java.type:"java.lang.IllegalArgumentException" = new @java.ref:"java.lang.IllegalArgumentException::()";
 476                         throw %8;
 477                     }
 478                     (%9 : java.type:"java.lang.Integer")java.type:"boolean" -> {
 479                         %10 : java.type:"int" = invoke %9 @java.ref:"java.lang.Integer::intValue():int";
 480                         %11 : java.type:"int" = constant @9;
 481                         %12 : java.type:"boolean" = eq %10 %11;
 482                         yield %12;
 483                     }
 484                     ()java.type:"java.lang.String" -> {
 485                         %13 : java.type:"java.lang.String" = constant @"NINE";
 486                         yield %13;
 487                     }
 488                     ()java.type:"boolean" -> {
 489                         %14 : java.type:"boolean" = constant @true;
 490                         yield %14;
 491                     }
 492                     ()java.type:"java.lang.String" -> {
 493                         %15 : java.type:"java.lang.String" = constant @"An integer";
 494                         yield %15;
 495                     };
 496                 return %3;
 497             };
 498             """)
 499     @Reflect
 500     private static String caseConstantThrow(Integer i) {
 501         return switch (i) {
 502             case 8 -> throw new IllegalArgumentException();
 503             case 9 -> "NINE";
 504             default -> "An integer";
 505         };
 506     }
 507 
 508     @IR("""
 509             func @"caseConstantNullLabel" (%0 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
 510                 %1 : Var<java.type:"java.lang.String"> = var %0 @"s";
 511                 %2 : java.type:"java.lang.String" = var.load %1;
 512                 %3 : java.type:"java.lang.String" = java.switch.expression %2 @switch.handle.nulls=true
 513                     (%4 : java.type:"java.lang.String")java.type:"boolean" -> {
 514                         %5 : java.type:"java.lang.Object" = constant @null;
 515                         %6 : java.type:"boolean" = invoke %4 %5 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
 516                         yield %6;
 517                     }
 518                     ()java.type:"java.lang.String" -> {
 519                         %7 : java.type:"java.lang.String" = constant @"null";
 520                         yield %7;
 521                     }
 522                     ()java.type:"boolean" -> {
 523                         %8 : java.type:"boolean" = constant @true;
 524                         yield %8;
 525                     }
 526                     ()java.type:"java.lang.String" -> {
 527                         %9 : java.type:"java.lang.String" = constant @"non null";
 528                         yield %9;
 529                     };
 530                 return %3;
 531             };
 532             """)
 533     @Reflect
 534     private static String caseConstantNullLabel(String s) {
 535         return switch (s) {
 536             case null -> "null";
 537             default -> "non null";
 538         };
 539     }
 540 
 541     @IR("""
 542             func @"caseConstantNullAndDefault" (%0 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
 543                 %1 : Var<java.type:"java.lang.String"> = var %0 @"s";
 544                 %2 : java.type:"java.lang.String" = var.load %1;
 545                 %3 : java.type:"java.lang.String" = java.switch.expression %2 @switch.handle.nulls=true
 546                     (%4 : java.type:"java.lang.String")java.type:"boolean" -> {
 547                         %5 : java.type:"java.lang.String" = constant @"abc";
 548                         %6 : java.type:"boolean" = invoke %4 %5 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
 549                         yield %6;
 550                     }
 551                     ()java.type:"java.lang.String" -> {
 552                         %7 : java.type:"java.lang.String" = constant @"alphabet";
 553                         yield %7;
 554                     }
 555                     ()java.type:"boolean" -> {
 556                         %8 : java.type:"boolean" = constant @true;
 557                         yield %8;
 558                     }
 559                     ()java.type:"java.lang.String" -> {
 560                         %9 : java.type:"java.lang.String" = constant @"null or default";
 561                         yield %9;
 562                     };
 563                 return %3;
 564             };
 565             """)
 566     @Reflect
 567     private static String caseConstantNullAndDefault(String s) {
 568         return switch (s) {
 569             case "abc" -> "alphabet";
 570             case null, default -> "null or default";
 571         };
 572     }
 573 
 574     @IR("""
 575             func @"caseConstantFallThrough" (%0 : java.type:"char")java.type:"java.lang.String" -> {
 576                 %1 : Var<java.type:"char"> = var %0 @"c";
 577                 %2 : java.type:"char" = var.load %1;
 578                 %3 : java.type:"java.lang.String" = java.switch.expression %2
 579                     (%4 : java.type:"char")java.type:"boolean" -> {
 580                         %5 : java.type:"char" = constant @'A';
 581                         %6 : java.type:"boolean" = eq %4 %5;
 582                         yield %6;
 583                     }
 584                     ()java.type:"java.lang.String" -> {
 585                         java.switch.fallthrough;
 586                     }
 587                     (%7 : java.type:"char")java.type:"boolean" -> {
 588                         %8 : java.type:"char" = constant @'B';
 589                         %9 : java.type:"boolean" = eq %7 %8;
 590                         yield %9;
 591                     }
 592                     ()java.type:"java.lang.String" -> {
 593                         %10 : java.type:"java.lang.String" = constant @"A or B";
 594                         java.yield %10;
 595                     }
 596                     ()java.type:"boolean" -> {
 597                         %11 : java.type:"boolean" = constant @true;
 598                         yield %11;
 599                     }
 600                     ()java.type:"java.lang.String" -> {
 601                         %12 : java.type:"java.lang.String" = constant @"Neither A nor B";
 602                         java.yield %12;
 603                     };
 604                 return %3;
 605             };
 606             """)
 607     @Reflect
 608     private static String caseConstantFallThrough(char c) {
 609         return switch (c) {
 610             case 'A':
 611             case 'B':
 612                 yield "A or B";
 613             default:
 614                 yield "Neither A nor B";
 615         };
 616     }
 617 
 618     enum Day {
 619         MON, TUE, WED, THU, FRI, SAT, SUN
 620     }
 621     @IR("""
 622             func @"caseConstantEnum" (%0 : java.type:"SwitchExpressionTest2$Day")java.type:"int" -> {
 623                 %1 : Var<java.type:"SwitchExpressionTest2$Day"> = var %0 @"d";
 624                 %2 : java.type:"SwitchExpressionTest2$Day" = var.load %1;
 625                 %3 : java.type:"int" = java.switch.expression %2
 626                     (%4 : java.type:"SwitchExpressionTest2$Day")java.type:"boolean" -> {
 627                         %5 : java.type:"boolean" = java.cor
 628                             ()java.type:"boolean" -> {
 629                                 %6 : java.type:"SwitchExpressionTest2$Day" = field.load @java.ref:"SwitchExpressionTest2$Day::MON:SwitchExpressionTest2$Day";
 630                                 %7 : java.type:"boolean" = eq %4 %6;
 631                                 yield %7;
 632                             }
 633                             ()java.type:"boolean" -> {
 634                                 %8 : java.type:"SwitchExpressionTest2$Day" = field.load @java.ref:"SwitchExpressionTest2$Day::FRI:SwitchExpressionTest2$Day";
 635                                 %9 : java.type:"boolean" = eq %4 %8;
 636                                 yield %9;
 637                             }
 638                             ()java.type:"boolean" -> {
 639                                 %10 : java.type:"SwitchExpressionTest2$Day" = field.load @java.ref:"SwitchExpressionTest2$Day::SUN:SwitchExpressionTest2$Day";
 640                                 %11 : java.type:"boolean" = eq %4 %10;
 641                                 yield %11;
 642                             };
 643                         yield %5;
 644                     }
 645                     ()java.type:"int" -> {
 646                         %12 : java.type:"int" = constant @6;
 647                         yield %12;
 648                     }
 649                     (%13 : java.type:"SwitchExpressionTest2$Day")java.type:"boolean" -> {
 650                         %14 : java.type:"SwitchExpressionTest2$Day" = field.load @java.ref:"SwitchExpressionTest2$Day::TUE:SwitchExpressionTest2$Day";
 651                         %15 : java.type:"boolean" = eq %13 %14;
 652                         yield %15;
 653                     }
 654                     ()java.type:"int" -> {
 655                         %16 : java.type:"int" = constant @7;
 656                         yield %16;
 657                     }
 658                     (%17 : java.type:"SwitchExpressionTest2$Day")java.type:"boolean" -> {
 659                         %18 : java.type:"boolean" = java.cor
 660                             ()java.type:"boolean" -> {
 661                                 %19 : java.type:"SwitchExpressionTest2$Day" = field.load @java.ref:"SwitchExpressionTest2$Day::THU:SwitchExpressionTest2$Day";
 662                                 %20 : java.type:"boolean" = eq %17 %19;
 663                                 yield %20;
 664                             }
 665                             ()java.type:"boolean" -> {
 666                                 %21 : java.type:"SwitchExpressionTest2$Day" = field.load @java.ref:"SwitchExpressionTest2$Day::SAT:SwitchExpressionTest2$Day";
 667                                 %22 : java.type:"boolean" = eq %17 %21;
 668                                 yield %22;
 669                             };
 670                         yield %18;
 671                     }
 672                     ()java.type:"int" -> {
 673                         %23 : java.type:"int" = constant @8;
 674                         yield %23;
 675                     }
 676                     (%24 : java.type:"SwitchExpressionTest2$Day")java.type:"boolean" -> {
 677                         %25 : java.type:"SwitchExpressionTest2$Day" = field.load @java.ref:"SwitchExpressionTest2$Day::WED:SwitchExpressionTest2$Day";
 678                         %26 : java.type:"boolean" = eq %24 %25;
 679                         yield %26;
 680                     }
 681                     ()java.type:"int" -> {
 682                         %27 : java.type:"int" = constant @9;
 683                         yield %27;
 684                     }
 685                     ()java.type:"boolean" -> {
 686                         %28 : java.type:"boolean" = constant @true;
 687                         yield %28;
 688                     }
 689                     ()java.type:"int" -> {
 690                         %29 : java.type:"java.lang.String" = constant @null;
 691                         %30 : java.type:"java.lang.Throwable" = constant @null;
 692                         %31 : java.type:"java.lang.MatchException" = new %29 %30 @java.ref:"java.lang.MatchException::(java.lang.String, java.lang.Throwable)";
 693                         throw %31;
 694                     };
 695                 return %3;
 696             };
 697             """)
 698     @Reflect
 699     private static int caseConstantEnum(Day d) {
 700         return switch (d) {
 701             case MON, FRI, SUN -> 6;
 702             case TUE -> 7;
 703             case THU, SAT -> 8;
 704             case WED -> 9;
 705         };
 706     }
 707 
 708     static class Constants {
 709         static final int c1 = 12;
 710     }
 711     @IR("""
 712             func @"caseConstantOtherKindsOfExpr" (%0 : java.type:"int")java.type:"java.lang.String" -> {
 713                 %1 : Var<java.type:"int"> = var %0 @"i";
 714                 %2 : java.type:"int" = constant @11;
 715                 %3 : Var<java.type:"int"> = var %2 @"eleven";
 716                 %4 : java.type:"int" = var.load %1;
 717                 %5 : java.type:"java.lang.String" = java.switch.expression %4
 718                     (%6 : java.type:"int")java.type:"boolean" -> {
 719                         %7 : java.type:"int" = constant @1;
 720                         %8 : java.type:"int" = constant @15;
 721                         %9 : java.type:"int" = and %7 %8;
 722                         %10 : java.type:"boolean" = eq %6 %9;
 723                         yield %10;
 724                     }
 725                     ()java.type:"java.lang.String" -> {
 726                         %11 : java.type:"java.lang.String" = constant @"1";
 727                         yield %11;
 728                     }
 729                     (%12 : java.type:"int")java.type:"boolean" -> {
 730                         %13 : java.type:"int" = constant @4;
 731                         %14 : java.type:"int" = constant @1;
 732                         %15 : java.type:"int" = ashr %13 %14;
 733                         %16 : java.type:"boolean" = eq %12 %15;
 734                         yield %16;
 735                     }
 736                     ()java.type:"java.lang.String" -> {
 737                         %17 : java.type:"java.lang.String" = constant @"2";
 738                         yield %17;
 739                     }
 740                     (%18 : java.type:"int")java.type:"boolean" -> {
 741                         %19 : java.type:"long" = constant @3;
 742                         %20 : java.type:"int" = conv %19;
 743                         %21 : java.type:"boolean" = eq %18 %20;
 744                         yield %21;
 745                     }
 746                     ()java.type:"java.lang.String" -> {
 747                         %22 : java.type:"java.lang.String" = constant @"3";
 748                         yield %22;
 749                     }
 750                     (%23 : java.type:"int")java.type:"boolean" -> {
 751                         %24 : java.type:"int" = constant @2;
 752                         %25 : java.type:"int" = constant @1;
 753                         %26 : java.type:"int" = lshl %24 %25;
 754                         %27 : java.type:"boolean" = eq %23 %26;
 755                         yield %27;
 756                     }
 757                     ()java.type:"java.lang.String" -> {
 758                         %28 : java.type:"java.lang.String" = constant @"4";
 759                         yield %28;
 760                     }
 761                     (%29 : java.type:"int")java.type:"boolean" -> {
 762                         %30 : java.type:"int" = constant @10;
 763                         %31 : java.type:"int" = constant @2;
 764                         %32 : java.type:"int" = div %30 %31;
 765                         %33 : java.type:"boolean" = eq %29 %32;
 766                         yield %33;
 767                     }
 768                     ()java.type:"java.lang.String" -> {
 769                         %34 : java.type:"java.lang.String" = constant @"5";
 770                         yield %34;
 771                     }
 772                     (%35 : java.type:"int")java.type:"boolean" -> {
 773                         %36 : java.type:"int" = constant @12;
 774                         %37 : java.type:"int" = constant @6;
 775                         %38 : java.type:"int" = sub %36 %37;
 776                         %39 : java.type:"boolean" = eq %35 %38;
 777                         yield %39;
 778                     }
 779                     ()java.type:"java.lang.String" -> {
 780                         %40 : java.type:"java.lang.String" = constant @"6";
 781                         yield %40;
 782                     }
 783                     (%41 : java.type:"int")java.type:"boolean" -> {
 784                         %42 : java.type:"int" = constant @3;
 785                         %43 : java.type:"int" = constant @4;
 786                         %44 : java.type:"int" = add %42 %43;
 787                         %45 : java.type:"boolean" = eq %41 %44;
 788                         yield %45;
 789                     }
 790                     ()java.type:"java.lang.String" -> {
 791                         %46 : java.type:"java.lang.String" = constant @"7";
 792                         yield %46;
 793                     }
 794                     (%47 : java.type:"int")java.type:"boolean" -> {
 795                         %48 : java.type:"int" = constant @2;
 796                         %49 : java.type:"int" = constant @2;
 797                         %50 : java.type:"int" = mul %48 %49;
 798                         %51 : java.type:"int" = constant @2;
 799                         %52 : java.type:"int" = mul %50 %51;
 800                         %53 : java.type:"boolean" = eq %47 %52;
 801                         yield %53;
 802                     }
 803                     ()java.type:"java.lang.String" -> {
 804                         %54 : java.type:"java.lang.String" = constant @"8";
 805                         yield %54;
 806                     }
 807                     (%55 : java.type:"int")java.type:"boolean" -> {
 808                         %56 : java.type:"int" = constant @8;
 809                         %57 : java.type:"int" = constant @1;
 810                         %58 : java.type:"int" = or %56 %57;
 811                         %59 : java.type:"boolean" = eq %55 %58;
 812                         yield %59;
 813                     }
 814                     ()java.type:"java.lang.String" -> {
 815                         %60 : java.type:"java.lang.String" = constant @"9";
 816                         yield %60;
 817                     }
 818                     (%61 : java.type:"int")java.type:"boolean" -> {
 819                         %62 : java.type:"int" = constant @10;
 820                         %63 : java.type:"boolean" = eq %61 %62;
 821                         yield %63;
 822                     }
 823                     ()java.type:"java.lang.String" -> {
 824                         %64 : java.type:"java.lang.String" = constant @"10";
 825                         yield %64;
 826                     }
 827                     (%65 : java.type:"int")java.type:"boolean" -> {
 828                         %66 : java.type:"int" = var.load %3;
 829                         %67 : java.type:"boolean" = eq %65 %66;
 830                         yield %67;
 831                     }
 832                     ()java.type:"java.lang.String" -> {
 833                         %68 : java.type:"java.lang.String" = constant @"11";
 834                         yield %68;
 835                     }
 836                     (%69 : java.type:"int")java.type:"boolean" -> {
 837                         %70 : java.type:"int" = field.load @java.ref:"SwitchExpressionTest2$Constants::c1:int";
 838                         %71 : java.type:"boolean" = eq %69 %70;
 839                         yield %71;
 840                     }
 841                     ()java.type:"java.lang.String" -> {
 842                         %72 : java.type:"int" = field.load @java.ref:"SwitchExpressionTest2$Constants::c1:int";
 843                         %73 : java.type:"java.lang.String" = invoke %72 @java.ref:"java.lang.String::valueOf(int):java.lang.String";
 844                         yield %73;
 845                     }
 846                     (%74 : java.type:"int")java.type:"boolean" -> {
 847                         %75 : java.type:"int" = java.cexpression
 848                             ()java.type:"boolean" -> {
 849                                 %76 : java.type:"int" = constant @1;
 850                                 %77 : java.type:"int" = constant @0;
 851                                 %78 : java.type:"boolean" = gt %76 %77;
 852                                 yield %78;
 853                             }
 854                             ()java.type:"int" -> {
 855                                 %79 : java.type:"int" = constant @13;
 856                                 yield %79;
 857                             }
 858                             ()java.type:"int" -> {
 859                                 %80 : java.type:"int" = constant @133;
 860                                 yield %80;
 861                             };
 862                         %81 : java.type:"boolean" = eq %74 %75;
 863                         yield %81;
 864                     }
 865                     ()java.type:"java.lang.String" -> {
 866                         %82 : java.type:"java.lang.String" = constant @"13";
 867                         yield %82;
 868                     }
 869                     ()java.type:"boolean" -> {
 870                         %83 : java.type:"boolean" = constant @true;
 871                         yield %83;
 872                     }
 873                     ()java.type:"java.lang.String" -> {
 874                         %84 : java.type:"java.lang.String" = constant @"an int";
 875                         yield %84;
 876                     };
 877                 return %5;
 878             };
 879             """)
 880     @Reflect
 881     private static String caseConstantOtherKindsOfExpr(int i) {
 882         final int eleven = 11;
 883         return switch (i) {
 884             case 1 & 0xF -> "1";
 885             case 4>>1 -> "2";
 886             case (int) 3L -> "3";
 887             case 2<<1 -> "4";
 888             case 10 / 2 -> "5";
 889             case 12 - 6 -> "6";
 890             case 3 + 4 -> "7";
 891             case 2 * 2 * 2 -> "8";
 892             case 8 | 1 -> "9";
 893             case (10) -> "10";
 894             case eleven -> "11";
 895             case Constants.c1 -> String.valueOf(Constants.c1);
 896             case 1 > 0 ? 13 : 133 -> "13";
 897             default -> "an int";
 898         };
 899     }
 900 
 901     // these are the conversions that applies in switch
 902 
 903     @IR("""
 904             func @"caseConstantConv" (%0 : java.type:"short")java.type:"java.lang.String" -> {
 905                 %1 : Var<java.type:"short"> = var %0 @"a";
 906                 %2 : java.type:"int" = constant @1;
 907                 %3 : java.type:"short" = conv %2;
 908                 %4 : Var<java.type:"short"> = var %3 @"s";
 909                 %5 : java.type:"int" = constant @2;
 910                 %6 : java.type:"byte" = conv %5;
 911                 %7 : Var<java.type:"byte"> = var %6 @"b";
 912                 %8 : java.type:"short" = var.load %1;
 913                 %9 : java.type:"java.lang.String" = java.switch.expression %8
 914                     (%10 : java.type:"short")java.type:"boolean" -> {
 915                         %11 : java.type:"short" = var.load %4;
 916                         %12 : java.type:"boolean" = eq %10 %11;
 917                         yield %12;
 918                     }
 919                     ()java.type:"java.lang.String" -> {
 920                         %13 : java.type:"java.lang.String" = constant @"one";
 921                         yield %13;
 922                     }
 923                     (%14 : java.type:"short")java.type:"boolean" -> {
 924                         %15 : java.type:"byte" = var.load %7;
 925                         %16 : java.type:"short" = conv %15;
 926                         %17 : java.type:"boolean" = eq %14 %16;
 927                         yield %17;
 928                     }
 929                     ()java.type:"java.lang.String" -> {
 930                         %18 : java.type:"java.lang.String" = constant @"three";
 931                         yield %18;
 932                     }
 933                     (%19 : java.type:"short")java.type:"boolean" -> {
 934                         %20 : java.type:"int" = constant @3;
 935                         %21 : java.type:"short" = conv %20;
 936                         %22 : java.type:"boolean" = eq %19 %21;
 937                         yield %22;
 938                     }
 939                     ()java.type:"java.lang.String" -> {
 940                         %23 : java.type:"java.lang.String" = constant @"two";
 941                         yield %23;
 942                     }
 943                     ()java.type:"boolean" -> {
 944                         %24 : java.type:"boolean" = constant @true;
 945                         yield %24;
 946                     }
 947                     ()java.type:"java.lang.String" -> {
 948                         %25 : java.type:"java.lang.String" = constant @"default";
 949                         yield %25;
 950                     };
 951                 return %9;
 952             };
 953             """)
 954     @Reflect
 955     static String caseConstantConv(short a) {
 956         final short s = 1;
 957         final byte b = 2;
 958         return switch (a) {
 959             case s -> "one"; // identity
 960             case b -> "three"; // widening primitive conversion
 961             case 3 -> "two"; // narrowing primitive conversion
 962             default -> "default";
 963         };
 964     }
 965 
 966     @IR("""
 967             func @"caseConstantConv2" (%0 : java.type:"java.lang.Byte")java.type:"java.lang.String" -> {
 968                 %1 : Var<java.type:"java.lang.Byte"> = var %0 @"a";
 969                 %2 : java.type:"int" = constant @2;
 970                 %3 : java.type:"byte" = conv %2;
 971                 %4 : Var<java.type:"byte"> = var %3 @"b";
 972                 %5 : java.type:"java.lang.Byte" = var.load %1;
 973                 %6 : java.type:"java.lang.String" = java.switch.expression %5
 974                     (%7 : java.type:"java.lang.Byte")java.type:"boolean" -> {
 975                         %8 : java.type:"byte" = invoke %7 @java.ref:"java.lang.Byte::byteValue():byte";
 976                         %9 : java.type:"int" = constant @1;
 977                         %10 : java.type:"byte" = conv %9;
 978                         %11 : java.type:"boolean" = eq %8 %10;
 979                         yield %11;
 980                     }
 981                     ()java.type:"java.lang.String" -> {
 982                         %11 : java.type:"java.lang.String" = constant @"one";
 983                         yield %11;
 984                     }
 985                     (%13 : java.type:"java.lang.Byte")java.type:"boolean" -> {
 986                         %14 : java.type:"byte" = invoke %13 @java.ref:"java.lang.Byte::byteValue():byte";
 987                         %15 : java.type:"byte" = var.load %4;
 988                         %16 : java.type:"boolean" = eq %14 %15;
 989                         yield %16;
 990                     }
 991                     ()java.type:"java.lang.String" -> {
 992                         %17 : java.type:"java.lang.String" = constant @"two";
 993                         yield %17;
 994                     }
 995                     ()java.type:"boolean" -> {
 996                         %18 : java.type:"boolean" = constant @true;
 997                         yield %18;
 998                     }
 999                     ()java.type:"java.lang.String" -> {
1000                         %19 : java.type:"java.lang.String" = constant @"default";
1001                         yield %19;
1002                     };
1003                 return %6;
1004             };
1005             """)
1006     @Reflect
1007     static String caseConstantConv2(Byte a) {
1008         final byte b = 2;
1009         return switch (a) {
1010             // narrowing conv is missing in the code model
1011             case 1 -> "one"; // narrowing primitive conversion followed by a boxing conversion
1012             case b -> "two"; // boxing
1013             default -> "default";
1014         };
1015     }
1016 
1017     enum E { F, G }
1018     @IR("""
1019             func @"noDefaultLabelEnum" (%0 : java.type:"SwitchExpressionTest2$E")java.type:"java.lang.String" -> {
1020                 %1 : Var<java.type:"SwitchExpressionTest2$E"> = var %0 @"e";
1021                 %2 : java.type:"SwitchExpressionTest2$E" = var.load %1;
1022                 %3 : java.type:"java.lang.String" = java.switch.expression %2
1023                     (%4 : java.type:"SwitchExpressionTest2$E")java.type:"boolean" -> {
1024                         %5 : java.type:"SwitchExpressionTest2$E" = field.load @java.ref:"SwitchExpressionTest2$E::F:SwitchExpressionTest2$E";
1025                         %6 : java.type:"boolean" = eq %4 %5;
1026                         yield %6;
1027                     }
1028                     ()java.type:"java.lang.String" -> {
1029                         %7 : java.type:"java.lang.String" = constant @"f";
1030                         yield %7;
1031                     }
1032                     (%8 : java.type:"SwitchExpressionTest2$E")java.type:"boolean" -> {
1033                         %9 : java.type:"SwitchExpressionTest2$E" = field.load @java.ref:"SwitchExpressionTest2$E::G:SwitchExpressionTest2$E";
1034                         %10 : java.type:"boolean" = eq %8 %9;
1035                         yield %10;
1036                     }
1037                     ()java.type:"java.lang.String" -> {
1038                         %11 : java.type:"java.lang.String" = constant @"g";
1039                         yield %11;
1040                     }
1041                     ()java.type:"boolean" -> {
1042                         %12 : java.type:"boolean" = constant @true;
1043                         yield %12;
1044                     }
1045                     ()java.type:"java.lang.String" -> {
1046                         %13 : java.type:"java.lang.String" = constant @null;
1047                         %14 : java.type:"java.lang.Throwable" = constant @null;
1048                         %15 : java.type:"java.lang.MatchException" = new %13 %14 @java.ref:"java.lang.MatchException::(java.lang.String, java.lang.Throwable)";
1049                         throw %15;
1050                     };
1051                 return %3;
1052             };
1053             """)
1054     @Reflect
1055     static String noDefaultLabelEnum(E e) {
1056         return switch (e) {
1057             case F -> "f";
1058             case G -> "g";
1059         };
1060     }
1061 
1062     @IR("""
1063             func @"unconditionalPattern" (%0 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
1064                 %1 : Var<java.type:"java.lang.String"> = var %0 @"s";
1065                 %2 : java.type:"java.lang.String" = var.load %1;
1066                 %3 : java.type:"java.lang.Object" = constant @null;
1067                 %4 : Var<java.type:"java.lang.Object"> = var %3 @"o";
1068                 %5 : java.type:"java.lang.String" = java.switch.expression %2
1069                     (%6 : java.type:"java.lang.String")java.type:"boolean" -> {
1070                         %7 : java.type:"java.lang.String" = constant @"A";
1071                         %8 : java.type:"boolean" = invoke %6 %7 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
1072                         yield %8;
1073                     }
1074                     ()java.type:"java.lang.String" -> {
1075                         %9 : java.type:"java.lang.String" = constant @"Alphabet";
1076                         yield %9;
1077                     }
1078                     (%10 : java.type:"java.lang.String")java.type:"boolean" -> {
1079                         %11 : java.type:"boolean" = pattern.match %10
1080                             ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Object>" -> {
1081                                 %12 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Object>" = pattern.type @"o";
1082                                 yield %12;
1083                             }
1084                             (%13 : java.type:"java.lang.Object")java.type:"void" -> {
1085                                 var.store %4 %13;
1086                                 yield;
1087                             };
1088                         yield %11;
1089                     }
1090                     ()java.type:"java.lang.String" -> {
1091                         %14 : java.type:"java.lang.String" = constant @"default";
1092                         yield %14;
1093                     };
1094                 return %5;
1095             };
1096             """)
1097     @Reflect
1098     static String unconditionalPattern(String s) {
1099         return switch (s) {
1100             case "A" -> "Alphabet";
1101             case Object o -> "default";
1102         };
1103     }
1104 
1105     sealed interface A permits B, C {}
1106     record B() implements A {}
1107     final class C implements A {}
1108     @IR("""
1109             func @"noDefault" (%0 : java.type:"SwitchExpressionTest2$A")java.type:"java.lang.String" -> {
1110                 %1 : Var<java.type:"SwitchExpressionTest2$A"> = var %0 @"a";
1111                 %2 : java.type:"SwitchExpressionTest2$A" = var.load %1;
1112                 %3 : java.type:"SwitchExpressionTest2$B" = constant @null;
1113                 %4 : Var<java.type:"SwitchExpressionTest2$B"> = var %3 @"b";
1114                 %5 : java.type:"SwitchExpressionTest2::C" = constant @null;
1115                 %6 : Var<java.type:"SwitchExpressionTest2::C"> = var %5 @"c";
1116                 %7 : java.type:"java.lang.String" = java.switch.expression %2
1117                     (%8 : java.type:"SwitchExpressionTest2$A")java.type:"boolean" -> {
1118                         %9 : java.type:"boolean" = pattern.match %8
1119                             ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<SwitchExpressionTest2$B>" -> {
1120                                 %10 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<SwitchExpressionTest2$B>" = pattern.type @"b";
1121                                 yield %10;
1122                             }
1123                             (%11 : java.type:"SwitchExpressionTest2$B")java.type:"void" -> {
1124                                 var.store %4 %11;
1125                                 yield;
1126                             };
1127                         yield %9;
1128                     }
1129                     ()java.type:"java.lang.String" -> {
1130                         %12 : java.type:"java.lang.String" = constant @"B";
1131                         yield %12;
1132                     }
1133                     (%13 : java.type:"SwitchExpressionTest2$A")java.type:"boolean" -> {
1134                         %14 : java.type:"boolean" = pattern.match %13
1135                             ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<SwitchExpressionTest2::C>" -> {
1136                                 %15 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<SwitchExpressionTest2::C>" = pattern.type @"c";
1137                                 yield %15;
1138                             }
1139                             (%16 : java.type:"SwitchExpressionTest2::C")java.type:"void" -> {
1140                                 var.store %6 %16;
1141                                 yield;
1142                             };
1143                         yield %14;
1144                     }
1145                     ()java.type:"java.lang.String" -> {
1146                         %17 : java.type:"java.lang.String" = constant @"C";
1147                         yield %17;
1148                     }
1149                     ()java.type:"boolean" -> {
1150                         %18 : java.type:"boolean" = constant @true;
1151                         yield %18;
1152                     }
1153                     ()java.type:"java.lang.String" -> {
1154                         %19 : java.type:"java.lang.String" = constant @null;
1155                         %20 : java.type:"java.lang.Throwable" = constant @null;
1156                         %21 : java.type:"java.lang.MatchException" = new %19 %20 @java.ref:"java.lang.MatchException::(java.lang.String, java.lang.Throwable)";
1157                         throw %21;
1158                     };
1159                 return %7;
1160             };
1161             """)
1162     @Reflect
1163     static String noDefault(A a) {
1164         return switch (a) {
1165             case B b -> "B";
1166             case C c -> "C";
1167         };
1168     }
1169 
1170     @IR("""
1171             func @"defaultNotTheLastLabel" (%0 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
1172                 %1 : Var<java.type:"java.lang.String"> = var %0 @"s";
1173                 %2 : java.type:"java.lang.String" = var.load %1;
1174                 %3 : java.type:"java.lang.String" = java.switch.expression %2
1175                     ()java.type:"boolean" -> {
1176                         %12 : java.type:"boolean" = constant @true;
1177                         yield %12;
1178                     }
1179                     ()java.type:"java.lang.String" -> {
1180                         %13 : java.type:"java.lang.String" = constant @"else";
1181                         yield %13;
1182                     }
1183                     (%4 : java.type:"java.lang.String")java.type:"boolean" -> {
1184                         %5 : java.type:"java.lang.String" = constant @"M";
1185                         %6 : java.type:"boolean" = invoke %4 %5 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
1186                         yield %6;
1187                     }
1188                     ()java.type:"java.lang.String" -> {
1189                         %7 : java.type:"java.lang.String" = constant @"Mow";
1190                         yield %7;
1191                     }
1192                     (%8 : java.type:"java.lang.String")java.type:"boolean" -> {
1193                         %9 : java.type:"java.lang.String" = constant @"A";
1194                         %10 : java.type:"boolean" = invoke %8 %9 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
1195                         yield %10;
1196                     }
1197                     ()java.type:"java.lang.String" -> {
1198                         %11 : java.type:"java.lang.String" = constant @"Aow";
1199                         yield %11;
1200                     };
1201                 return %3;
1202             };
1203             """)
1204     @Reflect
1205     static String defaultNotTheLastLabel(String s) {
1206         return switch (s) {
1207             default -> "else";
1208             case "M" -> "Mow";
1209             case "A" -> "Aow";
1210         };
1211     }
1212 
1213     @IR("""
1214             func @"caseConstantPrimitiveWrapperSelector" (%0 : java.type:"java.lang.Integer")java.type:"java.lang.String" -> {
1215                   %1 : Var<java.type:"java.lang.Integer"> = var %0 @"i";
1216                   %2 : java.type:"java.lang.Integer" = var.load %1;
1217                   %3 : java.type:"java.lang.String" = java.switch.expression %2
1218                       (%4 : java.type:"java.lang.Integer")java.type:"boolean" -> {
1219                           %5 : java.type:"int" = invoke %4 @java.ref:"java.lang.Integer::intValue():int";
1220                           %6 : java.type:"int" = constant @1;
1221                           %7 : java.type:"boolean" = eq %5 %6;
1222                           yield %7;
1223                       }
1224                       ()java.type:"java.lang.String" -> {
1225                           %8 : java.type:"java.lang.String" = constant @"one";
1226                           yield %8;
1227                       }
1228                       (%9 : java.type:"java.lang.Integer")java.type:"boolean" -> {
1229                           %10 : java.type:"boolean" = java.cor
1230                               ()java.type:"boolean" -> {
1231                                   %11 : java.type:"int" = invoke %9 @java.ref:"java.lang.Integer::intValue():int";
1232                                   %12 : java.type:"int" = constant @2;
1233                                   %13 : java.type:"boolean" = eq %11 %12;
1234                                   yield %13;
1235                               }
1236                               ()java.type:"boolean" -> {
1237                                   %14 : java.type:"int" = invoke %9 @java.ref:"java.lang.Integer::intValue():int";
1238                                   %15 : java.type:"int" = constant @3;
1239                                   %16 : java.type:"boolean" = eq %14 %15;
1240                                   yield %16;
1241                               };
1242                           yield %10;
1243                       }
1244                       ()java.type:"java.lang.String" -> {
1245                           %17 : java.type:"java.lang.String" = constant @"two or three";
1246                           yield %17;
1247                       }
1248                       ()java.type:"boolean" -> {
1249                           %18 : java.type:"boolean" = constant @true;
1250                           yield %18;
1251                       }
1252                       ()java.type:"java.lang.String" -> {
1253                           %19 : java.type:"java.lang.String" = constant @"else";
1254                           yield %19;
1255                       };
1256                   return %3;
1257             };
1258             """)
1259     @Reflect
1260     static String caseConstantPrimitiveWrapperSelector(Integer i) {
1261         return switch (i) {
1262             case 1 -> "one";
1263             case 2, 3 -> "two or three";
1264             default -> "else";
1265         };
1266     }
1267 
1268     @IR("""
1269             func @"constantLabelCasted" (%0 : java.type:"int")java.type:"java.lang.String" -> {
1270                   %1 : Var<java.type:"int"> = var %0 @"i";
1271                   %2 : java.type:"int" = var.load %1;
1272                   %3 : java.type:"java.lang.String" = java.switch.expression %2
1273                       (%4 : java.type:"int")java.type:"boolean" -> {
1274                           %5 : java.type:"int" = constant @1;
1275                           %6 : java.type:"byte" = conv %5;
1276                           %7 : java.type:"int" = conv %6;
1277                           %8 : java.type:"boolean" = eq %4 %7;
1278                           yield %8;
1279                       }
1280                       ()java.type:"java.lang.String" -> {
1281                           %9 : java.type:"java.lang.String" = constant @"one";
1282                           yield %9;
1283                       }
1284                       ()java.type:"boolean" -> {
1285                           %10 : java.type:"boolean" = constant @true;
1286                           yield %10;
1287                       }
1288                       ()java.type:"java.lang.String" -> {
1289                           %11 : java.type:"java.lang.String" = constant @"not one";
1290                           yield %11;
1291                       };
1292                   return %3;
1293               };
1294             """)
1295     @Reflect
1296     static String constantLabelCasted(int i) {
1297         return switch (i) {
1298             case (byte) 1 -> "one";
1299             default -> "not one";
1300         };
1301     }
1302 
1303     @IR("""
1304             func @"caseConstantStringLiteral" (%0 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
1305                   %1 : Var<java.type:"java.lang.String"> = var %0 @"s";
1306                   %2 : java.type:"java.lang.String" = var.load %1;
1307                   %3 : java.type:"java.lang.String" = java.switch.expression %2
1308                       (%4 : java.type:"java.lang.String")java.type:"boolean" -> {
1309                           %5 : java.type:"java.lang.String" = constant @"1";
1310                           %6 : java.type:"boolean" = invoke %4 %5 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
1311                           yield %6;
1312                       }
1313                       ()java.type:"java.lang.String" -> {
1314                           %7 : java.type:"java.lang.String" = constant @"one";
1315                           yield %7;
1316                       }
1317                       (%8 : java.type:"java.lang.String")java.type:"boolean" -> {
1318                           %9 : java.type:"boolean" = java.cor
1319                               ()java.type:"boolean" -> {
1320                                   %10 : java.type:"java.lang.String" = constant @"2";
1321                                   %11 : java.type:"boolean" = invoke %8 %10 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
1322                                   yield %11;
1323                               }
1324                               ()java.type:"boolean" -> {
1325                                   %12 : java.type:"java.lang.String" = constant @"3";
1326                                   %13 : java.type:"boolean" = invoke %8 %12 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
1327                                   yield %13;
1328                               };
1329                           yield %9;
1330                       }
1331                       ()java.type:"java.lang.String" -> {
1332                           %14 : java.type:"java.lang.String" = constant @"two or three";
1333                           yield %14;
1334                       }
1335                       ()java.type:"boolean" -> {
1336                           %15 : java.type:"boolean" = constant @true;
1337                           yield %15;
1338                       }
1339                       ()java.type:"java.lang.String" -> {
1340                           %16 : java.type:"java.lang.String" = constant @"else";
1341                           yield %16;
1342                       };
1343                   return %3;
1344               };
1345             """)
1346     @Reflect
1347     static String caseConstantStringLiteral(String s) {
1348         return switch (s) {
1349             case "1" -> "one";
1350             case "2", "3" -> "two or three";
1351             default -> "else";
1352         };
1353     }
1354 
1355     @IR("""
1356             func @"casePatternWithCaseConstant" (%0 : java.type:"int")java.type:"java.lang.String" -> {
1357                   %1 : Var<java.type:"int"> = var %0 @"i";
1358                   %2 : java.type:"int" = var.load %1;
1359                   %3 : java.type:"java.lang.Integer" = constant @null;
1360                   %4 : Var<java.type:"java.lang.Integer"> = var %3 @"j";
1361                   %5 : java.type:"java.lang.Integer" = constant @null;
1362                   %6 : Var<java.type:"java.lang.Integer"> = var %5;
1363                   %7 : java.type:"java.lang.String" = java.switch.expression %2
1364                       (%8 : java.type:"int")java.type:"boolean" -> {
1365                           %9 : java.type:"int" = constant @0;
1366                           %10 : java.type:"boolean" = eq %8 %9;
1367                           yield %10;
1368                       }
1369                       ()java.type:"java.lang.String" -> {
1370                           %11 : java.type:"java.lang.String" = constant @"zero";
1371                           yield %11;
1372                       }
1373                       (%12 : java.type:"int")java.type:"boolean" -> {
1374                           %13 : java.type:"boolean" = java.cand
1375                               ()java.type:"boolean" -> {
1376                                   %14 : java.type:"java.lang.Integer" = invoke %12 @java.ref:"java.lang.Integer::valueOf(int):java.lang.Integer";
1377                                   %15 : java.type:"boolean" = pattern.match %14
1378                                       ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Integer>" -> {
1379                                           %16 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Integer>" = pattern.type @"j";
1380                                           yield %16;
1381                                       }
1382                                       (%17 : java.type:"java.lang.Integer")java.type:"void" -> {
1383                                           var.store %4 %17;
1384                                           yield;
1385                                       };
1386                                   yield %15;
1387                               }
1388                               ()java.type:"boolean" -> {
1389                                   %18 : java.type:"java.lang.Integer" = var.load %4;
1390                                   %19 : java.type:"int" = invoke %18 @java.ref:"java.lang.Integer::intValue():int";
1391                                   %20 : java.type:"int" = constant @0;
1392                                   %21 : java.type:"boolean" = gt %19 %20;
1393                                   yield %21;
1394                               };
1395                           yield %13;
1396                       }
1397                       ()java.type:"java.lang.String" -> {
1398                           %22 : java.type:"java.lang.String" = constant @"positive";
1399                           yield %22;
1400                       }
1401                       (%23 : java.type:"int")java.type:"boolean" -> {
1402                           %24 : java.type:"java.lang.Integer" = invoke %23 @java.ref:"java.lang.Integer::valueOf(int):java.lang.Integer";
1403                           %25 : java.type:"boolean" = pattern.match %24
1404                               ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Integer>" -> {
1405                                   %26 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Integer>" = pattern.type;
1406                                   yield %26;
1407                               }
1408                               (%27 : java.type:"java.lang.Integer")java.type:"void" -> {
1409                                   var.store %6 %27;
1410                                   yield;
1411                               };
1412                           yield %25;
1413                       }
1414                       ()java.type:"java.lang.String" -> {
1415                           %28 : java.type:"java.lang.String" = constant @"negative";
1416                           yield %28;
1417                       };
1418                   return %7;
1419               };
1420             """)
1421     @Reflect
1422     static String casePatternWithCaseConstant(int i) {
1423         return switch (i) {
1424             case 0 -> "zero";
1425             case Integer j when j > 0 -> "positive";
1426             case Integer _ -> "negative";
1427         };
1428     }
1429 }