1 import java.lang.runtime.CodeReflection;
  2 
  3 /*
  4  * @test
  5  * @enablePreview
  6  * @build SwitchExpressionTest2
  7  * @build CodeReflectionTester
  8  * @run main CodeReflectionTester SwitchExpressionTest2
  9  */
 10 public class SwitchExpressionTest2 {
 11 
 12     @IR("""
 13             func @"caseConstantRuleExpression" (%0 : java.lang.String)java.lang.String -> {
 14                 %1 : Var<java.lang.String> = var %0 @"r";
 15                 %2 : java.lang.String = var.load %1;
 16                 %3 : java.lang.String = java.switch.expression %2
 17                     (%4 : java.lang.String)boolean -> {
 18                         %5 : java.lang.String = constant @"FOO";
 19                         %6 : boolean = invoke %4 %5 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 20                         yield %6;
 21                     }
 22                     ()java.lang.String -> {
 23                         %7 : java.lang.String = constant @"BAR";
 24                         yield %7;
 25                     }
 26                     (%8 : java.lang.String)boolean -> {
 27                         %9 : java.lang.String = constant @"BAR";
 28                         %10 : boolean = invoke %8 %9 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 29                         yield %10;
 30                     }
 31                     ()java.lang.String -> {
 32                         %11 : java.lang.String = constant @"BAZ";
 33                         yield %11;
 34                     }
 35                     (%12 : java.lang.String)boolean -> {
 36                         %13 : java.lang.String = constant @"BAZ";
 37                         %14 : boolean = invoke %12 %13 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 38                         yield %14;
 39                     }
 40                     ()java.lang.String -> {
 41                         %15 : java.lang.String = constant @"FOO";
 42                         yield %15;
 43                     }
 44                     ()boolean -> {
 45                         %17 : boolean = constant @"true";
 46                         yield %17;
 47                     }
 48                     ()java.lang.String -> {
 49                         %16 : java.lang.String = constant @"";
 50                         yield %16;
 51                     };
 52                 return %3;
 53             };
 54             """)
 55     @CodeReflection
 56     public static String caseConstantRuleExpression(String r) {
 57         return switch (r) {
 58             case "FOO" -> "BAR";
 59             case "BAR" -> "BAZ";
 60             case "BAZ" -> "FOO";
 61             default -> "";
 62         };
 63     }
 64 
 65     @IR("""
 66             func @"caseConstantRuleBlock" (%0 : java.lang.String)java.lang.String -> {
 67                 %1 : Var<java.lang.String> = var %0 @"r";
 68                 %2 : java.lang.String = var.load %1;
 69                 %3 : java.lang.String = java.switch.expression %2
 70                     (%4 : java.lang.String)boolean -> {
 71                         %5 : java.lang.String = constant @"FOO";
 72                         %6 : boolean = invoke %4 %5 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 73                         yield %6;
 74                     }
 75                     ()java.lang.String -> {
 76                         %7 : java.lang.String = constant @"BAR";
 77                         java.yield %7;
 78                     }
 79                     (%8 : java.lang.String)boolean -> {
 80                         %9 : java.lang.String = constant @"BAR";
 81                         %10 : boolean = invoke %8 %9 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 82                         yield %10;
 83                     }
 84                     ()java.lang.String -> {
 85                         %11 : java.lang.String = constant @"BAZ";
 86                         java.yield %11;
 87                     }
 88                     (%12 : java.lang.String)boolean -> {
 89                         %13 : java.lang.String = constant @"BAZ";
 90                         %14 : boolean = invoke %12 %13 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 91                         yield %14;
 92                     }
 93                     ()java.lang.String -> {
 94                         %15 : java.lang.String = constant @"FOO";
 95                         java.yield %15;
 96                     }
 97                     ()boolean -> {
 98                         %17 : boolean = constant @"true";
 99                         yield %17;
100                     }
101                     ()java.lang.String -> {
102                         %16 : java.lang.String = constant @"";
103                         java.yield %16;
104                     };
105                 return %3;
106             };
107             """)
108     @CodeReflection
109     public static String caseConstantRuleBlock(String r) {
110         return switch (r) {
111             case "FOO" -> {
112                 yield "BAR";
113             }
114             case "BAR" -> {
115                 yield "BAZ";
116             }
117             case "BAZ" -> {
118                 yield "FOO";
119             }
120             default -> {
121                 yield "";
122             }
123         };
124     }
125 
126     @IR("""
127             func @"caseConstantStatement" (%0 : java.lang.String)java.lang.String -> {
128                 %1 : Var<java.lang.String> = var %0 @"s";
129                 %2 : java.lang.String = var.load %1;
130                 %3 : java.lang.String = java.switch.expression %2
131                     (%4 : java.lang.String)boolean -> {
132                         %5 : java.lang.String = constant @"FOO";
133                         %6 : boolean = invoke %4 %5 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
134                         yield %6;
135                     }
136                     ()java.lang.String -> {
137                         %7 : java.lang.String = constant @"BAR";
138                         java.yield %7;
139                     }
140                     (%8 : java.lang.String)boolean -> {
141                         %9 : java.lang.String = constant @"BAR";
142                         %10 : boolean = invoke %8 %9 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
143                         yield %10;
144                     }
145                     ()java.lang.String -> {
146                         %11 : java.lang.String = constant @"BAZ";
147                         java.yield %11;
148                     }
149                     (%12 : java.lang.String)boolean -> {
150                         %13 : java.lang.String = constant @"BAZ";
151                         %14 : boolean = invoke %12 %13 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
152                         yield %14;
153                     }
154                     ()java.lang.String -> {
155                         %15 : java.lang.String = constant @"FOO";
156                         java.yield %15;
157                     }
158                     ()boolean -> {
159                         %17 : boolean = constant @"true";
160                         yield %17;
161                     }
162                     ()java.lang.String -> {
163                         %16 : java.lang.String = constant @"";
164                         java.yield %16;
165                     };
166                 return %3;
167             };
168             """)
169     @CodeReflection
170     private static String caseConstantStatement(String s) {
171         return switch (s) {
172             case "FOO": yield "BAR";
173             case "BAR": yield "BAZ";
174             case "BAZ": yield "FOO";
175             default: yield "";
176         };
177     }
178 
179     @IR("""
180             func @"caseConstantMultiLabels" (%0 : char)java.lang.String -> {
181                 %1 : Var<char> = var %0 @"c";
182                 %2 : char = var.load %1;
183                 %3 : char = invoke %2 @"java.lang.Character::toLowerCase(char)char";
184                 %4 : java.lang.String = java.switch.expression %3
185                     (%5 : char)boolean -> {
186                         %6 : boolean = java.cor
187                             ()boolean -> {
188                                 %7 : char = constant @"a";
189                                 %8 : boolean = eq %5 %7;
190                                 yield %8;
191                             }
192                             ()boolean -> {
193                                 %9 : char = constant @"e";
194                                 %10 : boolean = eq %5 %9;
195                                 yield %10;
196                             }
197                             ()boolean -> {
198                                 %11 : char = constant @"i";
199                                 %12 : boolean = eq %5 %11;
200                                 yield %12;
201                             }
202                             ()boolean -> {
203                                 %13 : char = constant @"o";
204                                 %14 : boolean = eq %5 %13;
205                                 yield %14;
206                             }
207                             ()boolean -> {
208                                 %15 : char = constant @"u";
209                                 %16 : boolean = eq %5 %15;
210                                 yield %16;
211                             };
212                         yield %6;
213                     }
214                     ()java.lang.String -> {
215                         %17 : java.lang.String = constant @"vowel";
216                         java.yield %17;
217                     }
218                     ()boolean -> {
219                         %19 : boolean = constant @"true";
220                         yield %19;
221                     }
222                     ()java.lang.String -> {
223                         %18 : java.lang.String = constant @"consonant";
224                         java.yield %18;
225                     };
226                 return %4;
227             };
228             """)
229     @CodeReflection
230     private static String caseConstantMultiLabels(char c) {
231         return switch (Character.toLowerCase(c)) {
232             case 'a', 'e', 'i', 'o', 'u': yield "vowel";
233             default: yield "consonant";
234         };
235     }
236 
237     @IR("""
238             func @"caseConstantThrow" (%0 : java.lang.Integer)java.lang.String -> {
239                 %1 : Var<java.lang.Integer> = var %0 @"i";
240                 %2 : java.lang.Integer = var.load %1;
241                 %3 : java.lang.String = java.switch.expression %2
242                     (%4 : java.lang.Integer)boolean -> {
243                         %5 : int = constant @"8";
244                         %6 : java.lang.Integer = invoke %5 @"java.lang.Integer::valueOf(int)java.lang.Integer";
245                         %7 : boolean = invoke %4 %6 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
246                         yield %7;
247                     }
248                     ()java.lang.String -> {
249                         %8 : java.lang.IllegalArgumentException = new @"func<java.lang.IllegalArgumentException>";
250                         throw %8;
251                     }
252                     (%9 : java.lang.Integer)boolean -> {
253                         %10 : int = constant @"9";
254                         %11 : java.lang.Integer = invoke %10 @"java.lang.Integer::valueOf(int)java.lang.Integer";
255                         %12 : boolean = invoke %9 %11 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
256                         yield %12;
257                     }
258                     ()java.lang.String -> {
259                         %13 : java.lang.String = constant @"NINE";
260                         yield %13;
261                     }
262                     ()boolean -> {
263                         %15 : boolean = constant @"true";
264                         yield %15;
265                     }
266                     ()java.lang.String -> {
267                         %14 : java.lang.String = constant @"An integer";
268                         yield %14;
269                     };
270                 return %3;
271             };
272             """)
273     @CodeReflection
274     private static String caseConstantThrow(Integer i) {
275         return switch (i) {
276             case 8 -> throw new IllegalArgumentException();
277             case 9 -> "NINE";
278             default -> "An integer";
279         };
280     }
281 
282     @IR("""
283             func @"caseConstantNullLabel" (%0 : java.lang.String)java.lang.String -> {
284                 %1 : Var<java.lang.String> = var %0 @"s";
285                 %2 : java.lang.String = var.load %1;
286                 %3 : java.lang.String = java.switch.expression %2
287                     (%4 : java.lang.String)boolean -> {
288                         %5 : java.lang.Object = constant @null;
289                         %6 : boolean = invoke %4 %5 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
290                         yield %6;
291                     }
292                     ()java.lang.String -> {
293                         %7 : java.lang.String = constant @"null";
294                         yield %7;
295                     }
296                     ()boolean -> {
297                         %9 : boolean = constant @"true";
298                         yield %9;
299                     }
300                     ()java.lang.String -> {
301                         %8 : java.lang.String = constant @"non null";
302                         yield %8;
303                     };
304                 return %3;
305             };
306             """)
307     @CodeReflection
308     private static String caseConstantNullLabel(String s) {
309         return switch (s) {
310             case null -> "null";
311             default -> "non null";
312         };
313     }
314 
315     // @CodeReflection
316     // compiler code doesn't support case null, default
317     // @@@ support such as case and test the switch expression lowering for this case
318     private static String caseConstantNullAndDefault(String s) {
319         return switch (s) {
320             case "abc" -> "alphabet";
321             case null, default -> "null or default";
322         };
323     }
324 
325     @IR("""
326             func @"caseConstantFallThrough" (%0 : char)java.lang.String -> {
327                 %1 : Var<char> = var %0 @"c";
328                 %2 : char = var.load %1;
329                 %3 : java.lang.String = java.switch.expression %2
330                     (%4 : char)boolean -> {
331                         %5 : char = constant @"A";
332                         %6 : boolean = eq %4 %5;
333                         yield %6;
334                     }
335                     ()java.lang.String -> {
336                         java.switch.fallthrough;
337                     }
338                     (%7 : char)boolean -> {
339                         %8 : char = constant @"B";
340                         %9 : boolean = eq %7 %8;
341                         yield %9;
342                     }
343                     ()java.lang.String -> {
344                         %10 : java.lang.String = constant @"A or B";
345                         java.yield %10;
346                     }
347                     ()boolean -> {
348                         %12 : boolean = constant @"true";
349                         yield %12;
350                     }
351                     ()java.lang.String -> {
352                         %11 : java.lang.String = constant @"Neither A nor B";
353                         java.yield %11;
354                     };
355                 return %3;
356             };
357             """)
358     @CodeReflection
359     private static String caseConstantFallThrough(char c) {
360         return switch (c) {
361             case 'A':
362             case 'B':
363                 yield "A or B";
364             default:
365                 yield "Neither A nor B";
366         };
367     }
368 
369     enum Day {
370         MON, TUE, WED, THU, FRI, SAT, SUN
371     }
372     @IR("""
373             func @"caseConstantEnum" (%0 : SwitchExpressionTest2$Day)int -> {
374                 %1 : Var<SwitchExpressionTest2$Day> = var %0 @"d";
375                 %2 : SwitchExpressionTest2$Day = var.load %1;
376                 %3 : int = java.switch.expression %2
377                     (%4 : SwitchExpressionTest2$Day)boolean -> {
378                         %5 : boolean = java.cor
379                             ()boolean -> {
380                                 %6 : SwitchExpressionTest2$Day = field.load @"SwitchExpressionTest2$Day::MON()SwitchExpressionTest2$Day";
381                                 %7 : boolean = invoke %4 %6 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
382                                 yield %7;
383                             }
384                             ()boolean -> {
385                                 %8 : SwitchExpressionTest2$Day = field.load @"SwitchExpressionTest2$Day::FRI()SwitchExpressionTest2$Day";
386                                 %9 : boolean = invoke %4 %8 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
387                                 yield %9;
388                             }
389                             ()boolean -> {
390                                 %10 : SwitchExpressionTest2$Day = field.load @"SwitchExpressionTest2$Day::SUN()SwitchExpressionTest2$Day";
391                                 %11 : boolean = invoke %4 %10 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
392                                 yield %11;
393                             };
394                         yield %5;
395                     }
396                     ()int -> {
397                         %12 : int = constant @"6";
398                         yield %12;
399                     }
400                     (%13 : SwitchExpressionTest2$Day)boolean -> {
401                         %14 : SwitchExpressionTest2$Day = field.load @"SwitchExpressionTest2$Day::TUE()SwitchExpressionTest2$Day";
402                         %15 : boolean = invoke %13 %14 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
403                         yield %15;
404                     }
405                     ()int -> {
406                         %16 : int = constant @"7";
407                         yield %16;
408                     }
409                     (%17 : SwitchExpressionTest2$Day)boolean -> {
410                         %18 : boolean = java.cor
411                             ()boolean -> {
412                                 %19 : SwitchExpressionTest2$Day = field.load @"SwitchExpressionTest2$Day::THU()SwitchExpressionTest2$Day";
413                                 %20 : boolean = invoke %17 %19 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
414                                 yield %20;
415                             }
416                             ()boolean -> {
417                                 %21 : SwitchExpressionTest2$Day = field.load @"SwitchExpressionTest2$Day::SAT()SwitchExpressionTest2$Day";
418                                 %22 : boolean = invoke %17 %21 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
419                                 yield %22;
420                             };
421                         yield %18;
422                     }
423                     ()int -> {
424                         %23 : int = constant @"8";
425                         yield %23;
426                     }
427                     (%24 : SwitchExpressionTest2$Day)boolean -> {
428                         %25 : SwitchExpressionTest2$Day = field.load @"SwitchExpressionTest2$Day::WED()SwitchExpressionTest2$Day";
429                         %26 : boolean = invoke %24 %25 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
430                         yield %26;
431                     }
432                     ()int -> {
433                         %27 : int = constant @"9";
434                         yield %27;
435                     }
436                     ()boolean -> {
437                         %29 : boolean = constant @"true";
438                         yield %29;
439                     }
440                     ()int -> {
441                         %28 : java.lang.MatchException = new @"func<java.lang.MatchException>";
442                         throw %28;
443                     };
444                 return %3;
445             };
446             """)
447     @CodeReflection
448     private static int caseConstantEnum(Day d) {
449         return switch (d) {
450             case MON, FRI, SUN -> 6;
451             case TUE -> 7;
452             case THU, SAT -> 8;
453             case WED -> 9;
454         };
455     }
456 
457     static class Constants {
458         static final int c1 = 12;
459     }
460     @IR("""
461             func @"caseConstantOtherKindsOfExpr" (%0 : int)java.lang.String -> {
462                 %1 : Var<int> = var %0 @"i";
463                 %2 : int = constant @"11";
464                 %3 : Var<int> = var %2 @"eleven";
465                 %4 : int = var.load %1;
466                 %5 : java.lang.String = java.switch.expression %4
467                     (%6 : int)boolean -> {
468                         %7 : int = constant @"1";
469                         %8 : int = constant @"15";
470                         %9 : int = and %7 %8;
471                         %10 : boolean = eq %6 %9;
472                         yield %10;
473                     }
474                     ()java.lang.String -> {
475                         %11 : java.lang.String = constant @"1";
476                         yield %11;
477                     }
478                     (%12 : int)boolean -> {
479                         %13 : int = constant @"4";
480                         %14 : int = constant @"1";
481                         %15 : int = ashr %13 %14;
482                         %16 : boolean = eq %12 %15;
483                         yield %16;
484                     }
485                     ()java.lang.String -> {
486                         %17 : java.lang.String = constant @"2";
487                         yield %17;
488                     }
489                     (%18 : int)boolean -> {
490                         %19 : long = constant @"3";
491                         %20 : int = conv %19;
492                         %21 : boolean = eq %18 %20;
493                         yield %21;
494                     }
495                     ()java.lang.String -> {
496                         %22 : java.lang.String = constant @"3";
497                         yield %22;
498                     }
499                     (%23 : int)boolean -> {
500                         %24 : int = constant @"2";
501                         %25 : int = constant @"1";
502                         %26 : int = lshl %24 %25;
503                         %27 : boolean = eq %23 %26;
504                         yield %27;
505                     }
506                     ()java.lang.String -> {
507                         %28 : java.lang.String = constant @"4";
508                         yield %28;
509                     }
510                     (%29 : int)boolean -> {
511                         %30 : int = constant @"10";
512                         %31 : int = constant @"2";
513                         %32 : int = div %30 %31;
514                         %33 : boolean = eq %29 %32;
515                         yield %33;
516                     }
517                     ()java.lang.String -> {
518                         %34 : java.lang.String = constant @"5";
519                         yield %34;
520                     }
521                     (%35 : int)boolean -> {
522                         %36 : int = constant @"12";
523                         %37 : int = constant @"6";
524                         %38 : int = sub %36 %37;
525                         %39 : boolean = eq %35 %38;
526                         yield %39;
527                     }
528                     ()java.lang.String -> {
529                         %40 : java.lang.String = constant @"6";
530                         yield %40;
531                     }
532                     (%41 : int)boolean -> {
533                         %42 : int = constant @"3";
534                         %43 : int = constant @"4";
535                         %44 : int = add %42 %43;
536                         %45 : boolean = eq %41 %44;
537                         yield %45;
538                     }
539                     ()java.lang.String -> {
540                         %46 : java.lang.String = constant @"7";
541                         yield %46;
542                     }
543                     (%47 : int)boolean -> {
544                         %48 : int = constant @"2";
545                         %49 : int = constant @"2";
546                         %50 : int = mul %48 %49;
547                         %51 : int = constant @"2";
548                         %52 : int = mul %50 %51;
549                         %53 : boolean = eq %47 %52;
550                         yield %53;
551                     }
552                     ()java.lang.String -> {
553                         %54 : java.lang.String = constant @"8";
554                         yield %54;
555                     }
556                     (%55 : int)boolean -> {
557                         %56 : int = constant @"8";
558                         %57 : int = constant @"1";
559                         %58 : int = or %56 %57;
560                         %59 : boolean = eq %55 %58;
561                         yield %59;
562                     }
563                     ()java.lang.String -> {
564                         %60 : java.lang.String = constant @"9";
565                         yield %60;
566                     }
567                     (%61 : int)boolean -> {
568                         %62 : int = constant @"10";
569                         %63 : boolean = eq %61 %62;
570                         yield %63;
571                     }
572                     ()java.lang.String -> {
573                         %64 : java.lang.String = constant @"10";
574                         yield %64;
575                     }
576                     (%65 : int)boolean -> {
577                         %66 : int = var.load %3;
578                         %67 : boolean = eq %65 %66;
579                         yield %67;
580                     }
581                     ()java.lang.String -> {
582                         %68 : java.lang.String = constant @"11";
583                         yield %68;
584                     }
585                     (%69 : int)boolean -> {
586                         %70 : int = field.load @"SwitchExpressionTest2$Constants::c1()int";
587                         %71 : boolean = eq %69 %70;
588                         yield %71;
589                     }
590                     ()java.lang.String -> {
591                         %72 : int = field.load @"SwitchExpressionTest2$Constants::c1()int";
592                         %73 : java.lang.String = invoke %72 @"java.lang.String::valueOf(int)java.lang.String";
593                         yield %73;
594                     }
595                     (%74 : int)boolean -> {
596                         %75 : int = java.cexpression
597                             ()boolean -> {
598                                 %76 : int = constant @"1";
599                                 %77 : int = constant @"0";
600                                 %78 : boolean = gt %76 %77;
601                                 yield %78;
602                             }
603                             ()int -> {
604                                 %79 : int = constant @"13";
605                                 yield %79;
606                             }
607                             ()int -> {
608                                 %80 : int = constant @"133";
609                                 yield %80;
610                             };
611                         %81 : boolean = eq %74 %75;
612                         yield %81;
613                     }
614                     ()java.lang.String -> {
615                         %82 : java.lang.String = constant @"13";
616                         yield %82;
617                     }
618                     ()boolean -> {
619                         %84 : boolean = constant @"true";
620                         yield %84;
621                     }
622                     ()java.lang.String -> {
623                         %83 : java.lang.String = constant @"an int";
624                         yield %83;
625                     };
626                 return %5;
627             };
628             """)
629     @CodeReflection
630     private static String caseConstantOtherKindsOfExpr(int i) {
631         final int eleven = 11;
632         return switch (i) {
633             case 1 & 0xF -> "1";
634             case 4>>1 -> "2";
635             case (int) 3L -> "3";
636             case 2<<1 -> "4";
637             case 10 / 2 -> "5";
638             case 12 - 6 -> "6";
639             case 3 + 4 -> "7";
640             case 2 * 2 * 2 -> "8";
641             case 8 | 1 -> "9";
642             case (10) -> "10";
643             case eleven -> "11";
644             case Constants.c1 -> String.valueOf(Constants.c1);
645             case 1 > 0 ? 13 : 133 -> "13";
646             default -> "an int";
647         };
648     }
649 
650     // these are the conversions that applies in switch
651 
652     @IR("""
653             func @"caseConstantConv" (%0 : short)java.lang.String -> {
654                 %1 : Var<short> = var %0 @"a";
655                 %2 : int = constant @"1";
656                 %3 : short = conv %2;
657                 %4 : Var<short> = var %3 @"s";
658                 %5 : int = constant @"2";
659                 %6 : byte = conv %5;
660                 %7 : Var<byte> = var %6 @"b";
661                 %8 : short = var.load %1;
662                 %9 : java.lang.String = java.switch.expression %8
663                     (%10 : short)boolean -> {
664                         %11 : short = var.load %4;
665                         %12 : boolean = eq %10 %11;
666                         yield %12;
667                     }
668                     ()java.lang.String -> {
669                         %13 : java.lang.String = constant @"one";
670                         yield %13;
671                     }
672                     (%14 : short)boolean -> {
673                         %15 : byte = var.load %7;
674                         %16 : short = conv %15;
675                         %17 : boolean = eq %14 %16;
676                         yield %17;
677                     }
678                     ()java.lang.String -> {
679                         %18 : java.lang.String = constant @"three";
680                         yield %18;
681                     }
682                     (%19 : short)boolean -> {
683                         %20 : int = constant @"3";
684                         %21 : short = conv %20;
685                         %22 : boolean = eq %19 %21;
686                         yield %22;
687                     }
688                     ()java.lang.String -> {
689                         %23 : java.lang.String = constant @"two";
690                         yield %23;
691                     }
692                     ()boolean -> {
693                         %25 : boolean = constant @"true";
694                         yield %25;
695                     }
696                     ()java.lang.String -> {
697                         %24 : java.lang.String = constant @"default";
698                         yield %24;
699                     };
700                 return %9;
701             };
702             """)
703     @CodeReflection
704     static String caseConstantConv(short a) {
705         final short s = 1;
706         final byte b = 2;
707         return switch (a) {
708             case s -> "one"; // identity
709             case b -> "three"; // widening primitive conversion
710             case 3 -> "two"; // narrowing primitive conversion
711             default -> "default";
712         };
713     }
714 
715     @IR("""
716             func @"caseConstantConv2" (%0 : java.lang.Byte)java.lang.String -> {
717                 %1 : Var<java.lang.Byte> = var %0 @"a";
718                 %2 : int = constant @"2";
719                 %3 : byte = conv %2;
720                 %4 : Var<byte> = var %3 @"b";
721                 %5 : java.lang.Byte = var.load %1;
722                 %6 : java.lang.String = java.switch.expression %5
723                     (%7 : java.lang.Byte)boolean -> {
724                         %8 : int = constant @"1";
725                         %9 : byte = conv %8;
726                         %10 : java.lang.Byte = invoke %9 @"java.lang.Byte::valueOf(byte)java.lang.Byte";
727                         %11 : boolean = invoke %7 %10 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
728                         yield %11;
729                     }
730                     ()java.lang.String -> {
731                         %12 : java.lang.String = constant @"one";
732                         yield %12;
733                     }
734                     (%13 : java.lang.Byte)boolean -> {
735                         %14 : byte = var.load %4;
736                         %15 : java.lang.Byte = invoke %14 @"java.lang.Byte::valueOf(byte)java.lang.Byte";
737                         %16 : boolean = invoke %13 %15 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
738                         yield %16;
739                     }
740                     ()java.lang.String -> {
741                         %17 : java.lang.String = constant @"two";
742                         yield %17;
743                     }
744                     ()boolean -> {
745                         %19 : boolean = constant @"true";
746                         yield %19;
747                     }
748                     ()java.lang.String -> {
749                         %18 : java.lang.String = constant @"default";
750                         yield %18;
751                     };
752                 return %6;
753             };
754             """)
755     @CodeReflection
756     static String caseConstantConv2(Byte a) {
757         final byte b = 2;
758         return switch (a) {
759             // narrowing conv is missing in the code model
760             case 1 -> "one"; // narrowing primitive conversion followed by a boxing conversion
761             case b -> "two"; // boxing
762             default -> "default";
763         };
764     }
765 
766     enum E { F, G }
767     @IR("""
768             func @"noDefaultLabelEnum" (%0 : SwitchExpressionTest2$E)java.lang.String -> {
769                 %1 : Var<SwitchExpressionTest2$E> = var %0 @"e";
770                 %2 : SwitchExpressionTest2$E = var.load %1;
771                 %3 : java.lang.String = java.switch.expression %2
772                     (%4 : SwitchExpressionTest2$E)boolean -> {
773                         %5 : SwitchExpressionTest2$E = field.load @"SwitchExpressionTest2$E::F()SwitchExpressionTest2$E";
774                         %6 : boolean = invoke %4 %5 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
775                         yield %6;
776                     }
777                     ()java.lang.String -> {
778                         %7 : java.lang.String = constant @"f";
779                         yield %7;
780                     }
781                     (%8 : SwitchExpressionTest2$E)boolean -> {
782                         %9 : SwitchExpressionTest2$E = field.load @"SwitchExpressionTest2$E::G()SwitchExpressionTest2$E";
783                         %10 : boolean = invoke %8 %9 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
784                         yield %10;
785                     }
786                     ()java.lang.String -> {
787                         %11 : java.lang.String = constant @"g";
788                         yield %11;
789                     }
790                     ()boolean -> {
791                         %13 : boolean = constant @"true";
792                         yield %13;
793                     }
794                     ()java.lang.String -> {
795                         %12 : java.lang.MatchException = new @"func<java.lang.MatchException>";
796                         throw %12;
797                     };
798                 return %3;
799             };
800             """)
801     @CodeReflection
802     static String noDefaultLabelEnum(E e) {
803         return switch (e) {
804             case F -> "f";
805             case G -> "g";
806         };
807     }
808 
809     @IR("""
810             func @"unconditionalPattern" (%0 : java.lang.String)java.lang.String -> {
811                 %1 : Var<java.lang.String> = var %0 @"s";
812                 %2 : java.lang.String = var.load %1;
813                 %3 : java.lang.Object = constant @null;
814                 %4 : Var<java.lang.Object> = var %3 @"o";
815                 %5 : java.lang.String = java.switch.expression %2
816                     (%6 : java.lang.String)boolean -> {
817                         %7 : java.lang.String = constant @"A";
818                         %8 : boolean = invoke %6 %7 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
819                         yield %8;
820                     }
821                     ()java.lang.String -> {
822                         %9 : java.lang.String = constant @"Alphabet";
823                         yield %9;
824                     }
825                     (%10 : java.lang.String)boolean -> {
826                         %11 : boolean = pattern.match %10
827                             ()java.lang.reflect.code.ExtendedOp$Pattern$Binding<java.lang.Object> -> {
828                                 %12 : java.lang.reflect.code.ExtendedOp$Pattern$Binding<java.lang.Object> = pattern.binding @"o";
829                                 yield %12;
830                             }
831                             (%13 : java.lang.Object)void -> {
832                                 var.store %4 %13;
833                                 yield;
834                             };
835                         yield %11;
836                     }
837                     ()java.lang.String -> {
838                         %14 : java.lang.String = constant @"default";
839                         yield %14;
840                     };
841                 return %5;
842             };
843             """)
844     @CodeReflection
845     static String unconditionalPattern(String s) {
846         return switch (s) {
847             case "A" -> "Alphabet";
848             case Object o -> "default";
849         };
850     }
851 
852     sealed interface A permits B, C {}
853     record B() implements A {}
854     final class C implements A {}
855     @IR("""
856             func @"noDefault" (%0 : SwitchExpressionTest2$A)java.lang.String -> {
857                 %1 : Var<SwitchExpressionTest2$A> = var %0 @"a";
858                 %2 : SwitchExpressionTest2$A = var.load %1;
859                 %3 : SwitchExpressionTest2$B = constant @null;
860                 %4 : Var<SwitchExpressionTest2$B> = var %3 @"b";
861                 %5 : .<SwitchExpressionTest2, SwitchExpressionTest2$C> = constant @null;
862                 %6 : Var<.<SwitchExpressionTest2, SwitchExpressionTest2$C>> = var %5 @"c";
863                 %7 : java.lang.String = java.switch.expression %2
864                     (%8 : SwitchExpressionTest2$A)boolean -> {
865                         %9 : boolean = pattern.match %8
866                             ()java.lang.reflect.code.ExtendedOp$Pattern$Binding<SwitchExpressionTest2$B> -> {
867                                 %10 : java.lang.reflect.code.ExtendedOp$Pattern$Binding<SwitchExpressionTest2$B> = pattern.binding @"b";
868                                 yield %10;
869                             }
870                             (%11 : SwitchExpressionTest2$B)void -> {
871                                 var.store %4 %11;
872                                 yield;
873                             };
874                         yield %9;
875                     }
876                     ()java.lang.String -> {
877                         %12 : java.lang.String = constant @"B";
878                         yield %12;
879                     }
880                     (%13 : SwitchExpressionTest2$A)boolean -> {
881                         %14 : boolean = pattern.match %13
882                             ()java.lang.reflect.code.ExtendedOp$Pattern$Binding<.<SwitchExpressionTest2, SwitchExpressionTest2$C>> -> {
883                                 %15 : java.lang.reflect.code.ExtendedOp$Pattern$Binding<.<SwitchExpressionTest2, SwitchExpressionTest2$C>> = pattern.binding @"c";
884                                 yield %15;
885                             }
886                             (%16 : .<SwitchExpressionTest2, SwitchExpressionTest2$C>)void -> {
887                                 var.store %6 %16;
888                                 yield;
889                             };
890                         yield %14;
891                     }
892                     ()java.lang.String -> {
893                         %17 : java.lang.String = constant @"C";
894                         yield %17;
895                     }
896                     ()boolean -> {
897                         %19 : boolean = constant @"true";
898                         yield %19;
899                     }
900                     ()java.lang.String -> {
901                         %18 : java.lang.MatchException = new @"func<java.lang.MatchException>";
902                         throw %18;
903                     };
904                 return %7;
905             };
906             """)
907     @CodeReflection
908     static String noDefault(A a) {
909         return switch (a) {
910             case B b -> "B";
911             case C c -> "C";
912         };
913     }
914 
915     @IR("""
916             func @"defaultNotTheLastLabel" (%0 : java.lang.String)java.lang.String -> {
917                 %1 : Var<java.lang.String> = var %0 @"s";
918                 %2 : java.lang.String = var.load %1;
919                 %3 : java.lang.String = java.switch.expression %2
920                     (%5 : java.lang.String)boolean -> {
921                         %6 : java.lang.String = constant @"M";
922                         %7 : boolean = invoke %5 %6 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
923                         yield %7;
924                     }
925                     ()java.lang.String -> {
926                         %8 : java.lang.String = constant @"Mow";
927                         yield %8;
928                     }
929                     (%9 : java.lang.String)boolean -> {
930                         %10 : java.lang.String = constant @"A";
931                         %11 : boolean = invoke %9 %10 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
932                         yield %11;
933                     }
934                     ()java.lang.String -> {
935                         %12 : java.lang.String = constant @"Aow";
936                         yield %12;
937                     }
938                     ()boolean -> {
939                         %13 : boolean = constant @"true";
940                         yield %13;
941                     }
942                     ()java.lang.String -> {
943                         %4 : java.lang.String = constant @"else";
944                         yield %4;
945                     };
946                 return %3;
947             };
948             """)
949     @CodeReflection
950     static String defaultNotTheLastLabel(String s) {
951         return switch (s) {
952             default -> "else";
953             case "M" -> "Mow";
954             case "A" -> "Aow";
955         };
956     }
957 }