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