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.MatchException" = new @java.ref:"java.lang.MatchException::()";
 691                         throw %29;
 692                     };
 693                 return %3;
 694             };
 695             """)
 696     @Reflect
 697     private static int caseConstantEnum(Day d) {
 698         return switch (d) {
 699             case MON, FRI, SUN -> 6;
 700             case TUE -> 7;
 701             case THU, SAT -> 8;
 702             case WED -> 9;
 703         };
 704     }
 705 
 706     static class Constants {
 707         static final int c1 = 12;
 708     }
 709     @IR("""
 710             func @"caseConstantOtherKindsOfExpr" (%0 : java.type:"int")java.type:"java.lang.String" -> {
 711                 %1 : Var<java.type:"int"> = var %0 @"i";
 712                 %2 : java.type:"int" = constant @11;
 713                 %3 : Var<java.type:"int"> = var %2 @"eleven";
 714                 %4 : java.type:"int" = var.load %1;
 715                 %5 : java.type:"java.lang.String" = java.switch.expression %4
 716                     (%6 : java.type:"int")java.type:"boolean" -> {
 717                         %7 : java.type:"int" = constant @1;
 718                         %8 : java.type:"int" = constant @15;
 719                         %9 : java.type:"int" = and %7 %8;
 720                         %10 : java.type:"boolean" = eq %6 %9;
 721                         yield %10;
 722                     }
 723                     ()java.type:"java.lang.String" -> {
 724                         %11 : java.type:"java.lang.String" = constant @"1";
 725                         yield %11;
 726                     }
 727                     (%12 : java.type:"int")java.type:"boolean" -> {
 728                         %13 : java.type:"int" = constant @4;
 729                         %14 : java.type:"int" = constant @1;
 730                         %15 : java.type:"int" = ashr %13 %14;
 731                         %16 : java.type:"boolean" = eq %12 %15;
 732                         yield %16;
 733                     }
 734                     ()java.type:"java.lang.String" -> {
 735                         %17 : java.type:"java.lang.String" = constant @"2";
 736                         yield %17;
 737                     }
 738                     (%18 : java.type:"int")java.type:"boolean" -> {
 739                         %19 : java.type:"long" = constant @3;
 740                         %20 : java.type:"int" = conv %19;
 741                         %21 : java.type:"boolean" = eq %18 %20;
 742                         yield %21;
 743                     }
 744                     ()java.type:"java.lang.String" -> {
 745                         %22 : java.type:"java.lang.String" = constant @"3";
 746                         yield %22;
 747                     }
 748                     (%23 : java.type:"int")java.type:"boolean" -> {
 749                         %24 : java.type:"int" = constant @2;
 750                         %25 : java.type:"int" = constant @1;
 751                         %26 : java.type:"int" = lshl %24 %25;
 752                         %27 : java.type:"boolean" = eq %23 %26;
 753                         yield %27;
 754                     }
 755                     ()java.type:"java.lang.String" -> {
 756                         %28 : java.type:"java.lang.String" = constant @"4";
 757                         yield %28;
 758                     }
 759                     (%29 : java.type:"int")java.type:"boolean" -> {
 760                         %30 : java.type:"int" = constant @10;
 761                         %31 : java.type:"int" = constant @2;
 762                         %32 : java.type:"int" = div %30 %31;
 763                         %33 : java.type:"boolean" = eq %29 %32;
 764                         yield %33;
 765                     }
 766                     ()java.type:"java.lang.String" -> {
 767                         %34 : java.type:"java.lang.String" = constant @"5";
 768                         yield %34;
 769                     }
 770                     (%35 : java.type:"int")java.type:"boolean" -> {
 771                         %36 : java.type:"int" = constant @12;
 772                         %37 : java.type:"int" = constant @6;
 773                         %38 : java.type:"int" = sub %36 %37;
 774                         %39 : java.type:"boolean" = eq %35 %38;
 775                         yield %39;
 776                     }
 777                     ()java.type:"java.lang.String" -> {
 778                         %40 : java.type:"java.lang.String" = constant @"6";
 779                         yield %40;
 780                     }
 781                     (%41 : java.type:"int")java.type:"boolean" -> {
 782                         %42 : java.type:"int" = constant @3;
 783                         %43 : java.type:"int" = constant @4;
 784                         %44 : java.type:"int" = add %42 %43;
 785                         %45 : java.type:"boolean" = eq %41 %44;
 786                         yield %45;
 787                     }
 788                     ()java.type:"java.lang.String" -> {
 789                         %46 : java.type:"java.lang.String" = constant @"7";
 790                         yield %46;
 791                     }
 792                     (%47 : java.type:"int")java.type:"boolean" -> {
 793                         %48 : java.type:"int" = constant @2;
 794                         %49 : java.type:"int" = constant @2;
 795                         %50 : java.type:"int" = mul %48 %49;
 796                         %51 : java.type:"int" = constant @2;
 797                         %52 : java.type:"int" = mul %50 %51;
 798                         %53 : java.type:"boolean" = eq %47 %52;
 799                         yield %53;
 800                     }
 801                     ()java.type:"java.lang.String" -> {
 802                         %54 : java.type:"java.lang.String" = constant @"8";
 803                         yield %54;
 804                     }
 805                     (%55 : java.type:"int")java.type:"boolean" -> {
 806                         %56 : java.type:"int" = constant @8;
 807                         %57 : java.type:"int" = constant @1;
 808                         %58 : java.type:"int" = or %56 %57;
 809                         %59 : java.type:"boolean" = eq %55 %58;
 810                         yield %59;
 811                     }
 812                     ()java.type:"java.lang.String" -> {
 813                         %60 : java.type:"java.lang.String" = constant @"9";
 814                         yield %60;
 815                     }
 816                     (%61 : java.type:"int")java.type:"boolean" -> {
 817                         %62 : java.type:"int" = constant @10;
 818                         %63 : java.type:"boolean" = eq %61 %62;
 819                         yield %63;
 820                     }
 821                     ()java.type:"java.lang.String" -> {
 822                         %64 : java.type:"java.lang.String" = constant @"10";
 823                         yield %64;
 824                     }
 825                     (%65 : java.type:"int")java.type:"boolean" -> {
 826                         %66 : java.type:"int" = var.load %3;
 827                         %67 : java.type:"boolean" = eq %65 %66;
 828                         yield %67;
 829                     }
 830                     ()java.type:"java.lang.String" -> {
 831                         %68 : java.type:"java.lang.String" = constant @"11";
 832                         yield %68;
 833                     }
 834                     (%69 : java.type:"int")java.type:"boolean" -> {
 835                         %70 : java.type:"int" = field.load @java.ref:"SwitchExpressionTest2$Constants::c1:int";
 836                         %71 : java.type:"boolean" = eq %69 %70;
 837                         yield %71;
 838                     }
 839                     ()java.type:"java.lang.String" -> {
 840                         %72 : java.type:"int" = field.load @java.ref:"SwitchExpressionTest2$Constants::c1:int";
 841                         %73 : java.type:"java.lang.String" = invoke %72 @java.ref:"java.lang.String::valueOf(int):java.lang.String";
 842                         yield %73;
 843                     }
 844                     (%74 : java.type:"int")java.type:"boolean" -> {
 845                         %75 : java.type:"int" = java.cexpression
 846                             ()java.type:"boolean" -> {
 847                                 %76 : java.type:"int" = constant @1;
 848                                 %77 : java.type:"int" = constant @0;
 849                                 %78 : java.type:"boolean" = gt %76 %77;
 850                                 yield %78;
 851                             }
 852                             ()java.type:"int" -> {
 853                                 %79 : java.type:"int" = constant @13;
 854                                 yield %79;
 855                             }
 856                             ()java.type:"int" -> {
 857                                 %80 : java.type:"int" = constant @133;
 858                                 yield %80;
 859                             };
 860                         %81 : java.type:"boolean" = eq %74 %75;
 861                         yield %81;
 862                     }
 863                     ()java.type:"java.lang.String" -> {
 864                         %82 : java.type:"java.lang.String" = constant @"13";
 865                         yield %82;
 866                     }
 867                     ()java.type:"boolean" -> {
 868                         %83 : java.type:"boolean" = constant @true;
 869                         yield %83;
 870                     }
 871                     ()java.type:"java.lang.String" -> {
 872                         %84 : java.type:"java.lang.String" = constant @"an int";
 873                         yield %84;
 874                     };
 875                 return %5;
 876             };
 877             """)
 878     @Reflect
 879     private static String caseConstantOtherKindsOfExpr(int i) {
 880         final int eleven = 11;
 881         return switch (i) {
 882             case 1 & 0xF -> "1";
 883             case 4>>1 -> "2";
 884             case (int) 3L -> "3";
 885             case 2<<1 -> "4";
 886             case 10 / 2 -> "5";
 887             case 12 - 6 -> "6";
 888             case 3 + 4 -> "7";
 889             case 2 * 2 * 2 -> "8";
 890             case 8 | 1 -> "9";
 891             case (10) -> "10";
 892             case eleven -> "11";
 893             case Constants.c1 -> String.valueOf(Constants.c1);
 894             case 1 > 0 ? 13 : 133 -> "13";
 895             default -> "an int";
 896         };
 897     }
 898 
 899     // these are the conversions that applies in switch
 900 
 901     @IR("""
 902             func @"caseConstantConv" (%0 : java.type:"short")java.type:"java.lang.String" -> {
 903                 %1 : Var<java.type:"short"> = var %0 @"a";
 904                 %2 : java.type:"int" = constant @1;
 905                 %3 : java.type:"short" = conv %2;
 906                 %4 : Var<java.type:"short"> = var %3 @"s";
 907                 %5 : java.type:"int" = constant @2;
 908                 %6 : java.type:"byte" = conv %5;
 909                 %7 : Var<java.type:"byte"> = var %6 @"b";
 910                 %8 : java.type:"short" = var.load %1;
 911                 %9 : java.type:"java.lang.String" = java.switch.expression %8
 912                     (%10 : java.type:"short")java.type:"boolean" -> {
 913                         %11 : java.type:"short" = var.load %4;
 914                         %12 : java.type:"boolean" = eq %10 %11;
 915                         yield %12;
 916                     }
 917                     ()java.type:"java.lang.String" -> {
 918                         %13 : java.type:"java.lang.String" = constant @"one";
 919                         yield %13;
 920                     }
 921                     (%14 : java.type:"short")java.type:"boolean" -> {
 922                         %15 : java.type:"byte" = var.load %7;
 923                         %16 : java.type:"short" = conv %15;
 924                         %17 : java.type:"boolean" = eq %14 %16;
 925                         yield %17;
 926                     }
 927                     ()java.type:"java.lang.String" -> {
 928                         %18 : java.type:"java.lang.String" = constant @"three";
 929                         yield %18;
 930                     }
 931                     (%19 : java.type:"short")java.type:"boolean" -> {
 932                         %20 : java.type:"int" = constant @3;
 933                         %21 : java.type:"short" = conv %20;
 934                         %22 : java.type:"boolean" = eq %19 %21;
 935                         yield %22;
 936                     }
 937                     ()java.type:"java.lang.String" -> {
 938                         %23 : java.type:"java.lang.String" = constant @"two";
 939                         yield %23;
 940                     }
 941                     ()java.type:"boolean" -> {
 942                         %24 : java.type:"boolean" = constant @true;
 943                         yield %24;
 944                     }
 945                     ()java.type:"java.lang.String" -> {
 946                         %25 : java.type:"java.lang.String" = constant @"default";
 947                         yield %25;
 948                     };
 949                 return %9;
 950             };
 951             """)
 952     @Reflect
 953     static String caseConstantConv(short a) {
 954         final short s = 1;
 955         final byte b = 2;
 956         return switch (a) {
 957             case s -> "one"; // identity
 958             case b -> "three"; // widening primitive conversion
 959             case 3 -> "two"; // narrowing primitive conversion
 960             default -> "default";
 961         };
 962     }
 963 
 964     @IR("""
 965             func @"caseConstantConv2" (%0 : java.type:"java.lang.Byte")java.type:"java.lang.String" -> {
 966                 %1 : Var<java.type:"java.lang.Byte"> = var %0 @"a";
 967                 %2 : java.type:"int" = constant @2;
 968                 %3 : java.type:"byte" = conv %2;
 969                 %4 : Var<java.type:"byte"> = var %3 @"b";
 970                 %5 : java.type:"java.lang.Byte" = var.load %1;
 971                 %6 : java.type:"java.lang.String" = java.switch.expression %5
 972                     (%7 : java.type:"java.lang.Byte")java.type:"boolean" -> {
 973                         %8 : java.type:"byte" = invoke %7 @java.ref:"java.lang.Byte::byteValue():byte";
 974                         %9 : java.type:"int" = constant @1;
 975                         %10 : java.type:"byte" = conv %9;
 976                         %11 : java.type:"boolean" = eq %8 %10;
 977                         yield %11;
 978                     }
 979                     ()java.type:"java.lang.String" -> {
 980                         %11 : java.type:"java.lang.String" = constant @"one";
 981                         yield %11;
 982                     }
 983                     (%13 : java.type:"java.lang.Byte")java.type:"boolean" -> {
 984                         %14 : java.type:"byte" = invoke %13 @java.ref:"java.lang.Byte::byteValue():byte";
 985                         %15 : java.type:"byte" = var.load %4;
 986                         %16 : java.type:"boolean" = eq %14 %15;
 987                         yield %16;
 988                     }
 989                     ()java.type:"java.lang.String" -> {
 990                         %17 : java.type:"java.lang.String" = constant @"two";
 991                         yield %17;
 992                     }
 993                     ()java.type:"boolean" -> {
 994                         %18 : java.type:"boolean" = constant @true;
 995                         yield %18;
 996                     }
 997                     ()java.type:"java.lang.String" -> {
 998                         %19 : java.type:"java.lang.String" = constant @"default";
 999                         yield %19;
1000                     };
1001                 return %6;
1002             };
1003             """)
1004     @Reflect
1005     static String caseConstantConv2(Byte a) {
1006         final byte b = 2;
1007         return switch (a) {
1008             // narrowing conv is missing in the code model
1009             case 1 -> "one"; // narrowing primitive conversion followed by a boxing conversion
1010             case b -> "two"; // boxing
1011             default -> "default";
1012         };
1013     }
1014 
1015     enum E { F, G }
1016     @IR("""
1017             func @"noDefaultLabelEnum" (%0 : java.type:"SwitchExpressionTest2$E")java.type:"java.lang.String" -> {
1018                 %1 : Var<java.type:"SwitchExpressionTest2$E"> = var %0 @"e";
1019                 %2 : java.type:"SwitchExpressionTest2$E" = var.load %1;
1020                 %3 : java.type:"java.lang.String" = java.switch.expression %2
1021                     (%4 : java.type:"SwitchExpressionTest2$E")java.type:"boolean" -> {
1022                         %5 : java.type:"SwitchExpressionTest2$E" = field.load @java.ref:"SwitchExpressionTest2$E::F:SwitchExpressionTest2$E";
1023                         %6 : java.type:"boolean" = eq %4 %5;
1024                         yield %6;
1025                     }
1026                     ()java.type:"java.lang.String" -> {
1027                         %7 : java.type:"java.lang.String" = constant @"f";
1028                         yield %7;
1029                     }
1030                     (%8 : java.type:"SwitchExpressionTest2$E")java.type:"boolean" -> {
1031                         %9 : java.type:"SwitchExpressionTest2$E" = field.load @java.ref:"SwitchExpressionTest2$E::G:SwitchExpressionTest2$E";
1032                         %10 : java.type:"boolean" = eq %8 %9;
1033                         yield %10;
1034                     }
1035                     ()java.type:"java.lang.String" -> {
1036                         %11 : java.type:"java.lang.String" = constant @"g";
1037                         yield %11;
1038                     }
1039                     ()java.type:"boolean" -> {
1040                         %12 : java.type:"boolean" = constant @true;
1041                         yield %12;
1042                     }
1043                     ()java.type:"java.lang.String" -> {
1044                         %13 : java.type:"java.lang.MatchException" = new @java.ref:"java.lang.MatchException::()";
1045                         throw %13;
1046                     };
1047                 return %3;
1048             };
1049             """)
1050     @Reflect
1051     static String noDefaultLabelEnum(E e) {
1052         return switch (e) {
1053             case F -> "f";
1054             case G -> "g";
1055         };
1056     }
1057 
1058     @IR("""
1059             func @"unconditionalPattern" (%0 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
1060                 %1 : Var<java.type:"java.lang.String"> = var %0 @"s";
1061                 %2 : java.type:"java.lang.String" = var.load %1;
1062                 %3 : java.type:"java.lang.Object" = constant @null;
1063                 %4 : Var<java.type:"java.lang.Object"> = var %3 @"o";
1064                 %5 : java.type:"java.lang.String" = java.switch.expression %2
1065                     (%6 : java.type:"java.lang.String")java.type:"boolean" -> {
1066                         %7 : java.type:"java.lang.String" = constant @"A";
1067                         %8 : java.type:"boolean" = invoke %6 %7 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
1068                         yield %8;
1069                     }
1070                     ()java.type:"java.lang.String" -> {
1071                         %9 : java.type:"java.lang.String" = constant @"Alphabet";
1072                         yield %9;
1073                     }
1074                     (%10 : java.type:"java.lang.String")java.type:"boolean" -> {
1075                         %11 : java.type:"boolean" = pattern.match %10
1076                             ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Object>" -> {
1077                                 %12 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Object>" = pattern.type @"o";
1078                                 yield %12;
1079                             }
1080                             (%13 : java.type:"java.lang.Object")java.type:"void" -> {
1081                                 var.store %4 %13;
1082                                 yield;
1083                             };
1084                         yield %11;
1085                     }
1086                     ()java.type:"java.lang.String" -> {
1087                         %14 : java.type:"java.lang.String" = constant @"default";
1088                         yield %14;
1089                     };
1090                 return %5;
1091             };
1092             """)
1093     @Reflect
1094     static String unconditionalPattern(String s) {
1095         return switch (s) {
1096             case "A" -> "Alphabet";
1097             case Object o -> "default";
1098         };
1099     }
1100 
1101     sealed interface A permits B, C {}
1102     record B() implements A {}
1103     final class C implements A {}
1104     @IR("""
1105             func @"noDefault" (%0 : java.type:"SwitchExpressionTest2$A")java.type:"java.lang.String" -> {
1106                 %1 : Var<java.type:"SwitchExpressionTest2$A"> = var %0 @"a";
1107                 %2 : java.type:"SwitchExpressionTest2$A" = var.load %1;
1108                 %3 : java.type:"SwitchExpressionTest2$B" = constant @null;
1109                 %4 : Var<java.type:"SwitchExpressionTest2$B"> = var %3 @"b";
1110                 %5 : java.type:"SwitchExpressionTest2::C" = constant @null;
1111                 %6 : Var<java.type:"SwitchExpressionTest2::C"> = var %5 @"c";
1112                 %7 : java.type:"java.lang.String" = java.switch.expression %2
1113                     (%8 : java.type:"SwitchExpressionTest2$A")java.type:"boolean" -> {
1114                         %9 : java.type:"boolean" = pattern.match %8
1115                             ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<SwitchExpressionTest2$B>" -> {
1116                                 %10 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<SwitchExpressionTest2$B>" = pattern.type @"b";
1117                                 yield %10;
1118                             }
1119                             (%11 : java.type:"SwitchExpressionTest2$B")java.type:"void" -> {
1120                                 var.store %4 %11;
1121                                 yield;
1122                             };
1123                         yield %9;
1124                     }
1125                     ()java.type:"java.lang.String" -> {
1126                         %12 : java.type:"java.lang.String" = constant @"B";
1127                         yield %12;
1128                     }
1129                     (%13 : java.type:"SwitchExpressionTest2$A")java.type:"boolean" -> {
1130                         %14 : java.type:"boolean" = pattern.match %13
1131                             ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<SwitchExpressionTest2::C>" -> {
1132                                 %15 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<SwitchExpressionTest2::C>" = pattern.type @"c";
1133                                 yield %15;
1134                             }
1135                             (%16 : java.type:"SwitchExpressionTest2::C")java.type:"void" -> {
1136                                 var.store %6 %16;
1137                                 yield;
1138                             };
1139                         yield %14;
1140                     }
1141                     ()java.type:"java.lang.String" -> {
1142                         %17 : java.type:"java.lang.String" = constant @"C";
1143                         yield %17;
1144                     }
1145                     ()java.type:"boolean" -> {
1146                         %18 : java.type:"boolean" = constant @true;
1147                         yield %18;
1148                     }
1149                     ()java.type:"java.lang.String" -> {
1150                         %19 : java.type:"java.lang.MatchException" = new @java.ref:"java.lang.MatchException::()";
1151                         throw %19;
1152                     };
1153                 return %7;
1154             };
1155             """)
1156     @Reflect
1157     static String noDefault(A a) {
1158         return switch (a) {
1159             case B b -> "B";
1160             case C c -> "C";
1161         };
1162     }
1163 
1164     @IR("""
1165             func @"defaultNotTheLastLabel" (%0 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
1166                 %1 : Var<java.type:"java.lang.String"> = var %0 @"s";
1167                 %2 : java.type:"java.lang.String" = var.load %1;
1168                 %3 : java.type:"java.lang.String" = java.switch.expression %2
1169                     ()java.type:"boolean" -> {
1170                         %12 : java.type:"boolean" = constant @true;
1171                         yield %12;
1172                     }
1173                     ()java.type:"java.lang.String" -> {
1174                         %13 : java.type:"java.lang.String" = constant @"else";
1175                         yield %13;
1176                     }
1177                     (%4 : java.type:"java.lang.String")java.type:"boolean" -> {
1178                         %5 : java.type:"java.lang.String" = constant @"M";
1179                         %6 : java.type:"boolean" = invoke %4 %5 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
1180                         yield %6;
1181                     }
1182                     ()java.type:"java.lang.String" -> {
1183                         %7 : java.type:"java.lang.String" = constant @"Mow";
1184                         yield %7;
1185                     }
1186                     (%8 : java.type:"java.lang.String")java.type:"boolean" -> {
1187                         %9 : java.type:"java.lang.String" = constant @"A";
1188                         %10 : java.type:"boolean" = invoke %8 %9 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
1189                         yield %10;
1190                     }
1191                     ()java.type:"java.lang.String" -> {
1192                         %11 : java.type:"java.lang.String" = constant @"Aow";
1193                         yield %11;
1194                     };
1195                 return %3;
1196             };
1197             """)
1198     @Reflect
1199     static String defaultNotTheLastLabel(String s) {
1200         return switch (s) {
1201             default -> "else";
1202             case "M" -> "Mow";
1203             case "A" -> "Aow";
1204         };
1205     }
1206 
1207     @IR("""
1208             func @"caseConstantPrimitiveWrapperSelector" (%0 : java.type:"java.lang.Integer")java.type:"java.lang.String" -> {
1209                   %1 : Var<java.type:"java.lang.Integer"> = var %0 @"i";
1210                   %2 : java.type:"java.lang.Integer" = var.load %1;
1211                   %3 : java.type:"java.lang.String" = java.switch.expression %2
1212                       (%4 : java.type:"java.lang.Integer")java.type:"boolean" -> {
1213                           %5 : java.type:"int" = invoke %4 @java.ref:"java.lang.Integer::intValue():int";
1214                           %6 : java.type:"int" = constant @1;
1215                           %7 : java.type:"boolean" = eq %5 %6;
1216                           yield %7;
1217                       }
1218                       ()java.type:"java.lang.String" -> {
1219                           %8 : java.type:"java.lang.String" = constant @"one";
1220                           yield %8;
1221                       }
1222                       (%9 : java.type:"java.lang.Integer")java.type:"boolean" -> {
1223                           %10 : java.type:"boolean" = java.cor
1224                               ()java.type:"boolean" -> {
1225                                   %11 : java.type:"int" = invoke %9 @java.ref:"java.lang.Integer::intValue():int";
1226                                   %12 : java.type:"int" = constant @2;
1227                                   %13 : java.type:"boolean" = eq %11 %12;
1228                                   yield %13;
1229                               }
1230                               ()java.type:"boolean" -> {
1231                                   %14 : java.type:"int" = invoke %9 @java.ref:"java.lang.Integer::intValue():int";
1232                                   %15 : java.type:"int" = constant @3;
1233                                   %16 : java.type:"boolean" = eq %14 %15;
1234                                   yield %16;
1235                               };
1236                           yield %10;
1237                       }
1238                       ()java.type:"java.lang.String" -> {
1239                           %17 : java.type:"java.lang.String" = constant @"two or three";
1240                           yield %17;
1241                       }
1242                       ()java.type:"boolean" -> {
1243                           %18 : java.type:"boolean" = constant @true;
1244                           yield %18;
1245                       }
1246                       ()java.type:"java.lang.String" -> {
1247                           %19 : java.type:"java.lang.String" = constant @"else";
1248                           yield %19;
1249                       };
1250                   return %3;
1251             };
1252             """)
1253     @Reflect
1254     static String caseConstantPrimitiveWrapperSelector(Integer i) {
1255         return switch (i) {
1256             case 1 -> "one";
1257             case 2, 3 -> "two or three";
1258             default -> "else";
1259         };
1260     }
1261 
1262     @IR("""
1263             func @"constantLabelCasted" (%0 : java.type:"int")java.type:"java.lang.String" -> {
1264                   %1 : Var<java.type:"int"> = var %0 @"i";
1265                   %2 : java.type:"int" = var.load %1;
1266                   %3 : java.type:"java.lang.String" = java.switch.expression %2
1267                       (%4 : java.type:"int")java.type:"boolean" -> {
1268                           %5 : java.type:"int" = constant @1;
1269                           %6 : java.type:"byte" = conv %5;
1270                           %7 : java.type:"int" = conv %6;
1271                           %8 : java.type:"boolean" = eq %4 %7;
1272                           yield %8;
1273                       }
1274                       ()java.type:"java.lang.String" -> {
1275                           %9 : java.type:"java.lang.String" = constant @"one";
1276                           yield %9;
1277                       }
1278                       ()java.type:"boolean" -> {
1279                           %10 : java.type:"boolean" = constant @true;
1280                           yield %10;
1281                       }
1282                       ()java.type:"java.lang.String" -> {
1283                           %11 : java.type:"java.lang.String" = constant @"not one";
1284                           yield %11;
1285                       };
1286                   return %3;
1287               };
1288             """)
1289     @Reflect
1290     static String constantLabelCasted(int i) {
1291         return switch (i) {
1292             case (byte) 1 -> "one";
1293             default -> "not one";
1294         };
1295     }
1296 
1297     @IR("""
1298             func @"caseConstantStringLiteral" (%0 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
1299                   %1 : Var<java.type:"java.lang.String"> = var %0 @"s";
1300                   %2 : java.type:"java.lang.String" = var.load %1;
1301                   %3 : java.type:"java.lang.String" = java.switch.expression %2
1302                       (%4 : java.type:"java.lang.String")java.type:"boolean" -> {
1303                           %5 : java.type:"java.lang.String" = constant @"1";
1304                           %6 : java.type:"boolean" = invoke %4 %5 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
1305                           yield %6;
1306                       }
1307                       ()java.type:"java.lang.String" -> {
1308                           %7 : java.type:"java.lang.String" = constant @"one";
1309                           yield %7;
1310                       }
1311                       (%8 : java.type:"java.lang.String")java.type:"boolean" -> {
1312                           %9 : java.type:"boolean" = java.cor
1313                               ()java.type:"boolean" -> {
1314                                   %10 : java.type:"java.lang.String" = constant @"2";
1315                                   %11 : java.type:"boolean" = invoke %8 %10 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
1316                                   yield %11;
1317                               }
1318                               ()java.type:"boolean" -> {
1319                                   %12 : java.type:"java.lang.String" = constant @"3";
1320                                   %13 : java.type:"boolean" = invoke %8 %12 @java.ref:"java.util.Objects::equals(java.lang.Object, java.lang.Object):boolean";
1321                                   yield %13;
1322                               };
1323                           yield %9;
1324                       }
1325                       ()java.type:"java.lang.String" -> {
1326                           %14 : java.type:"java.lang.String" = constant @"two or three";
1327                           yield %14;
1328                       }
1329                       ()java.type:"boolean" -> {
1330                           %15 : java.type:"boolean" = constant @true;
1331                           yield %15;
1332                       }
1333                       ()java.type:"java.lang.String" -> {
1334                           %16 : java.type:"java.lang.String" = constant @"else";
1335                           yield %16;
1336                       };
1337                   return %3;
1338               };
1339             """)
1340     @Reflect
1341     static String caseConstantStringLiteral(String s) {
1342         return switch (s) {
1343             case "1" -> "one";
1344             case "2", "3" -> "two or three";
1345             default -> "else";
1346         };
1347     }
1348 
1349     @IR("""
1350             func @"casePatternWithCaseConstant" (%0 : java.type:"int")java.type:"java.lang.String" -> {
1351                   %1 : Var<java.type:"int"> = var %0 @"i";
1352                   %2 : java.type:"int" = var.load %1;
1353                   %3 : java.type:"java.lang.Integer" = constant @null;
1354                   %4 : Var<java.type:"java.lang.Integer"> = var %3 @"j";
1355                   %5 : java.type:"java.lang.Integer" = constant @null;
1356                   %6 : Var<java.type:"java.lang.Integer"> = var %5;
1357                   %7 : java.type:"java.lang.String" = java.switch.expression %2
1358                       (%8 : java.type:"int")java.type:"boolean" -> {
1359                           %9 : java.type:"int" = constant @0;
1360                           %10 : java.type:"boolean" = eq %8 %9;
1361                           yield %10;
1362                       }
1363                       ()java.type:"java.lang.String" -> {
1364                           %11 : java.type:"java.lang.String" = constant @"zero";
1365                           yield %11;
1366                       }
1367                       (%12 : java.type:"int")java.type:"boolean" -> {
1368                           %13 : java.type:"boolean" = java.cand
1369                               ()java.type:"boolean" -> {
1370                                   %14 : java.type:"java.lang.Integer" = invoke %12 @java.ref:"java.lang.Integer::valueOf(int):java.lang.Integer";
1371                                   %15 : java.type:"boolean" = pattern.match %14
1372                                       ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Integer>" -> {
1373                                           %16 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Integer>" = pattern.type @"j";
1374                                           yield %16;
1375                                       }
1376                                       (%17 : java.type:"java.lang.Integer")java.type:"void" -> {
1377                                           var.store %4 %17;
1378                                           yield;
1379                                       };
1380                                   yield %15;
1381                               }
1382                               ()java.type:"boolean" -> {
1383                                   %18 : java.type:"java.lang.Integer" = var.load %4;
1384                                   %19 : java.type:"int" = invoke %18 @java.ref:"java.lang.Integer::intValue():int";
1385                                   %20 : java.type:"int" = constant @0;
1386                                   %21 : java.type:"boolean" = gt %19 %20;
1387                                   yield %21;
1388                               };
1389                           yield %13;
1390                       }
1391                       ()java.type:"java.lang.String" -> {
1392                           %22 : java.type:"java.lang.String" = constant @"positive";
1393                           yield %22;
1394                       }
1395                       (%23 : java.type:"int")java.type:"boolean" -> {
1396                           %24 : java.type:"java.lang.Integer" = invoke %23 @java.ref:"java.lang.Integer::valueOf(int):java.lang.Integer";
1397                           %25 : java.type:"boolean" = pattern.match %24
1398                               ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Integer>" -> {
1399                                   %26 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.Integer>" = pattern.type;
1400                                   yield %26;
1401                               }
1402                               (%27 : java.type:"java.lang.Integer")java.type:"void" -> {
1403                                   var.store %6 %27;
1404                                   yield;
1405                               };
1406                           yield %25;
1407                       }
1408                       ()java.type:"java.lang.String" -> {
1409                           %28 : java.type:"java.lang.String" = constant @"negative";
1410                           yield %28;
1411                       };
1412                   return %7;
1413               };
1414             """)
1415     @Reflect
1416     static String casePatternWithCaseConstant(int i) {
1417         return switch (i) {
1418             case 0 -> "zero";
1419             case Integer j when j > 0 -> "positive";
1420             case Integer _ -> "negative";
1421         };
1422     }
1423 }