1 /*
   2  * Copyright (c) 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.Op;
  25 import jdk.incubator.code.Reflect;
  26 import jdk.incubator.code.dialect.core.CoreOp.FuncOp;
  27 import jdk.incubator.code.dialect.java.JavaOp;
  28 import jdk.incubator.code.dialect.java.JavaType;
  29 
  30 import java.io.IOException;
  31 import java.io.Serializable;
  32 import java.lang.classfile.ClassFile;
  33 import java.lang.classfile.ClassModel;
  34 import java.lang.classfile.CodeModel;
  35 import java.lang.classfile.MethodModel;
  36 import java.lang.classfile.Opcode;
  37 import java.lang.classfile.instruction.TypeCheckInstruction;
  38 import java.lang.constant.ClassDesc;
  39 import java.lang.reflect.Method;
  40 import java.nio.file.Path;
  41 import java.util.List;
  42 
  43 /*
  44  * @test
  45  * @summary Smoke test for timing of synthetic erasure casts
  46  * @modules jdk.incubator.code
  47  * @build ErasedAccessTest
  48  * @run main ErasedAccessTest
  49  * @run main CodeReflectionTester ErasedAccessTest
  50  */
  51 
  52 public class ErasedAccessTest {
  53 
  54     static class Unbounded<X, T extends Throwable> {
  55         X x;
  56         T t;
  57 
  58         X getX() {
  59             return x;
  60         }
  61         T getT() {
  62             return t;
  63         }
  64     }
  65 
  66     static class UnboundedInteger extends Unbounded<Integer, WrongThreadException> {
  67 
  68         @IR("""
  69                 func @"testInstanceof" (%0 : java.type:"ErasedAccessTest$UnboundedInteger", %1 : java.type:"ErasedAccessTest$UnboundedInteger")java.type:"void" -> {
  70                     %2 : Var<java.type:"ErasedAccessTest$UnboundedInteger"> = var %1 @"test";
  71                     %3 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
  72                     %4 : java.type:"boolean" = instanceof %3 @java.type:"java.lang.Integer";
  73                     %5 : Var<java.type:"boolean"> = var %4 @"f_s_s";
  74                     %6 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
  75                     %7 : java.type:"java.lang.Integer" = field.load %6 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
  76                     %8 : java.type:"boolean" = instanceof %7 @java.type:"java.lang.Integer";
  77                     %9 : Var<java.type:"boolean"> = var %8 @"f_q_s";
  78                     %10 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
  79                     %11 : java.type:"boolean" = instanceof %10 @java.type:"java.lang.Integer";
  80                     %12 : Var<java.type:"boolean"> = var %11 @"m_s_s";
  81                     %13 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
  82                     %14 : java.type:"java.lang.Integer" = invoke %13 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
  83                     %15 : java.type:"boolean" = instanceof %14 @java.type:"java.lang.Integer";
  84                     %16 : Var<java.type:"boolean"> = var %15 @"m_q_s";
  85                     return;
  86                 };
  87                 """)
  88         @Reflect
  89         void testInstanceof(UnboundedInteger test) {
  90             // simple field name
  91             boolean f_s_s = x instanceof Integer;
  92 
  93             // qualified field name
  94             boolean f_q_s = test.x instanceof Integer;
  95 
  96             // simple method name
  97             boolean m_s_s = getX() instanceof Integer;
  98 
  99             // qualified method name
 100             boolean m_q_s = test.getX() instanceof Integer;
 101         }
 102 
 103         @IR("""
 104                 func @"testInstanceofCond" (%0 : java.type:"ErasedAccessTest$UnboundedInteger", %1 : java.type:"ErasedAccessTest$UnboundedInteger", %2 : java.type:"boolean")java.type:"void" -> {
 105                     %3 : Var<java.type:"ErasedAccessTest$UnboundedInteger"> = var %1 @"test";
 106                     %4 : Var<java.type:"boolean"> = var %2 @"cond";
 107                     %5 : java.type:"java.lang.Integer" = java.cexpression
 108                         ()java.type:"boolean" -> {
 109                             %6 : java.type:"boolean" = var.load %4;
 110                             yield %6;
 111                         }
 112                         ()java.type:"java.lang.Integer" -> {
 113                             %7 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 114                             %8 : java.type:"java.lang.Integer" = cast %7 @java.type:"java.lang.Integer";
 115                             yield %8;
 116                         }
 117                         ()java.type:"java.lang.Integer" -> {
 118                             %9 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 119                             %10 : java.type:"java.lang.Integer" = cast %9 @java.type:"java.lang.Integer";
 120                             yield %10;
 121                         };
 122                     %11 : java.type:"boolean" = instanceof %5 @java.type:"java.lang.Object";
 123                     %12 : Var<java.type:"boolean"> = var %11 @"f_s_o";
 124                     %13 : java.type:"java.lang.Integer" = java.cexpression
 125                         ()java.type:"boolean" -> {
 126                             %14 : java.type:"boolean" = var.load %4;
 127                             yield %14;
 128                         }
 129                         ()java.type:"java.lang.Integer" -> {
 130                             %15 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
 131                             %16 : java.type:"java.lang.Integer" = field.load %15 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 132                             %17 : java.type:"java.lang.Integer" = cast %16 @java.type:"java.lang.Integer";
 133                             yield %17;
 134                         }
 135                         ()java.type:"java.lang.Integer" -> {
 136                             %18 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
 137                             %19 : java.type:"java.lang.Integer" = field.load %18 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 138                             %20 : java.type:"java.lang.Integer" = cast %19 @java.type:"java.lang.Integer";
 139                             yield %20;
 140                         };
 141                     %21 : java.type:"boolean" = instanceof %13 @java.type:"java.lang.Object";
 142                     %22 : Var<java.type:"boolean"> = var %21 @"f_q_o";
 143                     %23 : java.type:"java.lang.Integer" = java.cexpression
 144                         ()java.type:"boolean" -> {
 145                             %24 : java.type:"boolean" = var.load %4;
 146                             yield %24;
 147                         }
 148                         ()java.type:"java.lang.Integer" -> {
 149                             %25 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 150                             %26 : java.type:"java.lang.Integer" = cast %25 @java.type:"java.lang.Integer";
 151                             yield %26;
 152                         }
 153                         ()java.type:"java.lang.Integer" -> {
 154                             %27 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 155                             %28 : java.type:"java.lang.Integer" = cast %27 @java.type:"java.lang.Integer";
 156                             yield %28;
 157                         };
 158                     %29 : java.type:"boolean" = instanceof %23 @java.type:"java.lang.Object";
 159                     %30 : Var<java.type:"boolean"> = var %29 @"m_s_o";
 160                     %31 : java.type:"java.lang.Integer" = java.cexpression
 161                         ()java.type:"boolean" -> {
 162                             %32 : java.type:"boolean" = var.load %4;
 163                             yield %32;
 164                         }
 165                         ()java.type:"java.lang.Integer" -> {
 166                             %33 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
 167                             %34 : java.type:"java.lang.Integer" = invoke %33 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 168                             %35 : java.type:"java.lang.Integer" = cast %34 @java.type:"java.lang.Integer";
 169                             yield %35;
 170                         }
 171                         ()java.type:"java.lang.Integer" -> {
 172                             %36 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
 173                             %37 : java.type:"java.lang.Integer" = invoke %36 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 174                             %38 : java.type:"java.lang.Integer" = cast %37 @java.type:"java.lang.Integer";
 175                             yield %38;
 176                         };
 177                     %39 : java.type:"boolean" = instanceof %31 @java.type:"java.lang.Object";
 178                     %40 : Var<java.type:"boolean"> = var %39 @"m_q_o";
 179                     return;
 180                 };
 181                 """)
 182         @Reflect
 183         void testInstanceofCond(UnboundedInteger test, boolean cond) {
 184             // simple field name
 185             boolean f_s_o = (cond ? x : x) instanceof Object;
 186 
 187             // qualified field name
 188             boolean f_q_o = (cond ? test.x : test.x) instanceof Object;
 189 
 190             // simple method name
 191             boolean m_s_o = (cond ? getX() : getX()) instanceof Object;
 192 
 193             // qualified method name
 194             boolean m_q_o = (cond ? test.getX() : test.getX()) instanceof Object;
 195         }
 196 
 197         @IR("""
 198                 func @"testExec" (%0 : java.type:"ErasedAccessTest$UnboundedInteger", %1 : java.type:"ErasedAccessTest$UnboundedInteger")java.type:"void" -> {
 199                     %2 : Var<java.type:"ErasedAccessTest$UnboundedInteger"> = var %1 @"test";
 200                     %3 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 201                     %4 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 202                     %5 : java.type:"java.lang.Integer" = invoke %4 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 203                     return;
 204                 };
 205                 """)
 206         @Reflect
 207         void testExec(UnboundedInteger test) {
 208             // simple method name
 209             getX();
 210 
 211             // qualified method name
 212             test.getX();
 213         }
 214 
 215         @IR("""
 216                 func @"testChainedCall" (%0 : java.type:"ErasedAccessTest$UnboundedInteger", %1 : java.type:"ErasedAccessTest$UnboundedInteger")java.type:"void" -> {
 217                     %2 : Var<java.type:"ErasedAccessTest$UnboundedInteger"> = var %1 @"test";
 218                     %3 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 219                     %4 : java.type:"java.lang.Integer" = cast %3 @java.type:"java.lang.Integer";
 220                     %5 : java.type:"int" = invoke %4 @java.ref:"java.lang.Integer::hashCode():int";
 221                     %6 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 222                     %7 : java.type:"java.lang.Integer" = field.load %6 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 223                     %8 : java.type:"java.lang.Integer" = cast %7 @java.type:"java.lang.Integer";
 224                     %9 : java.type:"int" = invoke %8 @java.ref:"java.lang.Integer::hashCode():int";
 225                     %10 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 226                     %11 : java.type:"java.lang.Integer" = cast %10 @java.type:"java.lang.Integer";
 227                     %12 : java.type:"int" = invoke %11 @java.ref:"java.lang.Integer::hashCode():int";
 228                     %13 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 229                     %14 : java.type:"java.lang.Integer" = invoke %13 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 230                     %15 : java.type:"java.lang.Integer" = cast %14 @java.type:"java.lang.Integer";
 231                     %16 : java.type:"int" = invoke %15 @java.ref:"java.lang.Integer::hashCode():int";
 232                     return;
 233                 };
 234                 """)
 235         @Reflect
 236         void testChainedCall(UnboundedInteger test) {
 237             // simple field name
 238             x.hashCode();
 239 
 240             // qualified field name
 241             test.x.hashCode();
 242 
 243             // simple method name
 244             getX().hashCode();
 245 
 246             // qualified method name
 247             test.getX().hashCode();
 248         }
 249 
 250         @IR("""
 251                 func @"testChainedCallCond" (%0 : java.type:"ErasedAccessTest$UnboundedInteger", %1 : java.type:"ErasedAccessTest$UnboundedInteger", %2 : java.type:"boolean")java.type:"void" -> {
 252                     %3 : Var<java.type:"ErasedAccessTest$UnboundedInteger"> = var %1 @"test";
 253                     %4 : Var<java.type:"boolean"> = var %2 @"cond";
 254                     %5 : java.type:"java.lang.Integer" = java.cexpression
 255                         ()java.type:"boolean" -> {
 256                             %6 : java.type:"boolean" = var.load %4;
 257                             yield %6;
 258                         }
 259                         ()java.type:"java.lang.Integer" -> {
 260                             %7 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 261                             %8 : java.type:"java.lang.Integer" = cast %7 @java.type:"java.lang.Integer";
 262                             yield %8;
 263                         }
 264                         ()java.type:"java.lang.Integer" -> {
 265                             %9 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 266                             %10 : java.type:"java.lang.Integer" = cast %9 @java.type:"java.lang.Integer";
 267                             yield %10;
 268                         };
 269                     %11 : java.type:"int" = invoke %5 @java.ref:"java.lang.Integer::hashCode():int";
 270                     %12 : java.type:"java.lang.Integer" = java.cexpression
 271                         ()java.type:"boolean" -> {
 272                             %13 : java.type:"boolean" = var.load %4;
 273                             yield %13;
 274                         }
 275                         ()java.type:"java.lang.Integer" -> {
 276                             %14 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
 277                             %15 : java.type:"java.lang.Integer" = field.load %14 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 278                             %16 : java.type:"java.lang.Integer" = cast %15 @java.type:"java.lang.Integer";
 279                             yield %16;
 280                         }
 281                         ()java.type:"java.lang.Integer" -> {
 282                             %17 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
 283                             %18 : java.type:"java.lang.Integer" = field.load %17 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 284                             %19 : java.type:"java.lang.Integer" = cast %18 @java.type:"java.lang.Integer";
 285                             yield %19;
 286                         };
 287                     %20 : java.type:"int" = invoke %12 @java.ref:"java.lang.Integer::hashCode():int";
 288                     %21 : java.type:"java.lang.Integer" = java.cexpression
 289                         ()java.type:"boolean" -> {
 290                             %22 : java.type:"boolean" = var.load %4;
 291                             yield %22;
 292                         }
 293                         ()java.type:"java.lang.Integer" -> {
 294                             %23 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 295                             %24 : java.type:"java.lang.Integer" = cast %23 @java.type:"java.lang.Integer";
 296                             yield %24;
 297                         }
 298                         ()java.type:"java.lang.Integer" -> {
 299                             %25 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 300                             %26 : java.type:"java.lang.Integer" = cast %25 @java.type:"java.lang.Integer";
 301                             yield %26;
 302                         };
 303                     %27 : java.type:"int" = invoke %21 @java.ref:"java.lang.Integer::hashCode():int";
 304                     %28 : java.type:"java.lang.Integer" = java.cexpression
 305                         ()java.type:"boolean" -> {
 306                             %29 : java.type:"boolean" = var.load %4;
 307                             yield %29;
 308                         }
 309                         ()java.type:"java.lang.Integer" -> {
 310                             %30 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
 311                             %31 : java.type:"java.lang.Integer" = invoke %30 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 312                             %32 : java.type:"java.lang.Integer" = cast %31 @java.type:"java.lang.Integer";
 313                             yield %32;
 314                         }
 315                         ()java.type:"java.lang.Integer" -> {
 316                             %33 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
 317                             %34 : java.type:"java.lang.Integer" = invoke %33 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 318                             %35 : java.type:"java.lang.Integer" = cast %34 @java.type:"java.lang.Integer";
 319                             yield %35;
 320                         };
 321                     %36 : java.type:"int" = invoke %28 @java.ref:"java.lang.Integer::hashCode():int";
 322                     return;
 323                 };
 324                 """)
 325         @Reflect
 326         void testChainedCallCond(UnboundedInteger test, boolean cond) {
 327             // simple field name
 328             (cond ? x : x).hashCode();
 329 
 330             // qualified field name
 331             (cond ? test.x : test.x).hashCode();
 332 
 333             // simple method name
 334             (cond ? getX() : getX()).hashCode();
 335 
 336             // qualified method name
 337             (cond ? test.getX() : test.getX()).hashCode();
 338         }
 339 
 340         @IR("""
 341                 func @"testAssign" (%0 : java.type:"ErasedAccessTest$UnboundedInteger", %1 : java.type:"ErasedAccessTest$UnboundedInteger")java.type:"void" -> {
 342                     %2 : Var<java.type:"ErasedAccessTest$UnboundedInteger"> = var %1 @"test";
 343                     %3 : Var<java.type:"java.lang.Object"> = var @"o";
 344                     %4 : Var<java.type:"java.lang.Number"> = var @"n";
 345                     %5 : Var<java.type:"java.lang.Integer"> = var @"i";
 346                     %6 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 347                     var.store %3 %6;
 348                     %7 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 349                     %8 : java.type:"java.lang.Number" = cast %7 @java.type:"java.lang.Number";
 350                     var.store %4 %8;
 351                     %9 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 352                     %10 : java.type:"java.lang.Integer" = cast %9 @java.type:"java.lang.Integer";
 353                     var.store %5 %10;
 354                     %11 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 355                     %12 : java.type:"java.lang.Integer" = field.load %11 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 356                     var.store %3 %12;
 357                     %13 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 358                     %14 : java.type:"java.lang.Integer" = field.load %13 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 359                     %15 : java.type:"java.lang.Number" = cast %14 @java.type:"java.lang.Number";
 360                     var.store %4 %15;
 361                     %16 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 362                     %17 : java.type:"java.lang.Integer" = field.load %16 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 363                     %18 : java.type:"java.lang.Integer" = cast %17 @java.type:"java.lang.Integer";
 364                     var.store %5 %18;
 365                     %19 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 366                     var.store %3 %19;
 367                     %20 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 368                     %21 : java.type:"java.lang.Number" = cast %20 @java.type:"java.lang.Number";
 369                     var.store %4 %21;
 370                     %22 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 371                     %23 : java.type:"java.lang.Integer" = cast %22 @java.type:"java.lang.Integer";
 372                     var.store %5 %23;
 373                     %24 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 374                     %25 : java.type:"java.lang.Integer" = invoke %24 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 375                     var.store %3 %25;
 376                     %26 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 377                     %27 : java.type:"java.lang.Integer" = invoke %26 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 378                     %28 : java.type:"java.lang.Number" = cast %27 @java.type:"java.lang.Number";
 379                     var.store %4 %28;
 380                     %29 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 381                     %30 : java.type:"java.lang.Integer" = invoke %29 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 382                     %31 : java.type:"java.lang.Integer" = cast %30 @java.type:"java.lang.Integer";
 383                     var.store %5 %31;
 384                     return;
 385                 };
 386                 """)
 387         @Reflect
 388         void testAssign(UnboundedInteger test) {
 389             Object o; Number n; Integer i;
 390 
 391             // simple field name
 392             o = x;
 393             n = x;
 394             i = x;
 395 
 396             // qualified field name
 397             o = test.x;
 398             n = test.x;
 399             i = test.x;
 400 
 401             // simple method name
 402             o = getX();
 403             n = getX();
 404             i = getX();
 405 
 406             // qualified method name
 407             o = test.getX();
 408             n = test.getX();
 409             i = test.getX();
 410         }
 411 
 412         @IR("""
 413                 func @"testArrayInit" (%0 : java.type:"ErasedAccessTest$UnboundedInteger", %1 : java.type:"ErasedAccessTest$UnboundedInteger")java.type:"void" -> {
 414                     %2 : Var<java.type:"ErasedAccessTest$UnboundedInteger"> = var %1 @"test";
 415                     %3 : Var<java.type:"java.lang.Object[]"> = var @"o";
 416                     %4 : Var<java.type:"java.lang.Number[]"> = var @"n";
 417                     %5 : Var<java.type:"java.lang.Integer[]"> = var @"i";
 418                     %6 : java.type:"int" = constant @1;
 419                     %7 : java.type:"java.lang.Object[]" = new %6 @java.ref:"java.lang.Object[]::(int)";
 420                     %8 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 421                     %9 : java.type:"int" = constant @0;
 422                     array.store %7 %9 %8;
 423                     var.store %3 %7;
 424                     %10 : java.type:"int" = constant @1;
 425                     %11 : java.type:"java.lang.Number[]" = new %10 @java.ref:"java.lang.Number[]::(int)";
 426                     %12 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 427                     %13 : java.type:"java.lang.Number" = cast %12 @java.type:"java.lang.Number";
 428                     %14 : java.type:"int" = constant @0;
 429                     array.store %11 %14 %13;
 430                     var.store %4 %11;
 431                     %15 : java.type:"int" = constant @1;
 432                     %16 : java.type:"java.lang.Integer[]" = new %15 @java.ref:"java.lang.Integer[]::(int)";
 433                     %17 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 434                     %18 : java.type:"java.lang.Integer" = cast %17 @java.type:"java.lang.Integer";
 435                     %19 : java.type:"int" = constant @0;
 436                     array.store %16 %19 %18;
 437                     var.store %5 %16;
 438                     %20 : java.type:"int" = constant @1;
 439                     %21 : java.type:"java.lang.Object[]" = new %20 @java.ref:"java.lang.Object[]::(int)";
 440                     %22 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 441                     %23 : java.type:"java.lang.Integer" = field.load %22 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 442                     %24 : java.type:"int" = constant @0;
 443                     array.store %21 %24 %23;
 444                     var.store %3 %21;
 445                     %25 : java.type:"int" = constant @1;
 446                     %26 : java.type:"java.lang.Number[]" = new %25 @java.ref:"java.lang.Number[]::(int)";
 447                     %27 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 448                     %28 : java.type:"java.lang.Integer" = field.load %27 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 449                     %29 : java.type:"java.lang.Number" = cast %28 @java.type:"java.lang.Number";
 450                     %30 : java.type:"int" = constant @0;
 451                     array.store %26 %30 %29;
 452                     var.store %4 %26;
 453                     %31 : java.type:"int" = constant @1;
 454                     %32 : java.type:"java.lang.Integer[]" = new %31 @java.ref:"java.lang.Integer[]::(int)";
 455                     %33 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 456                     %34 : java.type:"java.lang.Integer" = field.load %33 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 457                     %35 : java.type:"java.lang.Integer" = cast %34 @java.type:"java.lang.Integer";
 458                     %36 : java.type:"int" = constant @0;
 459                     array.store %32 %36 %35;
 460                     var.store %5 %32;
 461                     %37 : java.type:"int" = constant @1;
 462                     %38 : java.type:"java.lang.Object[]" = new %37 @java.ref:"java.lang.Object[]::(int)";
 463                     %39 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 464                     %40 : java.type:"int" = constant @0;
 465                     array.store %38 %40 %39;
 466                     var.store %3 %38;
 467                     %41 : java.type:"int" = constant @1;
 468                     %42 : java.type:"java.lang.Number[]" = new %41 @java.ref:"java.lang.Number[]::(int)";
 469                     %43 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 470                     %44 : java.type:"java.lang.Number" = cast %43 @java.type:"java.lang.Number";
 471                     %45 : java.type:"int" = constant @0;
 472                     array.store %42 %45 %44;
 473                     var.store %4 %42;
 474                     %46 : java.type:"int" = constant @1;
 475                     %47 : java.type:"java.lang.Integer[]" = new %46 @java.ref:"java.lang.Integer[]::(int)";
 476                     %48 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 477                     %49 : java.type:"java.lang.Integer" = cast %48 @java.type:"java.lang.Integer";
 478                     %50 : java.type:"int" = constant @0;
 479                     array.store %47 %50 %49;
 480                     var.store %5 %47;
 481                     %51 : java.type:"int" = constant @1;
 482                     %52 : java.type:"java.lang.Object[]" = new %51 @java.ref:"java.lang.Object[]::(int)";
 483                     %53 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 484                     %54 : java.type:"java.lang.Integer" = invoke %53 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 485                     %55 : java.type:"int" = constant @0;
 486                     array.store %52 %55 %54;
 487                     var.store %3 %52;
 488                     %56 : java.type:"int" = constant @1;
 489                     %57 : java.type:"java.lang.Number[]" = new %56 @java.ref:"java.lang.Number[]::(int)";
 490                     %58 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 491                     %59 : java.type:"java.lang.Integer" = invoke %58 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 492                     %60 : java.type:"java.lang.Number" = cast %59 @java.type:"java.lang.Number";
 493                     %61 : java.type:"int" = constant @0;
 494                     array.store %57 %61 %60;
 495                     var.store %4 %57;
 496                     %62 : java.type:"int" = constant @1;
 497                     %63 : java.type:"java.lang.Integer[]" = new %62 @java.ref:"java.lang.Integer[]::(int)";
 498                     %64 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 499                     %65 : java.type:"java.lang.Integer" = invoke %64 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 500                     %66 : java.type:"java.lang.Integer" = cast %65 @java.type:"java.lang.Integer";
 501                     %67 : java.type:"int" = constant @0;
 502                     array.store %63 %67 %66;
 503                     var.store %5 %63;
 504                     return;
 505                 };
 506                 """)
 507         @Reflect
 508         void testArrayInit(UnboundedInteger test) {
 509             Object[] o; Number[] n; Integer[] i;
 510 
 511             // simple field name
 512             o = new Object[] { x };
 513             n = new Number[] { x };
 514             i = new Integer[] { x };
 515 
 516             // qualified field name
 517             o = new Object[] { test.x };
 518             n = new Number[] { test.x };
 519             i = new Integer[] { test.x };
 520 
 521             // simple method name
 522             o = new Object[] { getX() };
 523             n = new Number[] { getX() };
 524             i = new Integer[] { getX() };
 525 
 526             // qualified method name
 527             o = new Object[] { test.getX() };
 528             n = new Number[] { test.getX() };
 529             i = new Integer[] { test.getX() };
 530         }
 531 
 532         @IR("""
 533                 func @"testCast" (%0 : java.type:"ErasedAccessTest$UnboundedInteger", %1 : java.type:"ErasedAccessTest$UnboundedInteger")java.type:"void" -> {
 534                     %2 : Var<java.type:"ErasedAccessTest$UnboundedInteger"> = var %1 @"test";
 535                     %3 : Var<java.type:"java.lang.Object"> = var @"o";
 536                     %4 : Var<java.type:"java.lang.Number"> = var @"n";
 537                     %5 : Var<java.type:"java.lang.Integer"> = var @"i";
 538                     %6 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 539                     var.store %3 %6;
 540                     %7 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 541                     %8 : java.type:"java.lang.Number" = cast %7 @java.type:"java.lang.Number";
 542                     var.store %4 %8;
 543                     %9 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 544                     %10 : java.type:"java.lang.Integer" = cast %9 @java.type:"java.lang.Integer";
 545                     var.store %5 %10;
 546                     %11 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 547                     %12 : java.type:"java.lang.Integer" = field.load %11 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 548                     var.store %3 %12;
 549                     %13 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 550                     %14 : java.type:"java.lang.Integer" = field.load %13 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 551                     %15 : java.type:"java.lang.Number" = cast %14 @java.type:"java.lang.Number";
 552                     var.store %4 %15;
 553                     %16 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 554                     %17 : java.type:"java.lang.Integer" = field.load %16 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 555                     %18 : java.type:"java.lang.Integer" = cast %17 @java.type:"java.lang.Integer";
 556                     var.store %5 %18;
 557                     %19 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 558                     var.store %3 %19;
 559                     %20 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 560                     %21 : java.type:"java.lang.Number" = cast %20 @java.type:"java.lang.Number";
 561                     var.store %4 %21;
 562                     %22 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 563                     %23 : java.type:"java.lang.Integer" = cast %22 @java.type:"java.lang.Integer";
 564                     var.store %5 %23;
 565                     %24 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 566                     %25 : java.type:"java.lang.Integer" = invoke %24 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 567                     var.store %3 %25;
 568                     %26 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 569                     %27 : java.type:"java.lang.Integer" = invoke %26 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 570                     %28 : java.type:"java.lang.Number" = cast %27 @java.type:"java.lang.Number";
 571                     var.store %4 %28;
 572                     %29 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 573                     %30 : java.type:"java.lang.Integer" = invoke %29 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 574                     %31 : java.type:"java.lang.Integer" = cast %30 @java.type:"java.lang.Integer";
 575                     var.store %5 %31;
 576                     return;
 577                 };
 578                 """)
 579         @Reflect
 580         void testCast(UnboundedInteger test) {
 581             Object o; Number n; Integer i;
 582 
 583             // simple field name
 584             o = (Object) x;
 585             n = (Number) x;
 586             i = (Integer) x;
 587 
 588             // qualified field name
 589             o = (Object) test.x;
 590             n = (Number) test.x;
 591             i = (Integer) test.x;
 592 
 593             // simple method name
 594             o = (Object) getX();
 595             n = (Number) getX();
 596             i = (Integer) getX();
 597 
 598             // qualified method name
 599             o = (Object) test.getX();
 600             n = (Number) test.getX();
 601             i = (Integer) test.getX();
 602         }
 603 
 604         @IR("""
 605                 func @"testIntersectionCast" (%0 : java.type:"ErasedAccessTest$UnboundedInteger", %1 : java.type:"ErasedAccessTest$UnboundedInteger")java.type:"void" -> {
 606                     %2 : Var<java.type:"ErasedAccessTest$UnboundedInteger"> = var %1 @"test";
 607                     %3 : Var<java.type:"java.lang.Object"> = var @"o";
 608                     %4 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 609                     %5 : java.type:"java.lang.Comparable<java.lang.Integer>" = cast %4 @java.type:"java.lang.Comparable";
 610                     %6 : java.type:"java.io.Serializable" = cast %5 @java.type:"java.io.Serializable";
 611                     %7 : java.type:"java.lang.Number" = cast %6 @java.type:"java.lang.Number";
 612                     var.store %3 %7;
 613                     %8 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 614                     %9 : java.type:"java.lang.Integer" = field.load %8 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 615                     %10 : java.type:"java.lang.Comparable<java.lang.Integer>" = cast %9 @java.type:"java.lang.Comparable";
 616                     %11 : java.type:"java.io.Serializable" = cast %10 @java.type:"java.io.Serializable";
 617                     %12 : java.type:"java.lang.Number" = cast %11 @java.type:"java.lang.Number";
 618                     var.store %3 %12;
 619                     %13 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 620                     %14 : java.type:"java.lang.Comparable<java.lang.Integer>" = cast %13 @java.type:"java.lang.Comparable";
 621                     %15 : java.type:"java.io.Serializable" = cast %14 @java.type:"java.io.Serializable";
 622                     %16 : java.type:"java.lang.Number" = cast %15 @java.type:"java.lang.Number";
 623                     var.store %3 %16;
 624                     %17 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 625                     %18 : java.type:"java.lang.Integer" = invoke %17 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 626                     %19 : java.type:"java.lang.Comparable<java.lang.Integer>" = cast %18 @java.type:"java.lang.Comparable";
 627                     %20 : java.type:"java.io.Serializable" = cast %19 @java.type:"java.io.Serializable";
 628                     %21 : java.type:"java.lang.Number" = cast %20 @java.type:"java.lang.Number";
 629                     var.store %3 %21;
 630                     return;
 631                 };
 632                 """)
 633         @Reflect
 634         void testIntersectionCast(UnboundedInteger test) {
 635             Object o;
 636 
 637             // simple field name
 638             o = (Number & Comparable<Integer> & Serializable) x;
 639 
 640             // qualified field name
 641             o = (Number & Comparable<Integer> & Serializable) test.x;
 642 
 643             // simple method name
 644             o = (Number & Comparable<Integer> & Serializable) getX();
 645 
 646             // qualified method name
 647             o = (Number & Comparable<Integer> & Serializable) test.getX();
 648         }
 649 
 650         void o(Object o) { }
 651         void n(Number n) { }
 652         void i(Integer i) { }
 653 
 654         @IR("""
 655                 func @"testMethod" (%0 : java.type:"ErasedAccessTest$UnboundedInteger", %1 : java.type:"ErasedAccessTest$UnboundedInteger")java.type:"void" -> {
 656                     %2 : Var<java.type:"ErasedAccessTest$UnboundedInteger"> = var %1 @"test";
 657                     %3 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 658                     invoke %0 %3 @java.ref:"ErasedAccessTest$UnboundedInteger::o(java.lang.Object):void";
 659                     %4 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 660                     %5 : java.type:"java.lang.Number" = cast %4 @java.type:"java.lang.Number";
 661                     invoke %0 %5 @java.ref:"ErasedAccessTest$UnboundedInteger::n(java.lang.Number):void";
 662                     %6 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 663                     %7 : java.type:"java.lang.Integer" = cast %6 @java.type:"java.lang.Integer";
 664                     invoke %0 %7 @java.ref:"ErasedAccessTest$UnboundedInteger::i(java.lang.Integer):void";
 665                     %8 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 666                     %9 : java.type:"java.lang.Integer" = field.load %8 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 667                     invoke %0 %9 @java.ref:"ErasedAccessTest$UnboundedInteger::o(java.lang.Object):void";
 668                     %10 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 669                     %11 : java.type:"java.lang.Integer" = field.load %10 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 670                     %12 : java.type:"java.lang.Number" = cast %11 @java.type:"java.lang.Number";
 671                     invoke %0 %12 @java.ref:"ErasedAccessTest$UnboundedInteger::n(java.lang.Number):void";
 672                     %13 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 673                     %14 : java.type:"java.lang.Integer" = field.load %13 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 674                     %15 : java.type:"java.lang.Integer" = cast %14 @java.type:"java.lang.Integer";
 675                     invoke %0 %15 @java.ref:"ErasedAccessTest$UnboundedInteger::i(java.lang.Integer):void";
 676                     %16 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 677                     invoke %0 %16 @java.ref:"ErasedAccessTest$UnboundedInteger::o(java.lang.Object):void";
 678                     %17 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 679                     %18 : java.type:"java.lang.Number" = cast %17 @java.type:"java.lang.Number";
 680                     invoke %0 %18 @java.ref:"ErasedAccessTest$UnboundedInteger::n(java.lang.Number):void";
 681                     %19 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 682                     %20 : java.type:"java.lang.Integer" = cast %19 @java.type:"java.lang.Integer";
 683                     invoke %0 %20 @java.ref:"ErasedAccessTest$UnboundedInteger::i(java.lang.Integer):void";
 684                     %21 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 685                     %22 : java.type:"java.lang.Integer" = invoke %21 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 686                     invoke %0 %22 @java.ref:"ErasedAccessTest$UnboundedInteger::o(java.lang.Object):void";
 687                     %23 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 688                     %24 : java.type:"java.lang.Integer" = invoke %23 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 689                     %25 : java.type:"java.lang.Number" = cast %24 @java.type:"java.lang.Number";
 690                     invoke %0 %25 @java.ref:"ErasedAccessTest$UnboundedInteger::n(java.lang.Number):void";
 691                     %26 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 692                     %27 : java.type:"java.lang.Integer" = invoke %26 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 693                     %28 : java.type:"java.lang.Integer" = cast %27 @java.type:"java.lang.Integer";
 694                     invoke %0 %28 @java.ref:"ErasedAccessTest$UnboundedInteger::i(java.lang.Integer):void";
 695                     return;
 696                 };
 697                 """)
 698         @Reflect
 699         void testMethod(UnboundedInteger test) {
 700             // simple field name
 701             o(x);
 702             n(x);
 703             i(x);
 704 
 705             // qualified field name
 706             o(test.x);
 707             n(test.x);
 708             i(test.x);
 709 
 710             // simple method name
 711             o(getX());
 712             n(getX());
 713             i(getX());
 714 
 715             // qualified method name
 716             o(test.getX());
 717             n(test.getX());
 718             i(test.getX());
 719         }
 720 
 721         @IR("""
 722                 func @"testWidening" (%0 : java.type:"ErasedAccessTest$UnboundedInteger", %1 : java.type:"ErasedAccessTest$UnboundedInteger")java.type:"void" -> {
 723                     %2 : Var<java.type:"ErasedAccessTest$UnboundedInteger"> = var %1 @"test";
 724                     %3 : Var<java.type:"long"> = var @"l";
 725                     %4 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 726                     %5 : java.type:"java.lang.Integer" = cast %4 @java.type:"java.lang.Integer";
 727                     %6 : java.type:"int" = invoke %5 @java.ref:"java.lang.Integer::intValue():int";
 728                     %7 : java.type:"long" = conv %6;
 729                     var.store %3 %7;
 730                     %8 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 731                     %9 : java.type:"java.lang.Integer" = field.load %8 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 732                     %10 : java.type:"java.lang.Integer" = cast %9 @java.type:"java.lang.Integer";
 733                     %11 : java.type:"int" = invoke %10 @java.ref:"java.lang.Integer::intValue():int";
 734                     %12 : java.type:"long" = conv %11;
 735                     var.store %3 %12;
 736                     %13 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 737                     %14 : java.type:"java.lang.Integer" = cast %13 @java.type:"java.lang.Integer";
 738                     %15 : java.type:"int" = invoke %14 @java.ref:"java.lang.Integer::intValue():int";
 739                     %16 : java.type:"long" = conv %15;
 740                     var.store %3 %16;
 741                     %17 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 742                     %18 : java.type:"java.lang.Integer" = invoke %17 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 743                     %19 : java.type:"java.lang.Integer" = cast %18 @java.type:"java.lang.Integer";
 744                     %20 : java.type:"int" = invoke %19 @java.ref:"java.lang.Integer::intValue():int";
 745                     %21 : java.type:"long" = conv %20;
 746                     var.store %3 %21;
 747                     return;
 748                 };
 749                 """)
 750         @Reflect
 751         void testWidening(UnboundedInteger test) {
 752             long l;
 753 
 754             // simple field name
 755             l = x;
 756 
 757             // qualified field name
 758             l = test.x;
 759 
 760             // simple method name
 761             l = getX();
 762 
 763             // qualified method name
 764             l = test.getX();
 765         }
 766 
 767         @IR("""
 768                 func @"testAssert" (%0 : java.type:"ErasedAccessTest$UnboundedInteger", %1 : java.type:"ErasedAccessTest$UnboundedInteger")java.type:"void" -> {
 769                     %2 : Var<java.type:"ErasedAccessTest$UnboundedInteger"> = var %1 @"test";
 770                     assert
 771                         ()java.type:"boolean" -> {
 772                             %3 : java.type:"boolean" = constant @false;
 773                             yield %3;
 774                         }
 775                         ()java.type:"java.lang.Integer" -> {
 776                             %4 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 777                             %5 : java.type:"java.lang.Integer" = cast %4 @java.type:"java.lang.Integer";
 778                             yield %5;
 779                         };
 780                     assert
 781                         ()java.type:"boolean" -> {
 782                             %6 : java.type:"boolean" = constant @false;
 783                             yield %6;
 784                         }
 785                         ()java.type:"java.lang.Integer" -> {
 786                             %7 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 787                             %8 : java.type:"java.lang.Integer" = field.load %7 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 788                             %9 : java.type:"java.lang.Integer" = cast %8 @java.type:"java.lang.Integer";
 789                             yield %9;
 790                         };
 791                     assert
 792                         ()java.type:"boolean" -> {
 793                             %10 : java.type:"boolean" = constant @false;
 794                             yield %10;
 795                         }
 796                         ()java.type:"java.lang.Integer" -> {
 797                             %11 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 798                             %12 : java.type:"java.lang.Integer" = cast %11 @java.type:"java.lang.Integer";
 799                             yield %12;
 800                         };
 801                     assert
 802                         ()java.type:"boolean" -> {
 803                             %13 : java.type:"boolean" = constant @false;
 804                             yield %13;
 805                         }
 806                         ()java.type:"java.lang.Integer" -> {
 807                             %14 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 808                             %15 : java.type:"java.lang.Integer" = invoke %14 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 809                             %16 : java.type:"java.lang.Integer" = cast %15 @java.type:"java.lang.Integer";
 810                             yield %16;
 811                         };
 812                     return;
 813                 };
 814                 """)
 815         @Reflect
 816         void testAssert(UnboundedInteger test) {
 817             // simple field name
 818             assert false : x;
 819 
 820             // qualified field name
 821             assert false : test.x;
 822 
 823             // simple method name
 824             assert false : getX();
 825 
 826             // qualified method name
 827             assert false : test.getX();
 828         }
 829 
 830         @IR("""
 831                 func @"testSynchronized" (%0 : java.type:"ErasedAccessTest$UnboundedInteger", %1 : java.type:"ErasedAccessTest$UnboundedInteger")java.type:"void" -> {
 832                     %2 : Var<java.type:"ErasedAccessTest$UnboundedInteger"> = var %1 @"test";
 833                     java.synchronized
 834                         ()java.type:"java.lang.Integer" -> {
 835                             %3 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 836                             %4 : java.type:"java.lang.Integer" = cast %3 @java.type:"java.lang.Integer";
 837                             yield %4;
 838                         }
 839                         ()java.type:"void" -> {
 840                             yield;
 841                         };
 842                     java.synchronized
 843                         ()java.type:"java.lang.Integer" -> {
 844                             %5 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 845                             %6 : java.type:"java.lang.Integer" = field.load %5 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 846                             %7 : java.type:"java.lang.Integer" = cast %6 @java.type:"java.lang.Integer";
 847                             yield %7;
 848                         }
 849                         ()java.type:"void" -> {
 850                             yield;
 851                         };
 852                     java.synchronized
 853                         ()java.type:"java.lang.Integer" -> {
 854                             %8 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 855                             %9 : java.type:"java.lang.Integer" = cast %8 @java.type:"java.lang.Integer";
 856                             yield %9;
 857                         }
 858                         ()java.type:"void" -> {
 859                             yield;
 860                         };
 861                     java.synchronized
 862                         ()java.type:"java.lang.Integer" -> {
 863                             %10 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
 864                             %11 : java.type:"java.lang.Integer" = invoke %10 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
 865                             %12 : java.type:"java.lang.Integer" = cast %11 @java.type:"java.lang.Integer";
 866                             yield %12;
 867                         }
 868                         ()java.type:"void" -> {
 869                             yield;
 870                         };
 871                     return;
 872                 };
 873                 """)
 874         @Reflect
 875         @SuppressWarnings("identity")
 876         void testSynchronized(UnboundedInteger test) {
 877             // simple field name
 878             synchronized (x) { };
 879 
 880             // qualified field name
 881             synchronized (test.x) { };
 882 
 883             // simple method name
 884             synchronized (getX()) { };
 885 
 886             // qualified method name
 887             synchronized (test.getX()) { };
 888         }
 889 
 890         @IR("""
 891                 func @"testYield" (%0 : java.type:"ErasedAccessTest$UnboundedInteger", %1 : java.type:"ErasedAccessTest$UnboundedInteger", %2 : java.type:"int")java.type:"void" -> {
 892                     %3 : Var<java.type:"ErasedAccessTest$UnboundedInteger"> = var %1 @"test";
 893                     %4 : Var<java.type:"int"> = var %2 @"s";
 894                     %5 : Var<java.type:"java.lang.Object"> = var @"o";
 895                     %6 : Var<java.type:"java.lang.Number"> = var @"n";
 896                     %7 : Var<java.type:"java.lang.Integer"> = var @"i";
 897                     %8 : java.type:"int" = var.load %4;
 898                     %9 : java.type:"java.lang.Object" = java.switch.expression %8
 899                         (%10 : java.type:"int")java.type:"boolean" -> {
 900                             %11 : java.type:"int" = constant @0;
 901                             %12 : java.type:"boolean" = eq %10 %11;
 902                             yield %12;
 903                         }
 904                         ()java.type:"java.lang.Object" -> {
 905                             %13 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 906                             %14 : java.type:"java.lang.Integer" = cast %13 @java.type:"java.lang.Integer";
 907                             yield %14;
 908                         }
 909                         ()java.type:"boolean" -> {
 910                             %15 : java.type:"boolean" = constant @true;
 911                             yield %15;
 912                         }
 913                         ()java.type:"java.lang.Object" -> {
 914                             %16 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 915                             %17 : java.type:"java.lang.Integer" = cast %16 @java.type:"java.lang.Integer";
 916                             yield %17;
 917                         };
 918                     var.store %5 %9;
 919                     %18 : java.type:"int" = var.load %4;
 920                     %19 : java.type:"java.lang.Number" = java.switch.expression %18
 921                         (%20 : java.type:"int")java.type:"boolean" -> {
 922                             %21 : java.type:"int" = constant @0;
 923                             %22 : java.type:"boolean" = eq %20 %21;
 924                             yield %22;
 925                         }
 926                         ()java.type:"java.lang.Number" -> {
 927                             %23 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 928                             %24 : java.type:"java.lang.Integer" = cast %23 @java.type:"java.lang.Integer";
 929                             yield %24;
 930                         }
 931                         ()java.type:"boolean" -> {
 932                             %25 : java.type:"boolean" = constant @true;
 933                             yield %25;
 934                         }
 935                         ()java.type:"java.lang.Number" -> {
 936                             %26 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 937                             %27 : java.type:"java.lang.Integer" = cast %26 @java.type:"java.lang.Integer";
 938                             yield %27;
 939                         };
 940                     var.store %6 %19;
 941                     %28 : java.type:"int" = var.load %4;
 942                     %29 : java.type:"java.lang.Integer" = java.switch.expression %28
 943                         (%30 : java.type:"int")java.type:"boolean" -> {
 944                             %31 : java.type:"int" = constant @0;
 945                             %32 : java.type:"boolean" = eq %30 %31;
 946                             yield %32;
 947                         }
 948                         ()java.type:"java.lang.Integer" -> {
 949                             %33 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 950                             %34 : java.type:"java.lang.Integer" = cast %33 @java.type:"java.lang.Integer";
 951                             yield %34;
 952                         }
 953                         ()java.type:"boolean" -> {
 954                             %35 : java.type:"boolean" = constant @true;
 955                             yield %35;
 956                         }
 957                         ()java.type:"java.lang.Integer" -> {
 958                             %36 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 959                             %37 : java.type:"java.lang.Integer" = cast %36 @java.type:"java.lang.Integer";
 960                             yield %37;
 961                         };
 962                     var.store %7 %29;
 963                     %38 : java.type:"int" = var.load %4;
 964                     %39 : java.type:"java.lang.Object" = java.switch.expression %38
 965                         (%40 : java.type:"int")java.type:"boolean" -> {
 966                             %41 : java.type:"int" = constant @0;
 967                             %42 : java.type:"boolean" = eq %40 %41;
 968                             yield %42;
 969                         }
 970                         ()java.type:"java.lang.Object" -> {
 971                             %43 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
 972                             %44 : java.type:"java.lang.Integer" = field.load %43 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 973                             %45 : java.type:"java.lang.Integer" = cast %44 @java.type:"java.lang.Integer";
 974                             yield %45;
 975                         }
 976                         ()java.type:"boolean" -> {
 977                             %46 : java.type:"boolean" = constant @true;
 978                             yield %46;
 979                         }
 980                         ()java.type:"java.lang.Object" -> {
 981                             %47 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
 982                             %48 : java.type:"java.lang.Integer" = field.load %47 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 983                             %49 : java.type:"java.lang.Integer" = cast %48 @java.type:"java.lang.Integer";
 984                             yield %49;
 985                         };
 986                     var.store %5 %39;
 987                     %50 : java.type:"int" = var.load %4;
 988                     %51 : java.type:"java.lang.Number" = java.switch.expression %50
 989                         (%52 : java.type:"int")java.type:"boolean" -> {
 990                             %53 : java.type:"int" = constant @0;
 991                             %54 : java.type:"boolean" = eq %52 %53;
 992                             yield %54;
 993                         }
 994                         ()java.type:"java.lang.Number" -> {
 995                             %55 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
 996                             %56 : java.type:"java.lang.Integer" = field.load %55 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
 997                             %57 : java.type:"java.lang.Integer" = cast %56 @java.type:"java.lang.Integer";
 998                             yield %57;
 999                         }
1000                         ()java.type:"boolean" -> {
1001                             %58 : java.type:"boolean" = constant @true;
1002                             yield %58;
1003                         }
1004                         ()java.type:"java.lang.Number" -> {
1005                             %59 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
1006                             %60 : java.type:"java.lang.Integer" = field.load %59 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
1007                             %61 : java.type:"java.lang.Integer" = cast %60 @java.type:"java.lang.Integer";
1008                             yield %61;
1009                         };
1010                     var.store %6 %51;
1011                     %62 : java.type:"int" = var.load %4;
1012                     %63 : java.type:"java.lang.Integer" = java.switch.expression %62
1013                         (%64 : java.type:"int")java.type:"boolean" -> {
1014                             %65 : java.type:"int" = constant @0;
1015                             %66 : java.type:"boolean" = eq %64 %65;
1016                             yield %66;
1017                         }
1018                         ()java.type:"java.lang.Integer" -> {
1019                             %67 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
1020                             %68 : java.type:"java.lang.Integer" = field.load %67 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
1021                             %69 : java.type:"java.lang.Integer" = cast %68 @java.type:"java.lang.Integer";
1022                             yield %69;
1023                         }
1024                         ()java.type:"boolean" -> {
1025                             %70 : java.type:"boolean" = constant @true;
1026                             yield %70;
1027                         }
1028                         ()java.type:"java.lang.Integer" -> {
1029                             %71 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
1030                             %72 : java.type:"java.lang.Integer" = field.load %71 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
1031                             %73 : java.type:"java.lang.Integer" = cast %72 @java.type:"java.lang.Integer";
1032                             yield %73;
1033                         };
1034                     var.store %7 %63;
1035                     %74 : java.type:"int" = var.load %4;
1036                     %75 : java.type:"java.lang.Object" = java.switch.expression %74
1037                         (%76 : java.type:"int")java.type:"boolean" -> {
1038                             %77 : java.type:"int" = constant @0;
1039                             %78 : java.type:"boolean" = eq %76 %77;
1040                             yield %78;
1041                         }
1042                         ()java.type:"java.lang.Object" -> {
1043                             %79 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
1044                             %80 : java.type:"java.lang.Integer" = cast %79 @java.type:"java.lang.Integer";
1045                             yield %80;
1046                         }
1047                         ()java.type:"boolean" -> {
1048                             %81 : java.type:"boolean" = constant @true;
1049                             yield %81;
1050                         }
1051                         ()java.type:"java.lang.Object" -> {
1052                             %82 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
1053                             %83 : java.type:"java.lang.Integer" = cast %82 @java.type:"java.lang.Integer";
1054                             yield %83;
1055                         };
1056                     var.store %5 %75;
1057                     %84 : java.type:"int" = var.load %4;
1058                     %85 : java.type:"java.lang.Number" = java.switch.expression %84
1059                         (%86 : java.type:"int")java.type:"boolean" -> {
1060                             %87 : java.type:"int" = constant @0;
1061                             %88 : java.type:"boolean" = eq %86 %87;
1062                             yield %88;
1063                         }
1064                         ()java.type:"java.lang.Number" -> {
1065                             %89 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
1066                             %90 : java.type:"java.lang.Integer" = cast %89 @java.type:"java.lang.Integer";
1067                             yield %90;
1068                         }
1069                         ()java.type:"boolean" -> {
1070                             %91 : java.type:"boolean" = constant @true;
1071                             yield %91;
1072                         }
1073                         ()java.type:"java.lang.Number" -> {
1074                             %92 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
1075                             %93 : java.type:"java.lang.Integer" = cast %92 @java.type:"java.lang.Integer";
1076                             yield %93;
1077                         };
1078                     var.store %6 %85;
1079                     %94 : java.type:"int" = var.load %4;
1080                     %95 : java.type:"java.lang.Integer" = java.switch.expression %94
1081                         (%96 : java.type:"int")java.type:"boolean" -> {
1082                             %97 : java.type:"int" = constant @0;
1083                             %98 : java.type:"boolean" = eq %96 %97;
1084                             yield %98;
1085                         }
1086                         ()java.type:"java.lang.Integer" -> {
1087                             %99 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
1088                             %100 : java.type:"java.lang.Integer" = cast %99 @java.type:"java.lang.Integer";
1089                             yield %100;
1090                         }
1091                         ()java.type:"boolean" -> {
1092                             %101 : java.type:"boolean" = constant @true;
1093                             yield %101;
1094                         }
1095                         ()java.type:"java.lang.Integer" -> {
1096                             %102 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
1097                             %103 : java.type:"java.lang.Integer" = cast %102 @java.type:"java.lang.Integer";
1098                             yield %103;
1099                         };
1100                     var.store %7 %95;
1101                     %104 : java.type:"int" = var.load %4;
1102                     %105 : java.type:"java.lang.Object" = java.switch.expression %104
1103                         (%106 : java.type:"int")java.type:"boolean" -> {
1104                             %107 : java.type:"int" = constant @0;
1105                             %108 : java.type:"boolean" = eq %106 %107;
1106                             yield %108;
1107                         }
1108                         ()java.type:"java.lang.Object" -> {
1109                             %109 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
1110                             %110 : java.type:"java.lang.Integer" = invoke %109 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
1111                             %111 : java.type:"java.lang.Integer" = cast %110 @java.type:"java.lang.Integer";
1112                             yield %111;
1113                         }
1114                         ()java.type:"boolean" -> {
1115                             %112 : java.type:"boolean" = constant @true;
1116                             yield %112;
1117                         }
1118                         ()java.type:"java.lang.Object" -> {
1119                             %113 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
1120                             %114 : java.type:"java.lang.Integer" = invoke %113 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
1121                             %115 : java.type:"java.lang.Integer" = cast %114 @java.type:"java.lang.Integer";
1122                             yield %115;
1123                         };
1124                     var.store %5 %105;
1125                     %116 : java.type:"int" = var.load %4;
1126                     %117 : java.type:"java.lang.Number" = java.switch.expression %116
1127                         (%118 : java.type:"int")java.type:"boolean" -> {
1128                             %119 : java.type:"int" = constant @0;
1129                             %120 : java.type:"boolean" = eq %118 %119;
1130                             yield %120;
1131                         }
1132                         ()java.type:"java.lang.Number" -> {
1133                             %121 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
1134                             %122 : java.type:"java.lang.Integer" = invoke %121 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
1135                             %123 : java.type:"java.lang.Integer" = cast %122 @java.type:"java.lang.Integer";
1136                             yield %123;
1137                         }
1138                         ()java.type:"boolean" -> {
1139                             %124 : java.type:"boolean" = constant @true;
1140                             yield %124;
1141                         }
1142                         ()java.type:"java.lang.Number" -> {
1143                             %125 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
1144                             %126 : java.type:"java.lang.Integer" = invoke %125 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
1145                             %127 : java.type:"java.lang.Integer" = cast %126 @java.type:"java.lang.Integer";
1146                             yield %127;
1147                         };
1148                     var.store %6 %117;
1149                     %128 : java.type:"int" = var.load %4;
1150                     %129 : java.type:"java.lang.Integer" = java.switch.expression %128
1151                         (%130 : java.type:"int")java.type:"boolean" -> {
1152                             %131 : java.type:"int" = constant @0;
1153                             %132 : java.type:"boolean" = eq %130 %131;
1154                             yield %132;
1155                         }
1156                         ()java.type:"java.lang.Integer" -> {
1157                             %133 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
1158                             %134 : java.type:"java.lang.Integer" = invoke %133 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
1159                             %135 : java.type:"java.lang.Integer" = cast %134 @java.type:"java.lang.Integer";
1160                             yield %135;
1161                         }
1162                         ()java.type:"boolean" -> {
1163                             %136 : java.type:"boolean" = constant @true;
1164                             yield %136;
1165                         }
1166                         ()java.type:"java.lang.Integer" -> {
1167                             %137 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
1168                             %138 : java.type:"java.lang.Integer" = invoke %137 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
1169                             %139 : java.type:"java.lang.Integer" = cast %138 @java.type:"java.lang.Integer";
1170                             yield %139;
1171                         };
1172                     var.store %7 %129;
1173                     return;
1174                 };
1175                 """)
1176         @Reflect
1177         void testYield(UnboundedInteger test, int s) {
1178             Object o; Number n; Integer i;
1179 
1180             // simple field name
1181             o = switch (s) {
1182                 case 0 -> x;
1183                 default -> x;
1184             };
1185 
1186             n = switch (s) {
1187                 case 0 -> x;
1188                 default -> x;
1189             };
1190 
1191             i = switch (s) {
1192                 case 0 -> x;
1193                 default -> x;
1194             };
1195 
1196             // qualified field name
1197             o = switch (s) {
1198                 case 0 -> test.x;
1199                 default -> test.x;
1200             };
1201 
1202             n = switch (s) {
1203                 case 0 -> test.x;
1204                 default -> test.x;
1205             };
1206 
1207             i = switch (s) {
1208                 case 0 -> test.x;
1209                 default -> test.x;
1210             };
1211 
1212             // simple method name
1213             o = switch (s) {
1214                 case 0 -> getX();
1215                 default -> getX();
1216             };
1217 
1218             n = switch (s) {
1219                 case 0 -> getX();
1220                 default -> getX();
1221             };
1222 
1223             i = switch (s) {
1224                 case 0 -> getX();
1225                 default -> getX();
1226             };
1227 
1228             // qualified method name
1229             o = switch (s) {
1230                 case 0 -> test.getX();
1231                 default -> test.getX();
1232             };
1233 
1234             n = switch (s) {
1235                 case 0 -> test.getX();
1236                 default -> test.getX();
1237             };
1238 
1239             i = switch (s) {
1240                 case 0 -> test.getX();
1241                 default -> test.getX();
1242             };
1243         }
1244 
1245         @IR("""
1246                 func @"testThrows" (%0 : java.type:"ErasedAccessTest$UnboundedInteger", %1 : java.type:"ErasedAccessTest$UnboundedInteger", %2 : java.type:"boolean")java.type:"void" -> {
1247                     %3 : Var<java.type:"ErasedAccessTest$UnboundedInteger"> = var %1 @"test";
1248                     %4 : Var<java.type:"boolean"> = var %2 @"cond";
1249                     java.if
1250                         ()java.type:"boolean" -> {
1251                             %5 : java.type:"boolean" = var.load %4;
1252                             yield %5;
1253                         }
1254                         ()java.type:"void" -> {
1255                             %6 : java.type:"java.lang.WrongThreadException" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::t:java.lang.Throwable";
1256                             %7 : java.type:"java.lang.WrongThreadException" = cast %6 @java.type:"java.lang.WrongThreadException";
1257                             throw %7;
1258                         }
1259                         ()java.type:"void" -> {
1260                             yield;
1261                         };
1262                     java.if
1263                         ()java.type:"boolean" -> {
1264                             %8 : java.type:"boolean" = var.load %4;
1265                             yield %8;
1266                         }
1267                         ()java.type:"void" -> {
1268                             %9 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
1269                             %10 : java.type:"java.lang.WrongThreadException" = field.load %9 @java.ref:"ErasedAccessTest$UnboundedInteger::t:java.lang.Throwable";
1270                             %11 : java.type:"java.lang.WrongThreadException" = cast %10 @java.type:"java.lang.WrongThreadException";
1271                             throw %11;
1272                         }
1273                         ()java.type:"void" -> {
1274                             yield;
1275                         };
1276                     java.if
1277                         ()java.type:"boolean" -> {
1278                             %12 : java.type:"boolean" = var.load %4;
1279                             yield %12;
1280                         }
1281                         ()java.type:"void" -> {
1282                             %13 : java.type:"java.lang.WrongThreadException" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getT():java.lang.Throwable";
1283                             %14 : java.type:"java.lang.WrongThreadException" = cast %13 @java.type:"java.lang.WrongThreadException";
1284                             throw %14;
1285                         }
1286                         ()java.type:"void" -> {
1287                             yield;
1288                         };
1289                     java.if
1290                         ()java.type:"boolean" -> {
1291                             %15 : java.type:"boolean" = var.load %4;
1292                             yield %15;
1293                         }
1294                         ()java.type:"void" -> {
1295                             %16 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %3;
1296                             %17 : java.type:"java.lang.WrongThreadException" = invoke %16 @java.ref:"ErasedAccessTest$UnboundedInteger::getT():java.lang.Throwable";
1297                             %18 : java.type:"java.lang.WrongThreadException" = cast %17 @java.type:"java.lang.WrongThreadException";
1298                             throw %18;
1299                         }
1300                         ()java.type:"void" -> {
1301                             yield;
1302                         };
1303                     return;
1304                 };
1305                 """)
1306         @Reflect
1307         void testThrows(UnboundedInteger test, boolean cond) {
1308             // simple field name
1309             if (cond) {
1310                 throw t;
1311             }
1312 
1313             // qualified field name
1314             if (cond) {
1315                 throw test.t;
1316             }
1317 
1318             // simple method name
1319             if (cond) {
1320                 throw getT();
1321             }
1322 
1323             // qualified method name
1324             if (cond) {
1325                 throw test.getT();
1326             }
1327         }
1328 
1329         @IR("""
1330                 func @"testSwitchSelector" (%0 : java.type:"ErasedAccessTest$UnboundedInteger", %1 : java.type:"ErasedAccessTest$UnboundedInteger")java.type:"void" -> {
1331                     %2 : Var<java.type:"ErasedAccessTest$UnboundedInteger"> = var %1 @"test";
1332                     %3 : Var<java.type:"java.lang.Object"> = var @"o";
1333                     %4 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
1334                     %5 : java.type:"java.lang.Integer" = cast %4 @java.type:"java.lang.Integer";
1335                     java.switch.statement %5
1336                         ()java.type:"boolean" -> {
1337                             %6 : java.type:"boolean" = constant @true;
1338                             yield %6;
1339                         }
1340                         ()java.type:"void" -> {
1341                             yield;
1342                         };
1343                     %7 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
1344                     %8 : java.type:"java.lang.Integer" = cast %7 @java.type:"java.lang.Integer";
1345                     %9 : java.type:"java.lang.Object" = java.switch.expression %8
1346                         ()java.type:"boolean" -> {
1347                             %10 : java.type:"boolean" = constant @true;
1348                             yield %10;
1349                         }
1350                         ()java.type:"java.lang.Object" -> {
1351                             %11 : java.type:"java.lang.Object" = constant @null;
1352                             yield %11;
1353                         };
1354                     var.store %3 %9;
1355                     %12 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
1356                     %13 : java.type:"java.lang.Integer" = field.load %12 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
1357                     %14 : java.type:"java.lang.Integer" = cast %13 @java.type:"java.lang.Integer";
1358                     java.switch.statement %14
1359                         ()java.type:"boolean" -> {
1360                             %15 : java.type:"boolean" = constant @true;
1361                             yield %15;
1362                         }
1363                         ()java.type:"void" -> {
1364                             yield;
1365                         };
1366                     %16 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
1367                     %17 : java.type:"java.lang.Integer" = field.load %16 @java.ref:"ErasedAccessTest$UnboundedInteger::x:java.lang.Object";
1368                     %18 : java.type:"java.lang.Integer" = cast %17 @java.type:"java.lang.Integer";
1369                     %19 : java.type:"java.lang.Object" = java.switch.expression %18
1370                         ()java.type:"boolean" -> {
1371                             %20 : java.type:"boolean" = constant @true;
1372                             yield %20;
1373                         }
1374                         ()java.type:"java.lang.Object" -> {
1375                             %21 : java.type:"java.lang.Object" = constant @null;
1376                             yield %21;
1377                         };
1378                     var.store %3 %19;
1379                     %22 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
1380                     %23 : java.type:"java.lang.Integer" = cast %22 @java.type:"java.lang.Integer";
1381                     java.switch.statement %23
1382                         ()java.type:"boolean" -> {
1383                             %24 : java.type:"boolean" = constant @true;
1384                             yield %24;
1385                         }
1386                         ()java.type:"void" -> {
1387                             yield;
1388                         };
1389                     %25 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
1390                     %26 : java.type:"java.lang.Integer" = cast %25 @java.type:"java.lang.Integer";
1391                     %27 : java.type:"java.lang.Object" = java.switch.expression %26
1392                         ()java.type:"boolean" -> {
1393                             %28 : java.type:"boolean" = constant @true;
1394                             yield %28;
1395                         }
1396                         ()java.type:"java.lang.Object" -> {
1397                             %29 : java.type:"java.lang.Object" = constant @null;
1398                             yield %29;
1399                         };
1400                     var.store %3 %27;
1401                     %30 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
1402                     %31 : java.type:"java.lang.Integer" = invoke %30 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
1403                     %32 : java.type:"java.lang.Integer" = cast %31 @java.type:"java.lang.Integer";
1404                     java.switch.statement %32
1405                         ()java.type:"boolean" -> {
1406                             %33 : java.type:"boolean" = constant @true;
1407                             yield %33;
1408                         }
1409                         ()java.type:"void" -> {
1410                             yield;
1411                         };
1412                     %34 : java.type:"ErasedAccessTest$UnboundedInteger" = var.load %2;
1413                     %35 : java.type:"java.lang.Integer" = invoke %34 @java.ref:"ErasedAccessTest$UnboundedInteger::getX():java.lang.Object";
1414                     %36 : java.type:"java.lang.Integer" = cast %35 @java.type:"java.lang.Integer";
1415                     %37 : java.type:"java.lang.Object" = java.switch.expression %36
1416                         ()java.type:"boolean" -> {
1417                             %38 : java.type:"boolean" = constant @true;
1418                             yield %38;
1419                         }
1420                         ()java.type:"java.lang.Object" -> {
1421                             %39 : java.type:"java.lang.Object" = constant @null;
1422                             yield %39;
1423                         };
1424                     var.store %3 %37;
1425                     return;
1426                 };
1427                 """)
1428         @Reflect
1429         void testSwitchSelector(UnboundedInteger test) {
1430             Object o;
1431 
1432             // simple field name
1433             switch (x) {default -> { }}
1434             o = switch (x) { default -> null; };
1435 
1436             // qualified field name
1437             switch (test.x) {default -> { }}
1438             o = switch (test.x) { default -> null; };
1439 
1440             // simple method name
1441             switch (getX()) {default -> { }}
1442             o = switch (getX()) { default -> null; };
1443 
1444             // qualified method name
1445             switch (test.getX()) {default -> { }}
1446             o = switch (test.getX()) { default -> null; };
1447         }
1448     }
1449 
1450     // the part below is just copied from the above with minor adaptations in the expected IRs
1451 
1452     static class Bounded<X extends Number> {
1453         X x;
1454 
1455         X getX() {
1456             return x;
1457         }
1458     }
1459 
1460     static class BoundedInteger extends Bounded<Integer> {
1461 
1462         @IR("""
1463                 func @"testInstanceof" (%0 : java.type:"ErasedAccessTest$BoundedInteger", %1 : java.type:"ErasedAccessTest$BoundedInteger")java.type:"void" -> {
1464                     %2 : Var<java.type:"ErasedAccessTest$BoundedInteger"> = var %1 @"test";
1465                     %3 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1466                     %4 : java.type:"boolean" = instanceof %3 @java.type:"java.lang.Integer";
1467                     %5 : Var<java.type:"boolean"> = var %4 @"f_s_s";
1468                     %6 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1469                     %7 : java.type:"java.lang.Integer" = field.load %6 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1470                     %8 : java.type:"boolean" = instanceof %7 @java.type:"java.lang.Integer";
1471                     %9 : Var<java.type:"boolean"> = var %8 @"f_q_s";
1472                     %10 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1473                     %11 : java.type:"boolean" = instanceof %10 @java.type:"java.lang.Integer";
1474                     %12 : Var<java.type:"boolean"> = var %11 @"m_s_s";
1475                     %13 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1476                     %14 : java.type:"java.lang.Integer" = invoke %13 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1477                     %15 : java.type:"boolean" = instanceof %14 @java.type:"java.lang.Integer";
1478                     %16 : Var<java.type:"boolean"> = var %15 @"m_q_s";
1479                     return;
1480                 };
1481                 """)
1482         @Reflect
1483         void testInstanceof(BoundedInteger test) {
1484             // simple field name
1485             boolean f_s_s = x instanceof Integer;
1486 
1487             // qualified field name
1488             boolean f_q_s = test.x instanceof Integer;
1489 
1490             // simple method name
1491             boolean m_s_s = getX() instanceof Integer;
1492 
1493             // qualified method name
1494             boolean m_q_s = test.getX() instanceof Integer;
1495         }
1496 
1497         @IR("""
1498                 func @"testInstanceofCond" (%0 : java.type:"ErasedAccessTest$BoundedInteger", %1 : java.type:"ErasedAccessTest$BoundedInteger", %2 : java.type:"boolean")java.type:"void" -> {
1499                     %3 : Var<java.type:"ErasedAccessTest$BoundedInteger"> = var %1 @"test";
1500                     %4 : Var<java.type:"boolean"> = var %2 @"cond";
1501                     %5 : java.type:"java.lang.Integer" = java.cexpression
1502                         ()java.type:"boolean" -> {
1503                             %6 : java.type:"boolean" = var.load %4;
1504                             yield %6;
1505                         }
1506                         ()java.type:"java.lang.Integer" -> {
1507                             %7 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1508                             %8 : java.type:"java.lang.Integer" = cast %7 @java.type:"java.lang.Integer";
1509                             yield %8;
1510                         }
1511                         ()java.type:"java.lang.Integer" -> {
1512                             %9 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1513                             %10 : java.type:"java.lang.Integer" = cast %9 @java.type:"java.lang.Integer";
1514                             yield %10;
1515                         };
1516                     %11 : java.type:"boolean" = instanceof %5 @java.type:"java.lang.Object";
1517                     %12 : Var<java.type:"boolean"> = var %11 @"f_s_o";
1518                     %13 : java.type:"java.lang.Integer" = java.cexpression
1519                         ()java.type:"boolean" -> {
1520                             %14 : java.type:"boolean" = var.load %4;
1521                             yield %14;
1522                         }
1523                         ()java.type:"java.lang.Integer" -> {
1524                             %15 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %3;
1525                             %16 : java.type:"java.lang.Integer" = field.load %15 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1526                             %17 : java.type:"java.lang.Integer" = cast %16 @java.type:"java.lang.Integer";
1527                             yield %17;
1528                         }
1529                         ()java.type:"java.lang.Integer" -> {
1530                             %18 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %3;
1531                             %19 : java.type:"java.lang.Integer" = field.load %18 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1532                             %20 : java.type:"java.lang.Integer" = cast %19 @java.type:"java.lang.Integer";
1533                             yield %20;
1534                         };
1535                     %21 : java.type:"boolean" = instanceof %13 @java.type:"java.lang.Object";
1536                     %22 : Var<java.type:"boolean"> = var %21 @"f_q_o";
1537                     %23 : java.type:"java.lang.Integer" = java.cexpression
1538                         ()java.type:"boolean" -> {
1539                             %24 : java.type:"boolean" = var.load %4;
1540                             yield %24;
1541                         }
1542                         ()java.type:"java.lang.Integer" -> {
1543                             %25 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1544                             %26 : java.type:"java.lang.Integer" = cast %25 @java.type:"java.lang.Integer";
1545                             yield %26;
1546                         }
1547                         ()java.type:"java.lang.Integer" -> {
1548                             %27 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1549                             %28 : java.type:"java.lang.Integer" = cast %27 @java.type:"java.lang.Integer";
1550                             yield %28;
1551                         };
1552                     %29 : java.type:"boolean" = instanceof %23 @java.type:"java.lang.Object";
1553                     %30 : Var<java.type:"boolean"> = var %29 @"m_s_o";
1554                     %31 : java.type:"java.lang.Integer" = java.cexpression
1555                         ()java.type:"boolean" -> {
1556                             %32 : java.type:"boolean" = var.load %4;
1557                             yield %32;
1558                         }
1559                         ()java.type:"java.lang.Integer" -> {
1560                             %33 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %3;
1561                             %34 : java.type:"java.lang.Integer" = invoke %33 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1562                             %35 : java.type:"java.lang.Integer" = cast %34 @java.type:"java.lang.Integer";
1563                             yield %35;
1564                         }
1565                         ()java.type:"java.lang.Integer" -> {
1566                             %36 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %3;
1567                             %37 : java.type:"java.lang.Integer" = invoke %36 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1568                             %38 : java.type:"java.lang.Integer" = cast %37 @java.type:"java.lang.Integer";
1569                             yield %38;
1570                         };
1571                     %39 : java.type:"boolean" = instanceof %31 @java.type:"java.lang.Object";
1572                     %40 : Var<java.type:"boolean"> = var %39 @"m_q_o";
1573                     return;
1574                 };
1575                 """)
1576         @Reflect
1577         void testInstanceofCond(BoundedInteger test, boolean cond) {
1578             // simple field name
1579             boolean f_s_o = (cond ? x : x) instanceof Object;
1580 
1581             // qualified field name
1582             boolean f_q_o = (cond ? test.x : test.x) instanceof Object;
1583 
1584             // simple method name
1585             boolean m_s_o = (cond ? getX() : getX()) instanceof Object;
1586 
1587             // qualified method name
1588             boolean m_q_o = (cond ? test.getX() : test.getX()) instanceof Object;
1589         }
1590 
1591         @IR("""
1592                 func @"testExec" (%0 : java.type:"ErasedAccessTest$BoundedInteger", %1 : java.type:"ErasedAccessTest$BoundedInteger")java.type:"void" -> {
1593                     %2 : Var<java.type:"ErasedAccessTest$BoundedInteger"> = var %1 @"test";
1594                     %3 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1595                     %4 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1596                     %5 : java.type:"java.lang.Integer" = invoke %4 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1597                     return;
1598                 };
1599                 """)
1600         @Reflect
1601         void testExec(BoundedInteger test) {
1602             // simple method name
1603             getX();
1604 
1605             // qualified method name
1606             test.getX();
1607         }
1608 
1609         @IR("""
1610                 func @"testChainedCall" (%0 : java.type:"ErasedAccessTest$BoundedInteger", %1 : java.type:"ErasedAccessTest$BoundedInteger")java.type:"void" -> {
1611                     %2 : Var<java.type:"ErasedAccessTest$BoundedInteger"> = var %1 @"test";
1612                     %3 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1613                     %4 : java.type:"java.lang.Integer" = cast %3 @java.type:"java.lang.Integer";
1614                     %5 : java.type:"int" = invoke %4 @java.ref:"java.lang.Integer::hashCode():int";
1615                     %6 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1616                     %7 : java.type:"java.lang.Integer" = field.load %6 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1617                     %8 : java.type:"java.lang.Integer" = cast %7 @java.type:"java.lang.Integer";
1618                     %9 : java.type:"int" = invoke %8 @java.ref:"java.lang.Integer::hashCode():int";
1619                     %10 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1620                     %11 : java.type:"java.lang.Integer" = cast %10 @java.type:"java.lang.Integer";
1621                     %12 : java.type:"int" = invoke %11 @java.ref:"java.lang.Integer::hashCode():int";
1622                     %13 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1623                     %14 : java.type:"java.lang.Integer" = invoke %13 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1624                     %15 : java.type:"java.lang.Integer" = cast %14 @java.type:"java.lang.Integer";
1625                     %16 : java.type:"int" = invoke %15 @java.ref:"java.lang.Integer::hashCode():int";
1626                     return;
1627                 };
1628                 """)
1629         @Reflect
1630         void testChainedCall(BoundedInteger test) {
1631             // simple field name
1632             x.hashCode();
1633 
1634             // qualified field name
1635             test.x.hashCode();
1636 
1637             // simple method name
1638             getX().hashCode();
1639 
1640             // qualified method name
1641             test.getX().hashCode();
1642         }
1643 
1644         @IR("""
1645                 func @"testChainedCallCond" (%0 : java.type:"ErasedAccessTest$BoundedInteger", %1 : java.type:"ErasedAccessTest$BoundedInteger", %2 : java.type:"boolean")java.type:"void" -> {
1646                     %3 : Var<java.type:"ErasedAccessTest$BoundedInteger"> = var %1 @"test";
1647                     %4 : Var<java.type:"boolean"> = var %2 @"cond";
1648                     %5 : java.type:"java.lang.Integer" = java.cexpression
1649                         ()java.type:"boolean" -> {
1650                             %6 : java.type:"boolean" = var.load %4;
1651                             yield %6;
1652                         }
1653                         ()java.type:"java.lang.Integer" -> {
1654                             %7 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1655                             %8 : java.type:"java.lang.Integer" = cast %7 @java.type:"java.lang.Integer";
1656                             yield %8;
1657                         }
1658                         ()java.type:"java.lang.Integer" -> {
1659                             %9 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1660                             %10 : java.type:"java.lang.Integer" = cast %9 @java.type:"java.lang.Integer";
1661                             yield %10;
1662                         };
1663                     %11 : java.type:"int" = invoke %5 @java.ref:"java.lang.Integer::hashCode():int";
1664                     %12 : java.type:"java.lang.Integer" = java.cexpression
1665                         ()java.type:"boolean" -> {
1666                             %13 : java.type:"boolean" = var.load %4;
1667                             yield %13;
1668                         }
1669                         ()java.type:"java.lang.Integer" -> {
1670                             %14 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %3;
1671                             %15 : java.type:"java.lang.Integer" = field.load %14 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1672                             %16 : java.type:"java.lang.Integer" = cast %15 @java.type:"java.lang.Integer";
1673                             yield %16;
1674                         }
1675                         ()java.type:"java.lang.Integer" -> {
1676                             %17 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %3;
1677                             %18 : java.type:"java.lang.Integer" = field.load %17 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1678                             %19 : java.type:"java.lang.Integer" = cast %18 @java.type:"java.lang.Integer";
1679                             yield %19;
1680                         };
1681                     %20 : java.type:"int" = invoke %12 @java.ref:"java.lang.Integer::hashCode():int";
1682                     %21 : java.type:"java.lang.Integer" = java.cexpression
1683                         ()java.type:"boolean" -> {
1684                             %22 : java.type:"boolean" = var.load %4;
1685                             yield %22;
1686                         }
1687                         ()java.type:"java.lang.Integer" -> {
1688                             %23 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1689                             %24 : java.type:"java.lang.Integer" = cast %23 @java.type:"java.lang.Integer";
1690                             yield %24;
1691                         }
1692                         ()java.type:"java.lang.Integer" -> {
1693                             %25 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1694                             %26 : java.type:"java.lang.Integer" = cast %25 @java.type:"java.lang.Integer";
1695                             yield %26;
1696                         };
1697                     %27 : java.type:"int" = invoke %21 @java.ref:"java.lang.Integer::hashCode():int";
1698                     %28 : java.type:"java.lang.Integer" = java.cexpression
1699                         ()java.type:"boolean" -> {
1700                             %29 : java.type:"boolean" = var.load %4;
1701                             yield %29;
1702                         }
1703                         ()java.type:"java.lang.Integer" -> {
1704                             %30 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %3;
1705                             %31 : java.type:"java.lang.Integer" = invoke %30 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1706                             %32 : java.type:"java.lang.Integer" = cast %31 @java.type:"java.lang.Integer";
1707                             yield %32;
1708                         }
1709                         ()java.type:"java.lang.Integer" -> {
1710                             %33 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %3;
1711                             %34 : java.type:"java.lang.Integer" = invoke %33 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1712                             %35 : java.type:"java.lang.Integer" = cast %34 @java.type:"java.lang.Integer";
1713                             yield %35;
1714                         };
1715                     %36 : java.type:"int" = invoke %28 @java.ref:"java.lang.Integer::hashCode():int";
1716                     return;
1717                 };
1718                 """)
1719         @Reflect
1720         void testChainedCallCond(BoundedInteger test, boolean cond) {
1721             // simple field name
1722             (cond ? x : x).hashCode();
1723 
1724             // qualified field name
1725             (cond ? test.x : test.x).hashCode();
1726 
1727             // simple method name
1728             (cond ? getX() : getX()).hashCode();
1729 
1730             // qualified method name
1731             (cond ? test.getX() : test.getX()).hashCode();
1732         }
1733 
1734         @IR("""
1735                 func @"testAssign" (%0 : java.type:"ErasedAccessTest$BoundedInteger", %1 : java.type:"ErasedAccessTest$BoundedInteger")java.type:"void" -> {
1736                     %2 : Var<java.type:"ErasedAccessTest$BoundedInteger"> = var %1 @"test";
1737                     %3 : Var<java.type:"java.lang.Object"> = var @"o";
1738                     %4 : Var<java.type:"java.lang.Number"> = var @"n";
1739                     %5 : Var<java.type:"java.lang.Integer"> = var @"i";
1740                     %6 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1741                     var.store %3 %6;
1742                     %7 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1743                     var.store %4 %7;
1744                     %8 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1745                     %9 : java.type:"java.lang.Integer" = cast %8 @java.type:"java.lang.Integer";
1746                     var.store %5 %9;
1747                     %10 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1748                     %11 : java.type:"java.lang.Integer" = field.load %10 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1749                     var.store %3 %11;
1750                     %12 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1751                     %13 : java.type:"java.lang.Integer" = field.load %12 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1752                     var.store %4 %13;
1753                     %14 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1754                     %15 : java.type:"java.lang.Integer" = field.load %14 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1755                     %16 : java.type:"java.lang.Integer" = cast %15 @java.type:"java.lang.Integer";
1756                     var.store %5 %16;
1757                     %17 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1758                     var.store %3 %17;
1759                     %18 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1760                     var.store %4 %18;
1761                     %19 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1762                     %20 : java.type:"java.lang.Integer" = cast %19 @java.type:"java.lang.Integer";
1763                     var.store %5 %20;
1764                     %21 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1765                     %22 : java.type:"java.lang.Integer" = invoke %21 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1766                     var.store %3 %22;
1767                     %23 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1768                     %24 : java.type:"java.lang.Integer" = invoke %23 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1769                     var.store %4 %24;
1770                     %25 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1771                     %26 : java.type:"java.lang.Integer" = invoke %25 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1772                     %27 : java.type:"java.lang.Integer" = cast %26 @java.type:"java.lang.Integer";
1773                     var.store %5 %27;
1774                     return;
1775                 };
1776                 """)
1777         @Reflect
1778         void testAssign(BoundedInteger test) {
1779             Object o; Number n; Integer i;
1780 
1781             // simple field name
1782             o = x;
1783             n = x;
1784             i = x;
1785 
1786             // qualified field name
1787             o = test.x;
1788             n = test.x;
1789             i = test.x;
1790 
1791             // simple method name
1792             o = getX();
1793             n = getX();
1794             i = getX();
1795 
1796             // qualified method name
1797             o = test.getX();
1798             n = test.getX();
1799             i = test.getX();
1800         }
1801 
1802         @IR("""
1803                 func @"testArrayInit" (%0 : java.type:"ErasedAccessTest$BoundedInteger", %1 : java.type:"ErasedAccessTest$BoundedInteger")java.type:"void" -> {
1804                     %2 : Var<java.type:"ErasedAccessTest$BoundedInteger"> = var %1 @"test";
1805                     %3 : Var<java.type:"java.lang.Object[]"> = var @"o";
1806                     %4 : Var<java.type:"java.lang.Number[]"> = var @"n";
1807                     %5 : Var<java.type:"java.lang.Integer[]"> = var @"i";
1808                     %6 : java.type:"int" = constant @1;
1809                     %7 : java.type:"java.lang.Object[]" = new %6 @java.ref:"java.lang.Object[]::(int)";
1810                     %8 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1811                     %9 : java.type:"int" = constant @0;
1812                     array.store %7 %9 %8;
1813                     var.store %3 %7;
1814                     %10 : java.type:"int" = constant @1;
1815                     %11 : java.type:"java.lang.Number[]" = new %10 @java.ref:"java.lang.Number[]::(int)";
1816                     %12 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1817                     %13 : java.type:"int" = constant @0;
1818                     array.store %11 %13 %12;
1819                     var.store %4 %11;
1820                     %14 : java.type:"int" = constant @1;
1821                     %15 : java.type:"java.lang.Integer[]" = new %14 @java.ref:"java.lang.Integer[]::(int)";
1822                     %16 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1823                     %17 : java.type:"java.lang.Integer" = cast %16 @java.type:"java.lang.Integer";
1824                     %18 : java.type:"int" = constant @0;
1825                     array.store %15 %18 %17;
1826                     var.store %5 %15;
1827                     %19 : java.type:"int" = constant @1;
1828                     %20 : java.type:"java.lang.Object[]" = new %19 @java.ref:"java.lang.Object[]::(int)";
1829                     %21 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1830                     %22 : java.type:"java.lang.Integer" = field.load %21 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1831                     %23 : java.type:"int" = constant @0;
1832                     array.store %20 %23 %22;
1833                     var.store %3 %20;
1834                     %24 : java.type:"int" = constant @1;
1835                     %25 : java.type:"java.lang.Number[]" = new %24 @java.ref:"java.lang.Number[]::(int)";
1836                     %26 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1837                     %27 : java.type:"java.lang.Integer" = field.load %26 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1838                     %28 : java.type:"int" = constant @0;
1839                     array.store %25 %28 %27;
1840                     var.store %4 %25;
1841                     %29 : java.type:"int" = constant @1;
1842                     %30 : java.type:"java.lang.Integer[]" = new %29 @java.ref:"java.lang.Integer[]::(int)";
1843                     %31 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1844                     %32 : java.type:"java.lang.Integer" = field.load %31 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1845                     %33 : java.type:"java.lang.Integer" = cast %32 @java.type:"java.lang.Integer";
1846                     %34 : java.type:"int" = constant @0;
1847                     array.store %30 %34 %33;
1848                     var.store %5 %30;
1849                     %35 : java.type:"int" = constant @1;
1850                     %36 : java.type:"java.lang.Object[]" = new %35 @java.ref:"java.lang.Object[]::(int)";
1851                     %37 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1852                     %38 : java.type:"int" = constant @0;
1853                     array.store %36 %38 %37;
1854                     var.store %3 %36;
1855                     %39 : java.type:"int" = constant @1;
1856                     %40 : java.type:"java.lang.Number[]" = new %39 @java.ref:"java.lang.Number[]::(int)";
1857                     %41 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1858                     %42 : java.type:"int" = constant @0;
1859                     array.store %40 %42 %41;
1860                     var.store %4 %40;
1861                     %43 : java.type:"int" = constant @1;
1862                     %44 : java.type:"java.lang.Integer[]" = new %43 @java.ref:"java.lang.Integer[]::(int)";
1863                     %45 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1864                     %46 : java.type:"java.lang.Integer" = cast %45 @java.type:"java.lang.Integer";
1865                     %47 : java.type:"int" = constant @0;
1866                     array.store %44 %47 %46;
1867                     var.store %5 %44;
1868                     %48 : java.type:"int" = constant @1;
1869                     %49 : java.type:"java.lang.Object[]" = new %48 @java.ref:"java.lang.Object[]::(int)";
1870                     %50 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1871                     %51 : java.type:"java.lang.Integer" = invoke %50 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1872                     %52 : java.type:"int" = constant @0;
1873                     array.store %49 %52 %51;
1874                     var.store %3 %49;
1875                     %53 : java.type:"int" = constant @1;
1876                     %54 : java.type:"java.lang.Number[]" = new %53 @java.ref:"java.lang.Number[]::(int)";
1877                     %55 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1878                     %56 : java.type:"java.lang.Integer" = invoke %55 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1879                     %57 : java.type:"int" = constant @0;
1880                     array.store %54 %57 %56;
1881                     var.store %4 %54;
1882                     %58 : java.type:"int" = constant @1;
1883                     %59 : java.type:"java.lang.Integer[]" = new %58 @java.ref:"java.lang.Integer[]::(int)";
1884                     %60 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1885                     %61 : java.type:"java.lang.Integer" = invoke %60 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1886                     %62 : java.type:"java.lang.Integer" = cast %61 @java.type:"java.lang.Integer";
1887                     %63 : java.type:"int" = constant @0;
1888                     array.store %59 %63 %62;
1889                     var.store %5 %59;
1890                     return;
1891                 };
1892                 """)
1893         @Reflect
1894         void testArrayInit(BoundedInteger test) {
1895             Object[] o; Number[] n; Integer[] i;
1896 
1897             // simple field name
1898             o = new Object[] { x };
1899             n = new Number[] { x };
1900             i = new Integer[] { x };
1901 
1902             // qualified field name
1903             o = new Object[] { test.x };
1904             n = new Number[] { test.x };
1905             i = new Integer[] { test.x };
1906 
1907             // simple method name
1908             o = new Object[] { getX() };
1909             n = new Number[] { getX() };
1910             i = new Integer[] { getX() };
1911 
1912             // qualified method name
1913             o = new Object[] { test.getX() };
1914             n = new Number[] { test.getX() };
1915             i = new Integer[] { test.getX() };
1916         }
1917 
1918         @IR("""
1919                 func @"testCast" (%0 : java.type:"ErasedAccessTest$BoundedInteger", %1 : java.type:"ErasedAccessTest$BoundedInteger")java.type:"void" -> {
1920                     %2 : Var<java.type:"ErasedAccessTest$BoundedInteger"> = var %1 @"test";
1921                     %3 : Var<java.type:"java.lang.Object"> = var @"o";
1922                     %4 : Var<java.type:"java.lang.Number"> = var @"n";
1923                     %5 : Var<java.type:"java.lang.Integer"> = var @"i";
1924                     %6 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1925                     var.store %3 %6;
1926                     %7 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1927                     var.store %4 %7;
1928                     %8 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1929                     %9 : java.type:"java.lang.Integer" = cast %8 @java.type:"java.lang.Integer";
1930                     var.store %5 %9;
1931                     %10 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1932                     %11 : java.type:"java.lang.Integer" = field.load %10 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1933                     var.store %3 %11;
1934                     %12 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1935                     %13 : java.type:"java.lang.Integer" = field.load %12 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1936                     var.store %4 %13;
1937                     %14 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1938                     %15 : java.type:"java.lang.Integer" = field.load %14 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1939                     %16 : java.type:"java.lang.Integer" = cast %15 @java.type:"java.lang.Integer";
1940                     var.store %5 %16;
1941                     %17 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1942                     var.store %3 %17;
1943                     %18 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1944                     var.store %4 %18;
1945                     %19 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1946                     %20 : java.type:"java.lang.Integer" = cast %19 @java.type:"java.lang.Integer";
1947                     var.store %5 %20;
1948                     %21 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1949                     %22 : java.type:"java.lang.Integer" = invoke %21 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1950                     var.store %3 %22;
1951                     %23 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1952                     %24 : java.type:"java.lang.Integer" = invoke %23 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1953                     var.store %4 %24;
1954                     %25 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1955                     %26 : java.type:"java.lang.Integer" = invoke %25 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
1956                     %27 : java.type:"java.lang.Integer" = cast %26 @java.type:"java.lang.Integer";
1957                     var.store %5 %27;
1958                     return;
1959                 };
1960                 """)
1961         @Reflect
1962         void testCast(BoundedInteger test) {
1963             Object o; Number n; Integer i;
1964 
1965             // simple field name
1966             o = (Object) x;
1967             n = (Number) x;
1968             i = (Integer) x;
1969 
1970             // qualified field name
1971             o = (Object) test.x;
1972             n = (Number) test.x;
1973             i = (Integer) test.x;
1974 
1975             // simple method name
1976             o = (Object) getX();
1977             n = (Number) getX();
1978             i = (Integer) getX();
1979 
1980             // qualified method name
1981             o = (Object) test.getX();
1982             n = (Number) test.getX();
1983             i = (Integer) test.getX();
1984         }
1985 
1986         @IR("""
1987                 func @"testIntersectionCast" (%0 : java.type:"ErasedAccessTest$BoundedInteger", %1 : java.type:"ErasedAccessTest$BoundedInteger")java.type:"void" -> {
1988                     %2 : Var<java.type:"ErasedAccessTest$BoundedInteger"> = var %1 @"test";
1989                     %3 : Var<java.type:"java.lang.Object"> = var @"o";
1990                     %4 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1991                     %5 : java.type:"java.lang.Comparable<java.lang.Integer>" = cast %4 @java.type:"java.lang.Comparable";
1992                     %6 : java.type:"java.io.Serializable" = cast %5 @java.type:"java.io.Serializable";
1993                     %7 : java.type:"java.lang.Number" = cast %6 @java.type:"java.lang.Number";
1994                     var.store %3 %7;
1995                     %8 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
1996                     %9 : java.type:"java.lang.Integer" = field.load %8 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
1997                     %10 : java.type:"java.lang.Comparable<java.lang.Integer>" = cast %9 @java.type:"java.lang.Comparable";
1998                     %11 : java.type:"java.io.Serializable" = cast %10 @java.type:"java.io.Serializable";
1999                     %12 : java.type:"java.lang.Number" = cast %11 @java.type:"java.lang.Number";
2000                     var.store %3 %12;
2001                     %13 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2002                     %14 : java.type:"java.lang.Comparable<java.lang.Integer>" = cast %13 @java.type:"java.lang.Comparable";
2003                     %15 : java.type:"java.io.Serializable" = cast %14 @java.type:"java.io.Serializable";
2004                     %16 : java.type:"java.lang.Number" = cast %15 @java.type:"java.lang.Number";
2005                     var.store %3 %16;
2006                     %17 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
2007                     %18 : java.type:"java.lang.Integer" = invoke %17 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2008                     %19 : java.type:"java.lang.Comparable<java.lang.Integer>" = cast %18 @java.type:"java.lang.Comparable";
2009                     %20 : java.type:"java.io.Serializable" = cast %19 @java.type:"java.io.Serializable";
2010                     %21 : java.type:"java.lang.Number" = cast %20 @java.type:"java.lang.Number";
2011                     var.store %3 %21;
2012                     return;
2013                 };
2014                 """)
2015         @Reflect
2016         void testIntersectionCast(BoundedInteger test) {
2017             Object o;
2018 
2019             // simple field name
2020             o = (Number & Comparable<Integer> & Serializable) x;
2021 
2022             // qualified field name
2023             o = (Number & Comparable<Integer> & Serializable) test.x;
2024 
2025             // simple method name
2026             o = (Number & Comparable<Integer> & Serializable) getX();
2027 
2028             // qualified method name
2029             o = (Number & Comparable<Integer> & Serializable) test.getX();
2030         }
2031 
2032         void o(Object o) { }
2033         void n(Number n) { }
2034         void i(Integer i) { }
2035 
2036         @IR("""
2037                 func @"testMethod" (%0 : java.type:"ErasedAccessTest$BoundedInteger", %1 : java.type:"ErasedAccessTest$BoundedInteger")java.type:"void" -> {
2038                     %2 : Var<java.type:"ErasedAccessTest$BoundedInteger"> = var %1 @"test";
2039                     %3 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2040                     invoke %0 %3 @java.ref:"ErasedAccessTest$BoundedInteger::o(java.lang.Object):void";
2041                     %4 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2042                     invoke %0 %4 @java.ref:"ErasedAccessTest$BoundedInteger::n(java.lang.Number):void";
2043                     %5 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2044                     %6 : java.type:"java.lang.Integer" = cast %5 @java.type:"java.lang.Integer";
2045                     invoke %0 %6 @java.ref:"ErasedAccessTest$BoundedInteger::i(java.lang.Integer):void";
2046                     %7 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
2047                     %8 : java.type:"java.lang.Integer" = field.load %7 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2048                     invoke %0 %8 @java.ref:"ErasedAccessTest$BoundedInteger::o(java.lang.Object):void";
2049                     %9 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
2050                     %10 : java.type:"java.lang.Integer" = field.load %9 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2051                     invoke %0 %10 @java.ref:"ErasedAccessTest$BoundedInteger::n(java.lang.Number):void";
2052                     %11 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
2053                     %12 : java.type:"java.lang.Integer" = field.load %11 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2054                     %13 : java.type:"java.lang.Integer" = cast %12 @java.type:"java.lang.Integer";
2055                     invoke %0 %13 @java.ref:"ErasedAccessTest$BoundedInteger::i(java.lang.Integer):void";
2056                     %14 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2057                     invoke %0 %14 @java.ref:"ErasedAccessTest$BoundedInteger::o(java.lang.Object):void";
2058                     %15 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2059                     invoke %0 %15 @java.ref:"ErasedAccessTest$BoundedInteger::n(java.lang.Number):void";
2060                     %16 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2061                     %17 : java.type:"java.lang.Integer" = cast %16 @java.type:"java.lang.Integer";
2062                     invoke %0 %17 @java.ref:"ErasedAccessTest$BoundedInteger::i(java.lang.Integer):void";
2063                     %18 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
2064                     %19 : java.type:"java.lang.Integer" = invoke %18 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2065                     invoke %0 %19 @java.ref:"ErasedAccessTest$BoundedInteger::o(java.lang.Object):void";
2066                     %20 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
2067                     %21 : java.type:"java.lang.Integer" = invoke %20 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2068                     invoke %0 %21 @java.ref:"ErasedAccessTest$BoundedInteger::n(java.lang.Number):void";
2069                     %22 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
2070                     %23 : java.type:"java.lang.Integer" = invoke %22 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2071                     %24 : java.type:"java.lang.Integer" = cast %23 @java.type:"java.lang.Integer";
2072                     invoke %0 %24 @java.ref:"ErasedAccessTest$BoundedInteger::i(java.lang.Integer):void";
2073                     return;
2074                 };
2075                 """)
2076         @Reflect
2077         void testMethod(BoundedInteger test) {
2078             // simple field name
2079             o(x);
2080             n(x);
2081             i(x);
2082 
2083             // qualified field name
2084             o(test.x);
2085             n(test.x);
2086             i(test.x);
2087 
2088             // simple method name
2089             o(getX());
2090             n(getX());
2091             i(getX());
2092 
2093             // qualified method name
2094             o(test.getX());
2095             n(test.getX());
2096             i(test.getX());
2097         }
2098 
2099         @IR("""
2100                 func @"testWidening" (%0 : java.type:"ErasedAccessTest$BoundedInteger", %1 : java.type:"ErasedAccessTest$BoundedInteger")java.type:"void" -> {
2101                     %2 : Var<java.type:"ErasedAccessTest$BoundedInteger"> = var %1 @"test";
2102                     %3 : Var<java.type:"long"> = var @"l";
2103                     %4 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2104                     %5 : java.type:"java.lang.Integer" = cast %4 @java.type:"java.lang.Integer";
2105                     %6 : java.type:"int" = invoke %5 @java.ref:"java.lang.Integer::intValue():int";
2106                     %7 : java.type:"long" = conv %6;
2107                     var.store %3 %7;
2108                     %8 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
2109                     %9 : java.type:"java.lang.Integer" = field.load %8 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2110                     %10 : java.type:"java.lang.Integer" = cast %9 @java.type:"java.lang.Integer";
2111                     %11 : java.type:"int" = invoke %10 @java.ref:"java.lang.Integer::intValue():int";
2112                     %12 : java.type:"long" = conv %11;
2113                     var.store %3 %12;
2114                     %13 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2115                     %14 : java.type:"java.lang.Integer" = cast %13 @java.type:"java.lang.Integer";
2116                     %15 : java.type:"int" = invoke %14 @java.ref:"java.lang.Integer::intValue():int";
2117                     %16 : java.type:"long" = conv %15;
2118                     var.store %3 %16;
2119                     %17 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
2120                     %18 : java.type:"java.lang.Integer" = invoke %17 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2121                     %19 : java.type:"java.lang.Integer" = cast %18 @java.type:"java.lang.Integer";
2122                     %20 : java.type:"int" = invoke %19 @java.ref:"java.lang.Integer::intValue():int";
2123                     %21 : java.type:"long" = conv %20;
2124                     var.store %3 %21;
2125                     return;
2126                 };
2127                 """)
2128         @Reflect
2129         void testWidening(BoundedInteger test) {
2130             long l;
2131 
2132             // simple field name
2133             l = x;
2134 
2135             // qualified field name
2136             l = test.x;
2137 
2138             // simple method name
2139             l = getX();
2140 
2141             // qualified method name
2142             l = test.getX();
2143         }
2144 
2145         @IR("""
2146                 func @"testAssert" (%0 : java.type:"ErasedAccessTest$BoundedInteger", %1 : java.type:"ErasedAccessTest$BoundedInteger")java.type:"void" -> {
2147                     %2 : Var<java.type:"ErasedAccessTest$BoundedInteger"> = var %1 @"test";
2148                     assert
2149                         ()java.type:"boolean" -> {
2150                             %3 : java.type:"boolean" = constant @false;
2151                             yield %3;
2152                         }
2153                         ()java.type:"java.lang.Integer" -> {
2154                             %4 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2155                             %5 : java.type:"java.lang.Integer" = cast %4 @java.type:"java.lang.Integer";
2156                             yield %5;
2157                         };
2158                     assert
2159                         ()java.type:"boolean" -> {
2160                             %6 : java.type:"boolean" = constant @false;
2161                             yield %6;
2162                         }
2163                         ()java.type:"java.lang.Integer" -> {
2164                             %7 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
2165                             %8 : java.type:"java.lang.Integer" = field.load %7 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2166                             %9 : java.type:"java.lang.Integer" = cast %8 @java.type:"java.lang.Integer";
2167                             yield %9;
2168                         };
2169                     assert
2170                         ()java.type:"boolean" -> {
2171                             %10 : java.type:"boolean" = constant @false;
2172                             yield %10;
2173                         }
2174                         ()java.type:"java.lang.Integer" -> {
2175                             %11 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2176                             %12 : java.type:"java.lang.Integer" = cast %11 @java.type:"java.lang.Integer";
2177                             yield %12;
2178                         };
2179                     assert
2180                         ()java.type:"boolean" -> {
2181                             %13 : java.type:"boolean" = constant @false;
2182                             yield %13;
2183                         }
2184                         ()java.type:"java.lang.Integer" -> {
2185                             %14 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
2186                             %15 : java.type:"java.lang.Integer" = invoke %14 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2187                             %16 : java.type:"java.lang.Integer" = cast %15 @java.type:"java.lang.Integer";
2188                             yield %16;
2189                         };
2190                     return;
2191                 };
2192                 """)
2193         @Reflect
2194         void testAssert(BoundedInteger test) {
2195             // simple field name
2196             assert false : x;
2197 
2198             // qualified field name
2199             assert false : test.x;
2200 
2201             // simple method name
2202             assert false : getX();
2203 
2204             // qualified method name
2205             assert false : test.getX();
2206         }
2207 
2208         @IR("""
2209                 func @"testSynchronized" (%0 : java.type:"ErasedAccessTest$BoundedInteger", %1 : java.type:"ErasedAccessTest$BoundedInteger")java.type:"void" -> {
2210                     %2 : Var<java.type:"ErasedAccessTest$BoundedInteger"> = var %1 @"test";
2211                     java.synchronized
2212                         ()java.type:"java.lang.Integer" -> {
2213                             %3 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2214                             %4 : java.type:"java.lang.Integer" = cast %3 @java.type:"java.lang.Integer";
2215                             yield %4;
2216                         }
2217                         ()java.type:"void" -> {
2218                             yield;
2219                         };
2220                     java.synchronized
2221                         ()java.type:"java.lang.Integer" -> {
2222                             %5 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
2223                             %6 : java.type:"java.lang.Integer" = field.load %5 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2224                             %7 : java.type:"java.lang.Integer" = cast %6 @java.type:"java.lang.Integer";
2225                             yield %7;
2226                         }
2227                         ()java.type:"void" -> {
2228                             yield;
2229                         };
2230                     java.synchronized
2231                         ()java.type:"java.lang.Integer" -> {
2232                             %8 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2233                             %9 : java.type:"java.lang.Integer" = cast %8 @java.type:"java.lang.Integer";
2234                             yield %9;
2235                         }
2236                         ()java.type:"void" -> {
2237                             yield;
2238                         };
2239                     java.synchronized
2240                         ()java.type:"java.lang.Integer" -> {
2241                             %10 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
2242                             %11 : java.type:"java.lang.Integer" = invoke %10 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2243                             %12 : java.type:"java.lang.Integer" = cast %11 @java.type:"java.lang.Integer";
2244                             yield %12;
2245                         }
2246                         ()java.type:"void" -> {
2247                             yield;
2248                         };
2249                     return;
2250                 };
2251                 """)
2252         @Reflect
2253         @SuppressWarnings("identity")
2254         void testSynchronized(BoundedInteger test) {
2255             // simple field name
2256             synchronized (x) { };
2257 
2258             // qualified field name
2259             synchronized (test.x) { };
2260 
2261             // simple method name
2262             synchronized (getX()) { };
2263 
2264             // qualified method name
2265             synchronized (test.getX()) { };
2266         }
2267 
2268         @IR("""
2269                 func @"testYield" (%0 : java.type:"ErasedAccessTest$BoundedInteger", %1 : java.type:"ErasedAccessTest$BoundedInteger", %2 : java.type:"int")java.type:"void" -> {
2270                     %3 : Var<java.type:"ErasedAccessTest$BoundedInteger"> = var %1 @"test";
2271                     %4 : Var<java.type:"int"> = var %2 @"s";
2272                     %5 : Var<java.type:"java.lang.Object"> = var @"o";
2273                     %6 : Var<java.type:"java.lang.Number"> = var @"n";
2274                     %7 : Var<java.type:"java.lang.Integer"> = var @"i";
2275                     %8 : java.type:"int" = var.load %4;
2276                     %9 : java.type:"java.lang.Object" = java.switch.expression %8
2277                         (%10 : java.type:"int")java.type:"boolean" -> {
2278                             %11 : java.type:"int" = constant @0;
2279                             %12 : java.type:"boolean" = eq %10 %11;
2280                             yield %12;
2281                         }
2282                         ()java.type:"java.lang.Object" -> {
2283                             %13 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2284                             %14 : java.type:"java.lang.Integer" = cast %13 @java.type:"java.lang.Integer";
2285                             yield %14;
2286                         }
2287                         ()java.type:"boolean" -> {
2288                             %15 : java.type:"boolean" = constant @true;
2289                             yield %15;
2290                         }
2291                         ()java.type:"java.lang.Object" -> {
2292                             %16 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2293                             %17 : java.type:"java.lang.Integer" = cast %16 @java.type:"java.lang.Integer";
2294                             yield %17;
2295                         };
2296                     var.store %5 %9;
2297                     %18 : java.type:"int" = var.load %4;
2298                     %19 : java.type:"java.lang.Number" = java.switch.expression %18
2299                         (%20 : java.type:"int")java.type:"boolean" -> {
2300                             %21 : java.type:"int" = constant @0;
2301                             %22 : java.type:"boolean" = eq %20 %21;
2302                             yield %22;
2303                         }
2304                         ()java.type:"java.lang.Number" -> {
2305                             %23 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2306                             %24 : java.type:"java.lang.Integer" = cast %23 @java.type:"java.lang.Integer";
2307                             yield %24;
2308                         }
2309                         ()java.type:"boolean" -> {
2310                             %25 : java.type:"boolean" = constant @true;
2311                             yield %25;
2312                         }
2313                         ()java.type:"java.lang.Number" -> {
2314                             %26 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2315                             %27 : java.type:"java.lang.Integer" = cast %26 @java.type:"java.lang.Integer";
2316                             yield %27;
2317                         };
2318                     var.store %6 %19;
2319                     %28 : java.type:"int" = var.load %4;
2320                     %29 : java.type:"java.lang.Integer" = java.switch.expression %28
2321                         (%30 : java.type:"int")java.type:"boolean" -> {
2322                             %31 : java.type:"int" = constant @0;
2323                             %32 : java.type:"boolean" = eq %30 %31;
2324                             yield %32;
2325                         }
2326                         ()java.type:"java.lang.Integer" -> {
2327                             %33 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2328                             %34 : java.type:"java.lang.Integer" = cast %33 @java.type:"java.lang.Integer";
2329                             yield %34;
2330                         }
2331                         ()java.type:"boolean" -> {
2332                             %35 : java.type:"boolean" = constant @true;
2333                             yield %35;
2334                         }
2335                         ()java.type:"java.lang.Integer" -> {
2336                             %36 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2337                             %37 : java.type:"java.lang.Integer" = cast %36 @java.type:"java.lang.Integer";
2338                             yield %37;
2339                         };
2340                     var.store %7 %29;
2341                     %38 : java.type:"int" = var.load %4;
2342                     %39 : java.type:"java.lang.Object" = java.switch.expression %38
2343                         (%40 : java.type:"int")java.type:"boolean" -> {
2344                             %41 : java.type:"int" = constant @0;
2345                             %42 : java.type:"boolean" = eq %40 %41;
2346                             yield %42;
2347                         }
2348                         ()java.type:"java.lang.Object" -> {
2349                             %43 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %3;
2350                             %44 : java.type:"java.lang.Integer" = field.load %43 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2351                             %45 : java.type:"java.lang.Integer" = cast %44 @java.type:"java.lang.Integer";
2352                             yield %45;
2353                         }
2354                         ()java.type:"boolean" -> {
2355                             %46 : java.type:"boolean" = constant @true;
2356                             yield %46;
2357                         }
2358                         ()java.type:"java.lang.Object" -> {
2359                             %47 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %3;
2360                             %48 : java.type:"java.lang.Integer" = field.load %47 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2361                             %49 : java.type:"java.lang.Integer" = cast %48 @java.type:"java.lang.Integer";
2362                             yield %49;
2363                         };
2364                     var.store %5 %39;
2365                     %50 : java.type:"int" = var.load %4;
2366                     %51 : java.type:"java.lang.Number" = java.switch.expression %50
2367                         (%52 : java.type:"int")java.type:"boolean" -> {
2368                             %53 : java.type:"int" = constant @0;
2369                             %54 : java.type:"boolean" = eq %52 %53;
2370                             yield %54;
2371                         }
2372                         ()java.type:"java.lang.Number" -> {
2373                             %55 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %3;
2374                             %56 : java.type:"java.lang.Integer" = field.load %55 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2375                             %57 : java.type:"java.lang.Integer" = cast %56 @java.type:"java.lang.Integer";
2376                             yield %57;
2377                         }
2378                         ()java.type:"boolean" -> {
2379                             %58 : java.type:"boolean" = constant @true;
2380                             yield %58;
2381                         }
2382                         ()java.type:"java.lang.Number" -> {
2383                             %59 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %3;
2384                             %60 : java.type:"java.lang.Integer" = field.load %59 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2385                             %61 : java.type:"java.lang.Integer" = cast %60 @java.type:"java.lang.Integer";
2386                             yield %61;
2387                         };
2388                     var.store %6 %51;
2389                     %62 : java.type:"int" = var.load %4;
2390                     %63 : java.type:"java.lang.Integer" = java.switch.expression %62
2391                         (%64 : java.type:"int")java.type:"boolean" -> {
2392                             %65 : java.type:"int" = constant @0;
2393                             %66 : java.type:"boolean" = eq %64 %65;
2394                             yield %66;
2395                         }
2396                         ()java.type:"java.lang.Integer" -> {
2397                             %67 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %3;
2398                             %68 : java.type:"java.lang.Integer" = field.load %67 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2399                             %69 : java.type:"java.lang.Integer" = cast %68 @java.type:"java.lang.Integer";
2400                             yield %69;
2401                         }
2402                         ()java.type:"boolean" -> {
2403                             %70 : java.type:"boolean" = constant @true;
2404                             yield %70;
2405                         }
2406                         ()java.type:"java.lang.Integer" -> {
2407                             %71 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %3;
2408                             %72 : java.type:"java.lang.Integer" = field.load %71 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2409                             %73 : java.type:"java.lang.Integer" = cast %72 @java.type:"java.lang.Integer";
2410                             yield %73;
2411                         };
2412                     var.store %7 %63;
2413                     %74 : java.type:"int" = var.load %4;
2414                     %75 : java.type:"java.lang.Object" = java.switch.expression %74
2415                         (%76 : java.type:"int")java.type:"boolean" -> {
2416                             %77 : java.type:"int" = constant @0;
2417                             %78 : java.type:"boolean" = eq %76 %77;
2418                             yield %78;
2419                         }
2420                         ()java.type:"java.lang.Object" -> {
2421                             %79 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2422                             %80 : java.type:"java.lang.Integer" = cast %79 @java.type:"java.lang.Integer";
2423                             yield %80;
2424                         }
2425                         ()java.type:"boolean" -> {
2426                             %81 : java.type:"boolean" = constant @true;
2427                             yield %81;
2428                         }
2429                         ()java.type:"java.lang.Object" -> {
2430                             %82 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2431                             %83 : java.type:"java.lang.Integer" = cast %82 @java.type:"java.lang.Integer";
2432                             yield %83;
2433                         };
2434                     var.store %5 %75;
2435                     %84 : java.type:"int" = var.load %4;
2436                     %85 : java.type:"java.lang.Number" = java.switch.expression %84
2437                         (%86 : java.type:"int")java.type:"boolean" -> {
2438                             %87 : java.type:"int" = constant @0;
2439                             %88 : java.type:"boolean" = eq %86 %87;
2440                             yield %88;
2441                         }
2442                         ()java.type:"java.lang.Number" -> {
2443                             %89 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2444                             %90 : java.type:"java.lang.Integer" = cast %89 @java.type:"java.lang.Integer";
2445                             yield %90;
2446                         }
2447                         ()java.type:"boolean" -> {
2448                             %91 : java.type:"boolean" = constant @true;
2449                             yield %91;
2450                         }
2451                         ()java.type:"java.lang.Number" -> {
2452                             %92 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2453                             %93 : java.type:"java.lang.Integer" = cast %92 @java.type:"java.lang.Integer";
2454                             yield %93;
2455                         };
2456                     var.store %6 %85;
2457                     %94 : java.type:"int" = var.load %4;
2458                     %95 : java.type:"java.lang.Integer" = java.switch.expression %94
2459                         (%96 : java.type:"int")java.type:"boolean" -> {
2460                             %97 : java.type:"int" = constant @0;
2461                             %98 : java.type:"boolean" = eq %96 %97;
2462                             yield %98;
2463                         }
2464                         ()java.type:"java.lang.Integer" -> {
2465                             %99 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2466                             %100 : java.type:"java.lang.Integer" = cast %99 @java.type:"java.lang.Integer";
2467                             yield %100;
2468                         }
2469                         ()java.type:"boolean" -> {
2470                             %101 : java.type:"boolean" = constant @true;
2471                             yield %101;
2472                         }
2473                         ()java.type:"java.lang.Integer" -> {
2474                             %102 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2475                             %103 : java.type:"java.lang.Integer" = cast %102 @java.type:"java.lang.Integer";
2476                             yield %103;
2477                         };
2478                     var.store %7 %95;
2479                     %104 : java.type:"int" = var.load %4;
2480                     %105 : java.type:"java.lang.Object" = java.switch.expression %104
2481                         (%106 : java.type:"int")java.type:"boolean" -> {
2482                             %107 : java.type:"int" = constant @0;
2483                             %108 : java.type:"boolean" = eq %106 %107;
2484                             yield %108;
2485                         }
2486                         ()java.type:"java.lang.Object" -> {
2487                             %109 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %3;
2488                             %110 : java.type:"java.lang.Integer" = invoke %109 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2489                             %111 : java.type:"java.lang.Integer" = cast %110 @java.type:"java.lang.Integer";
2490                             yield %111;
2491                         }
2492                         ()java.type:"boolean" -> {
2493                             %112 : java.type:"boolean" = constant @true;
2494                             yield %112;
2495                         }
2496                         ()java.type:"java.lang.Object" -> {
2497                             %113 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %3;
2498                             %114 : java.type:"java.lang.Integer" = invoke %113 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2499                             %115 : java.type:"java.lang.Integer" = cast %114 @java.type:"java.lang.Integer";
2500                             yield %115;
2501                         };
2502                     var.store %5 %105;
2503                     %116 : java.type:"int" = var.load %4;
2504                     %117 : java.type:"java.lang.Number" = java.switch.expression %116
2505                         (%118 : java.type:"int")java.type:"boolean" -> {
2506                             %119 : java.type:"int" = constant @0;
2507                             %120 : java.type:"boolean" = eq %118 %119;
2508                             yield %120;
2509                         }
2510                         ()java.type:"java.lang.Number" -> {
2511                             %121 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %3;
2512                             %122 : java.type:"java.lang.Integer" = invoke %121 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2513                             %123 : java.type:"java.lang.Integer" = cast %122 @java.type:"java.lang.Integer";
2514                             yield %123;
2515                         }
2516                         ()java.type:"boolean" -> {
2517                             %124 : java.type:"boolean" = constant @true;
2518                             yield %124;
2519                         }
2520                         ()java.type:"java.lang.Number" -> {
2521                             %125 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %3;
2522                             %126 : java.type:"java.lang.Integer" = invoke %125 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2523                             %127 : java.type:"java.lang.Integer" = cast %126 @java.type:"java.lang.Integer";
2524                             yield %127;
2525                         };
2526                     var.store %6 %117;
2527                     %128 : java.type:"int" = var.load %4;
2528                     %129 : java.type:"java.lang.Integer" = java.switch.expression %128
2529                         (%130 : java.type:"int")java.type:"boolean" -> {
2530                             %131 : java.type:"int" = constant @0;
2531                             %132 : java.type:"boolean" = eq %130 %131;
2532                             yield %132;
2533                         }
2534                         ()java.type:"java.lang.Integer" -> {
2535                             %133 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %3;
2536                             %134 : java.type:"java.lang.Integer" = invoke %133 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2537                             %135 : java.type:"java.lang.Integer" = cast %134 @java.type:"java.lang.Integer";
2538                             yield %135;
2539                         }
2540                         ()java.type:"boolean" -> {
2541                             %136 : java.type:"boolean" = constant @true;
2542                             yield %136;
2543                         }
2544                         ()java.type:"java.lang.Integer" -> {
2545                             %137 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %3;
2546                             %138 : java.type:"java.lang.Integer" = invoke %137 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2547                             %139 : java.type:"java.lang.Integer" = cast %138 @java.type:"java.lang.Integer";
2548                             yield %139;
2549                         };
2550                     var.store %7 %129;
2551                     return;
2552                 };
2553                 """)
2554         @Reflect
2555         void testYield(BoundedInteger test, int s) {
2556             Object o; Number n; Integer i;
2557 
2558             // simple field name
2559             o = switch (s) {
2560                 case 0 -> x;
2561                 default -> x;
2562             };
2563 
2564             n = switch (s) {
2565                 case 0 -> x;
2566                 default -> x;
2567             };
2568 
2569             i = switch (s) {
2570                 case 0 -> x;
2571                 default -> x;
2572             };
2573 
2574             // qualified field name
2575             o = switch (s) {
2576                 case 0 -> test.x;
2577                 default -> test.x;
2578             };
2579 
2580             n = switch (s) {
2581                 case 0 -> test.x;
2582                 default -> test.x;
2583             };
2584 
2585             i = switch (s) {
2586                 case 0 -> test.x;
2587                 default -> test.x;
2588             };
2589 
2590             // simple method name
2591             o = switch (s) {
2592                 case 0 -> getX();
2593                 default -> getX();
2594             };
2595 
2596             n = switch (s) {
2597                 case 0 -> getX();
2598                 default -> getX();
2599             };
2600 
2601             i = switch (s) {
2602                 case 0 -> getX();
2603                 default -> getX();
2604             };
2605 
2606             // qualified method name
2607             o = switch (s) {
2608                 case 0 -> test.getX();
2609                 default -> test.getX();
2610             };
2611 
2612             n = switch (s) {
2613                 case 0 -> test.getX();
2614                 default -> test.getX();
2615             };
2616 
2617             i = switch (s) {
2618                 case 0 -> test.getX();
2619                 default -> test.getX();
2620             };
2621         }
2622 
2623         @IR("""
2624                 func @"testSwitchSelector" (%0 : java.type:"ErasedAccessTest$BoundedInteger", %1 : java.type:"ErasedAccessTest$BoundedInteger")java.type:"void" -> {
2625                     %2 : Var<java.type:"ErasedAccessTest$BoundedInteger"> = var %1 @"test";
2626                     %3 : Var<java.type:"java.lang.Object"> = var @"o";
2627                     %4 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2628                     %5 : java.type:"java.lang.Integer" = cast %4 @java.type:"java.lang.Integer";
2629                     java.switch.statement %5
2630                         ()java.type:"boolean" -> {
2631                             %6 : java.type:"boolean" = constant @true;
2632                             yield %6;
2633                         }
2634                         ()java.type:"void" -> {
2635                             yield;
2636                         };
2637                     %7 : java.type:"java.lang.Integer" = field.load %0 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2638                     %8 : java.type:"java.lang.Integer" = cast %7 @java.type:"java.lang.Integer";
2639                     %9 : java.type:"java.lang.Object" = java.switch.expression %8
2640                         ()java.type:"boolean" -> {
2641                             %10 : java.type:"boolean" = constant @true;
2642                             yield %10;
2643                         }
2644                         ()java.type:"java.lang.Object" -> {
2645                             %11 : java.type:"java.lang.Object" = constant @null;
2646                             yield %11;
2647                         };
2648                     var.store %3 %9;
2649                     %12 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
2650                     %13 : java.type:"java.lang.Integer" = field.load %12 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2651                     %14 : java.type:"java.lang.Integer" = cast %13 @java.type:"java.lang.Integer";
2652                     java.switch.statement %14
2653                         ()java.type:"boolean" -> {
2654                             %15 : java.type:"boolean" = constant @true;
2655                             yield %15;
2656                         }
2657                         ()java.type:"void" -> {
2658                             yield;
2659                         };
2660                     %16 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
2661                     %17 : java.type:"java.lang.Integer" = field.load %16 @java.ref:"ErasedAccessTest$BoundedInteger::x:java.lang.Number";
2662                     %18 : java.type:"java.lang.Integer" = cast %17 @java.type:"java.lang.Integer";
2663                     %19 : java.type:"java.lang.Object" = java.switch.expression %18
2664                         ()java.type:"boolean" -> {
2665                             %20 : java.type:"boolean" = constant @true;
2666                             yield %20;
2667                         }
2668                         ()java.type:"java.lang.Object" -> {
2669                             %21 : java.type:"java.lang.Object" = constant @null;
2670                             yield %21;
2671                         };
2672                     var.store %3 %19;
2673                     %22 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2674                     %23 : java.type:"java.lang.Integer" = cast %22 @java.type:"java.lang.Integer";
2675                     java.switch.statement %23
2676                         ()java.type:"boolean" -> {
2677                             %24 : java.type:"boolean" = constant @true;
2678                             yield %24;
2679                         }
2680                         ()java.type:"void" -> {
2681                             yield;
2682                         };
2683                     %25 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2684                     %26 : java.type:"java.lang.Integer" = cast %25 @java.type:"java.lang.Integer";
2685                     %27 : java.type:"java.lang.Object" = java.switch.expression %26
2686                         ()java.type:"boolean" -> {
2687                             %28 : java.type:"boolean" = constant @true;
2688                             yield %28;
2689                         }
2690                         ()java.type:"java.lang.Object" -> {
2691                             %29 : java.type:"java.lang.Object" = constant @null;
2692                             yield %29;
2693                         };
2694                     var.store %3 %27;
2695                     %30 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
2696                     %31 : java.type:"java.lang.Integer" = invoke %30 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2697                     %32 : java.type:"java.lang.Integer" = cast %31 @java.type:"java.lang.Integer";
2698                     java.switch.statement %32
2699                         ()java.type:"boolean" -> {
2700                             %33 : java.type:"boolean" = constant @true;
2701                             yield %33;
2702                         }
2703                         ()java.type:"void" -> {
2704                             yield;
2705                         };
2706                     %34 : java.type:"ErasedAccessTest$BoundedInteger" = var.load %2;
2707                     %35 : java.type:"java.lang.Integer" = invoke %34 @java.ref:"ErasedAccessTest$BoundedInteger::getX():java.lang.Number";
2708                     %36 : java.type:"java.lang.Integer" = cast %35 @java.type:"java.lang.Integer";
2709                     %37 : java.type:"java.lang.Object" = java.switch.expression %36
2710                         ()java.type:"boolean" -> {
2711                             %38 : java.type:"boolean" = constant @true;
2712                             yield %38;
2713                         }
2714                         ()java.type:"java.lang.Object" -> {
2715                             %39 : java.type:"java.lang.Object" = constant @null;
2716                             yield %39;
2717                         };
2718                     var.store %3 %37;
2719                     return;
2720                 };
2721                 """)
2722         @Reflect
2723         void testSwitchSelector(BoundedInteger test) {
2724             Object o;
2725 
2726             // simple field name
2727             switch (x) {default -> { }}
2728             o = switch (x) { default -> null; };
2729 
2730             // qualified field name
2731             switch (test.x) {default -> { }}
2732             o = switch (test.x) { default -> null; };
2733 
2734             // simple method name
2735             switch (getX()) {default -> { }}
2736             o = switch (getX()) { default -> null; };
2737 
2738             // qualified method name
2739             switch (test.getX()) {default -> { }}
2740             o = switch (test.getX()) { default -> null; };
2741         }
2742     }
2743 
2744 
2745     static final String TEST_CLASSES_DIR = System.getProperty("test.classes", ".");
2746     static final Class<?>[] TEST_CLASSES = new Class<?>[] { UnboundedInteger.class, BoundedInteger.class };
2747 
2748     public static void main(String[] args) throws ReflectiveOperationException, IOException {
2749         for (Class<?> testClass : TEST_CLASSES) {
2750             ClassModel mod = ClassFile.of().parse(Path.of(TEST_CLASSES_DIR, testClass.getName() + ".class"));
2751             for (Method m : testClass.getDeclaredMethods()) {
2752                 if (m.isAnnotationPresent(Reflect.class)) {
2753                     FuncOp model = Op.ofMethod(m).get();
2754                     System.out.println(model.toText());
2755                     CodeModel bytecode = mod.methods().stream()
2756                             .filter(mm -> mm.methodName().stringValue().equals(m.getName()))
2757                             .findAny()
2758                             .flatMap(MethodModel::code)
2759                             .orElseThrow(() -> new AssertionError("Code model not found for method " + m.getName()));
2760                     List<ClassDesc> modelCasts = modelCasts(model);
2761                     List<ClassDesc> bytecodeCasts = bytecodeCasts(bytecode);
2762                     if (!modelCasts.equals(bytecodeCasts)) {
2763                         throw new AssertionError("Casts do not match for method " + m.getName() +
2764                                 "\nbytecode casts = " + bytecodeCasts +
2765                                 "\nmodel casts = " + modelCasts);
2766                     }
2767                 }
2768             }
2769         }
2770     }
2771 
2772     static List<ClassDesc> bytecodeCasts(CodeModel m) {
2773         return m.elementStream()
2774                 .filter(i -> i instanceof TypeCheckInstruction tci && tci.opcode() == Opcode.CHECKCAST)
2775                 .map(TypeCheckInstruction.class::cast)
2776                 .map(i -> i.type().asSymbol())
2777                 .toList();
2778     }
2779 
2780     static List<ClassDesc> modelCasts(FuncOp model) {
2781         return model.elements()
2782                 .filter(JavaOp.CastOp.class::isInstance)
2783                 .map(JavaOp.CastOp.class::cast)
2784                 .map(c -> ((JavaType) c.targetType()).toNominalDescriptor())
2785                 .toList();
2786     }
2787 }