1 /* 2 * Copyright (c) 1999, 2022, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.javac.comp; 27 28 29 import com.sun.tools.javac.code.*; 30 import com.sun.tools.javac.code.Attribute.TypeCompound; 31 import com.sun.tools.javac.code.Source.Feature; 32 import com.sun.tools.javac.code.Symbol.*; 33 import com.sun.tools.javac.tree.*; 34 import com.sun.tools.javac.tree.JCTree.*; 35 import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind; 36 import com.sun.tools.javac.util.*; 37 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 38 import com.sun.tools.javac.util.List; 39 40 import static com.sun.tools.javac.code.Flags.*; 41 import static com.sun.tools.javac.code.Kinds.Kind.*; 42 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; 43 import static com.sun.tools.javac.code.TypeTag.CLASS; 44 import static com.sun.tools.javac.code.TypeTag.TYPEVAR; 45 import static com.sun.tools.javac.code.TypeTag.VOID; 46 import static com.sun.tools.javac.comp.CompileStates.CompileState; 47 import com.sun.tools.javac.tree.JCTree.JCBreak; 48 49 /** This pass translates Generic Java to conventional Java. 50 * 51 * <p><b>This is NOT part of any supported API. 52 * If you write code that depends on this, you do so at your own risk. 53 * This code and its internal interfaces are subject to change or 54 * deletion without notice.</b> 55 */ 56 public class TransTypes extends TreeTranslator { 57 /** The context key for the TransTypes phase. */ 58 protected static final Context.Key<TransTypes> transTypesKey = new Context.Key<>(); 59 60 /** Get the instance for this context. */ 61 public static TransTypes instance(Context context) { 62 TransTypes instance = context.get(transTypesKey); 63 if (instance == null) 64 instance = new TransTypes(context); 65 return instance; 66 } 67 68 private Names names; 69 private Log log; 70 private Symtab syms; 71 private TreeMaker make; 72 private Enter enter; 73 private Types types; 74 private Annotate annotate; 75 private Attr attr; 76 private final Resolve resolve; 77 private final CompileStates compileStates; 78 79 @SuppressWarnings("this-escape") 80 protected TransTypes(Context context) { 81 context.put(transTypesKey, this); 82 compileStates = CompileStates.instance(context); 83 names = Names.instance(context); 84 log = Log.instance(context); 85 syms = Symtab.instance(context); 86 enter = Enter.instance(context); 87 types = Types.instance(context); 88 make = TreeMaker.instance(context); 89 resolve = Resolve.instance(context); 90 annotate = Annotate.instance(context); 91 attr = Attr.instance(context); 92 } 93 94 /** Construct an attributed tree for a cast of expression to target type, 95 * unless it already has precisely that type. 96 * @param tree The expression tree. 97 * @param target The target type. 98 */ 99 JCExpression cast(JCExpression tree, Type target) { 100 int oldpos = make.pos; 101 make.at(tree.pos); 102 if (!types.isSameType(tree.type, target)) { 103 if (!resolve.isAccessible(env, target.tsym)) 104 resolve.logAccessErrorInternal(env, tree, target); 105 tree = make.TypeCast(make.Type(target), tree).setType(target); 106 } 107 make.pos = oldpos; 108 return tree; 109 } 110 111 /** Construct an attributed tree to coerce an expression to some erased 112 * target type, unless the expression is already assignable to that type. 113 * If target type is a constant type, use its base type instead. 114 * @param tree The expression tree. 115 * @param target The target type. 116 */ 117 public JCExpression coerce(Env<AttrContext> env, JCExpression tree, Type target) { 118 Env<AttrContext> prevEnv = this.env; 119 try { 120 this.env = env; 121 return coerce(tree, target); 122 } 123 finally { 124 this.env = prevEnv; 125 } 126 } 127 JCExpression coerce(JCExpression tree, Type target) { 128 Type btarget = target.baseType(); 129 if (tree.type.isPrimitive() == target.isPrimitive()) { 130 return types.isAssignable(tree.type, btarget, types.noWarnings) 131 ? tree 132 : cast(tree, btarget); 133 } 134 return tree; 135 } 136 137 /** Given an erased reference type, assume this type as the tree's type. 138 * Then, coerce to some given target type unless target type is null. 139 * This operation is used in situations like the following: 140 * 141 * <pre>{@code 142 * class Cell<A> { A value; } 143 * ... 144 * Cell<Integer> cell; 145 * Integer x = cell.value; 146 * }</pre> 147 * 148 * Since the erasure of Cell.value is Object, but the type 149 * of cell.value in the assignment is Integer, we need to 150 * adjust the original type of cell.value to Object, and insert 151 * a cast to Integer. That is, the last assignment becomes: 152 * 153 * <pre>{@code 154 * Integer x = (Integer)cell.value; 155 * }</pre> 156 * 157 * @param tree The expression tree whose type might need adjustment. 158 * @param erasedType The expression's type after erasure. 159 * @param target The target type, which is usually the erasure of the 160 * expression's original type. 161 */ 162 JCExpression retype(JCExpression tree, Type erasedType, Type target) { 163 // System.err.println("retype " + tree + " to " + erasedType);//DEBUG 164 if (!erasedType.isPrimitive()) { 165 if (target != null && target.isPrimitive()) { 166 target = erasure(tree.type); 167 } 168 tree.type = erasedType; 169 if (target != null) { 170 return coerce(tree, target); 171 } 172 } 173 return tree; 174 } 175 176 /** Translate method argument list, casting each argument 177 * to its corresponding type in a list of target types. 178 * @param _args The method argument list. 179 * @param parameters The list of target types. 180 * @param varargsElement The erasure of the varargs element type, 181 * or null if translating a non-varargs invocation 182 */ 183 <T extends JCTree> List<T> translateArgs(List<T> _args, 184 List<Type> parameters, 185 Type varargsElement) { 186 if (parameters.isEmpty()) return _args; 187 List<T> args = _args; 188 while (parameters.tail.nonEmpty()) { 189 args.head = translate(args.head, parameters.head); 190 args = args.tail; 191 parameters = parameters.tail; 192 } 193 Type parameter = parameters.head; 194 Assert.check(varargsElement != null || args.length() == 1); 195 if (varargsElement != null) { 196 while (args.nonEmpty()) { 197 args.head = translate(args.head, varargsElement); 198 args = args.tail; 199 } 200 } else { 201 args.head = translate(args.head, parameter); 202 } 203 return _args; 204 } 205 206 public <T extends JCTree> List<T> translateArgs(List<T> _args, 207 List<Type> parameters, 208 Type varargsElement, 209 Env<AttrContext> localEnv) { 210 Env<AttrContext> prevEnv = env; 211 try { 212 env = localEnv; 213 return translateArgs(_args, parameters, varargsElement); 214 } 215 finally { 216 env = prevEnv; 217 } 218 } 219 220 /** Add a bridge definition and enter corresponding method symbol in 221 * local scope of origin. 222 * 223 * @param pos The source code position to be used for the definition. 224 * @param meth The method for which a bridge needs to be added 225 * @param impl That method's implementation (possibly the method itself) 226 * @param origin The class to which the bridge will be added 227 * @param bridges The list buffer to which the bridge will be added 228 */ 229 void addBridge(DiagnosticPosition pos, 230 MethodSymbol meth, 231 MethodSymbol impl, 232 ClassSymbol origin, 233 ListBuffer<JCTree> bridges) { 234 make.at(pos); 235 Type implTypeErasure = erasure(impl.type); 236 237 // Create a bridge method symbol and a bridge definition without a body. 238 Type bridgeType = meth.erasure(types); 239 long flags = impl.flags() & AccessFlags | SYNTHETIC | BRIDGE | 240 (origin.isInterface() ? DEFAULT : 0); 241 MethodSymbol bridge = new MethodSymbol(flags, 242 meth.name, 243 bridgeType, 244 origin); 245 /* once JDK-6996415 is solved it should be checked if this approach can 246 * be applied to method addOverrideBridgesIfNeeded 247 */ 248 bridge.params = createBridgeParams(impl, bridge, bridgeType); 249 bridge.setAttributes(impl); 250 251 JCMethodDecl md = make.MethodDef(bridge, null); 252 253 // The bridge calls this.impl(..), if we have an implementation 254 // in the current class, super.impl(...) otherwise. 255 JCExpression receiver = (impl.owner == origin) 256 ? make.This(origin.erasure(types)) 257 : make.Super(types.supertype(origin.type).tsym.erasure(types), origin); 258 259 // The type returned from the original method. 260 Type calltype = implTypeErasure.getReturnType(); 261 262 // Construct a call of this.impl(params), or super.impl(params), 263 // casting params and possibly results as needed. 264 JCExpression call = 265 make.Apply( 266 null, 267 make.Select(receiver, impl).setType(calltype), 268 translateArgs(make.Idents(md.params), implTypeErasure.getParameterTypes(), null)) 269 .setType(calltype); 270 JCStatement stat = (implTypeErasure.getReturnType().hasTag(VOID)) 271 ? make.Exec(call) 272 : make.Return(coerce(call, bridgeType.getReturnType())); 273 md.body = make.Block(0, List.of(stat)); 274 275 // Add bridge to `bridges' buffer 276 bridges.append(md); 277 278 // Add bridge to scope of enclosing class and keep track of the bridge span. 279 origin.members().enter(bridge); 280 } 281 282 private List<VarSymbol> createBridgeParams(MethodSymbol impl, MethodSymbol bridge, 283 Type bridgeType) { 284 List<VarSymbol> bridgeParams = null; 285 if (impl.params != null) { 286 bridgeParams = List.nil(); 287 List<VarSymbol> implParams = impl.params; 288 Type.MethodType mType = (Type.MethodType)bridgeType; 289 List<Type> argTypes = mType.argtypes; 290 while (implParams.nonEmpty() && argTypes.nonEmpty()) { 291 VarSymbol param = new VarSymbol(implParams.head.flags() | SYNTHETIC | PARAMETER, 292 implParams.head.name, argTypes.head, bridge); 293 param.setAttributes(implParams.head); 294 bridgeParams = bridgeParams.append(param); 295 implParams = implParams.tail; 296 argTypes = argTypes.tail; 297 } 298 } 299 return bridgeParams; 300 } 301 302 /** Add bridge if given symbol is a non-private, non-static member 303 * of the given class, which is either defined in the class or non-final 304 * inherited, and one of the two following conditions holds: 305 * 1. The method's type changes in the given class, as compared to the 306 * class where the symbol was defined, (in this case 307 * we have extended a parameterized class with non-trivial parameters). 308 * 2. The method has an implementation with a different erased return type. 309 * (in this case we have used co-variant returns). 310 * If a bridge already exists in some other class, no new bridge is added. 311 * Instead, it is checked that the bridge symbol overrides the method symbol. 312 * (Spec ???). 313 * todo: what about bridges for privates??? 314 * 315 * @param pos The source code position to be used for the definition. 316 * @param sym The symbol for which a bridge might have to be added. 317 * @param origin The class in which the bridge would go. 318 * @param bridges The list buffer to which the bridge would be added. 319 */ 320 void addBridgeIfNeeded(DiagnosticPosition pos, 321 Symbol sym, 322 ClassSymbol origin, 323 ListBuffer<JCTree> bridges) { 324 if (sym.kind == MTH && 325 !names.isInitOrVNew(sym.name) && 326 (sym.flags() & (PRIVATE | STATIC)) == 0 && 327 (sym.flags() & SYNTHETIC) != SYNTHETIC && 328 sym.isMemberOf(origin, types)) { 329 MethodSymbol meth = (MethodSymbol)sym; 330 MethodSymbol bridge = meth.binaryImplementation(origin, types); 331 MethodSymbol impl = meth.implementation(origin, types, true); 332 if (bridge == null || 333 bridge == meth || 334 (impl != null && !bridge.owner.isSubClass(impl.owner, types))) { 335 // No bridge was added yet. 336 if (impl != null && bridge != impl && isBridgeNeeded(meth, impl, origin.type)) { 337 addBridge(pos, meth, impl, origin, bridges); 338 } else if (impl == meth 339 && impl.owner != origin 340 && (impl.flags() & FINAL) == 0 341 && (meth.flags() & (ABSTRACT|PUBLIC)) == PUBLIC 342 && (origin.flags() & PUBLIC) > (impl.owner.flags() & PUBLIC)) { 343 // this is to work around a horrible but permanent 344 // reflection design error. 345 addBridge(pos, meth, impl, origin, bridges); 346 } 347 } 348 } 349 } 350 // where 351 352 /** 353 * @param method The symbol for which a bridge might have to be added 354 * @param impl The implementation of method 355 * @param dest The type in which the bridge would go 356 */ 357 private boolean isBridgeNeeded(MethodSymbol method, 358 MethodSymbol impl, 359 Type dest) { 360 if (impl != method) { 361 // If either method or impl have different erasures as 362 // members of dest, a bridge is needed. 363 Type method_erasure = method.erasure(types); 364 if (!isSameMemberWhenErased(dest, method, method_erasure)) 365 return true; 366 Type impl_erasure = impl.erasure(types); 367 if (!isSameMemberWhenErased(dest, impl, impl_erasure)) 368 return true; 369 370 /* Bottom line: A bridge is needed if the erasure of the implementation 371 is different from that of the method that it overrides. 372 */ 373 return !types.isSameType(impl_erasure, method_erasure); 374 } else { 375 // method and impl are the same... 376 if ((method.flags() & ABSTRACT) != 0) { 377 // ...and abstract so a bridge is not needed. 378 // Concrete subclasses will bridge as needed. 379 return false; 380 } 381 382 // The erasure of the return type is always the same 383 // for the same symbol. Reducing the three tests in 384 // the other branch to just one: 385 return !isSameMemberWhenErased(dest, method, method.erasure(types)); 386 } 387 } 388 /** 389 * Lookup the method as a member of the type. Compare the 390 * erasures. 391 * @param type the class where to look for the method 392 * @param method the method to look for in class 393 * @param erasure the erasure of method 394 */ 395 private boolean isSameMemberWhenErased(Type type, 396 MethodSymbol method, 397 Type erasure) { 398 return types.isSameType(erasure(types.memberType(type, method)), 399 erasure); 400 } 401 402 void addBridges(DiagnosticPosition pos, 403 TypeSymbol i, 404 ClassSymbol origin, 405 ListBuffer<JCTree> bridges) { 406 for (Symbol sym : i.members().getSymbols(NON_RECURSIVE)) 407 addBridgeIfNeeded(pos, sym, origin, bridges); 408 for (List<Type> l = types.interfaces(i.type); l.nonEmpty(); l = l.tail) 409 addBridges(pos, l.head.tsym, origin, bridges); 410 } 411 412 /** Add all necessary bridges to some class appending them to list buffer. 413 * @param pos The source code position to be used for the bridges. 414 * @param origin The class in which the bridges go. 415 * @param bridges The list buffer to which the bridges are added. 416 */ 417 void addBridges(DiagnosticPosition pos, ClassSymbol origin, ListBuffer<JCTree> bridges) { 418 Type st = types.supertype(origin.type); 419 while (st.hasTag(CLASS)) { 420 // if (isSpecialization(st)) 421 addBridges(pos, st.tsym, origin, bridges); 422 st = types.supertype(st); 423 } 424 for (List<Type> l = types.interfaces(origin.type); l.nonEmpty(); l = l.tail) 425 // if (isSpecialization(l.head)) 426 addBridges(pos, l.head.tsym, origin, bridges); 427 } 428 429 /* ************************************************************************ 430 * Visitor methods 431 *************************************************************************/ 432 433 /** Visitor argument: proto-type. 434 */ 435 private Type pt; 436 437 /** Visitor method: perform a type translation on tree. 438 */ 439 public <T extends JCTree> T translate(T tree, Type pt) { 440 Type prevPt = this.pt; 441 try { 442 this.pt = pt; 443 return translate(tree); 444 } finally { 445 this.pt = prevPt; 446 } 447 } 448 449 /** Visitor method: perform a type translation on list of trees. 450 */ 451 public <T extends JCTree> List<T> translate(List<T> trees, Type pt) { 452 Type prevPt = this.pt; 453 List<T> res; 454 try { 455 this.pt = pt; 456 res = translate(trees); 457 } finally { 458 this.pt = prevPt; 459 } 460 return res; 461 } 462 463 public void visitClassDef(JCClassDecl tree) { 464 translateClass(tree.sym); 465 result = tree; 466 } 467 468 Type returnType = null; 469 public void visitMethodDef(JCMethodDecl tree) { 470 Type prevRetType = returnType; 471 try { 472 returnType = erasure(tree.type).getReturnType(); 473 tree.restype = translate(tree.restype, null); 474 tree.typarams = List.nil(); 475 tree.params = translateVarDefs(tree.params); 476 tree.recvparam = translate(tree.recvparam, null); 477 tree.thrown = translate(tree.thrown, null); 478 tree.body = translate(tree.body, tree.sym.erasure(types).getReturnType()); 479 tree.type = erasure(tree.type); 480 result = tree; 481 } finally { 482 returnType = prevRetType; 483 } 484 } 485 486 public void visitVarDef(JCVariableDecl tree) { 487 tree.vartype = translate(tree.vartype, null); 488 tree.init = translate(tree.init, tree.sym.erasure(types)); 489 tree.type = erasure(tree.type); 490 result = tree; 491 } 492 493 public void visitDoLoop(JCDoWhileLoop tree) { 494 tree.body = translate(tree.body); 495 tree.cond = translate(tree.cond, syms.booleanType); 496 result = tree; 497 } 498 499 public void visitWhileLoop(JCWhileLoop tree) { 500 tree.cond = translate(tree.cond, syms.booleanType); 501 tree.body = translate(tree.body); 502 result = tree; 503 } 504 505 public void visitWithField(JCWithField tree) { 506 tree.field = translate(tree.field, null); 507 tree.value = translate(tree.value, erasure(tree.field.type)); 508 tree.type = erasure(tree.type); 509 result = retype(tree, tree.type, pt); 510 } 511 512 public void visitForLoop(JCForLoop tree) { 513 tree.init = translate(tree.init, null); 514 if (tree.cond != null) 515 tree.cond = translate(tree.cond, syms.booleanType); 516 tree.step = translate(tree.step, null); 517 tree.body = translate(tree.body); 518 result = tree; 519 } 520 521 public void visitForeachLoop(JCEnhancedForLoop tree) { 522 tree.var = translate(tree.var, null); 523 Type iterableType = tree.expr.type; 524 tree.expr = translate(tree.expr, erasure(tree.expr.type)); 525 if (types.elemtype(tree.expr.type) == null) 526 tree.expr.type = iterableType; // preserve type for Lower 527 tree.body = translate(tree.body); 528 result = tree; 529 } 530 531 public void visitLambda(JCLambda tree) { 532 Type prevRetType = returnType; 533 try { 534 returnType = erasure(tree.getDescriptorType(types)).getReturnType(); 535 tree.params = translate(tree.params); 536 tree.body = translate(tree.body, tree.body.type == null || returnType.hasTag(VOID) ? null : returnType); 537 if (!tree.type.isIntersection()) { 538 tree.type = erasure(tree.type); 539 } else { 540 tree.type = types.erasure(types.findDescriptorSymbol(tree.type.tsym).owner.type); 541 } 542 result = tree; 543 } 544 finally { 545 returnType = prevRetType; 546 } 547 } 548 549 public void visitSwitch(JCSwitch tree) { 550 Type selsuper = types.supertype(tree.selector.type); 551 boolean enumSwitch = selsuper != null && 552 selsuper.tsym == syms.enumSym; 553 Type target = enumSwitch ? erasure(tree.selector.type) : syms.intType; 554 tree.selector = translate(tree.selector, target); 555 tree.cases = translateCases(tree.cases); 556 result = tree; 557 } 558 559 public void visitCase(JCCase tree) { 560 tree.labels = translate(tree.labels, null); 561 tree.guard = translate(tree.guard, syms.booleanType); 562 tree.stats = translate(tree.stats); 563 result = tree; 564 } 565 566 @Override 567 public void visitAnyPattern(JCAnyPattern tree) { 568 result = tree; 569 } 570 571 public void visitBindingPattern(JCBindingPattern tree) { 572 tree.var = translate(tree.var, null); 573 result = tree; 574 } 575 576 @Override 577 public void visitConstantCaseLabel(JCConstantCaseLabel tree) { 578 tree.expr = translate(tree.expr, null); 579 result = tree; 580 } 581 582 @Override 583 public void visitPatternCaseLabel(JCPatternCaseLabel tree) { 584 tree.pat = translate(tree.pat, null); 585 result = tree; 586 } 587 588 public void visitSwitchExpression(JCSwitchExpression tree) { 589 Type selsuper = types.supertype(tree.selector.type); 590 boolean enumSwitch = selsuper != null && 591 selsuper.tsym == syms.enumSym; 592 Type target = enumSwitch ? erasure(tree.selector.type) : syms.intType; 593 tree.selector = translate(tree.selector, target); 594 tree.cases = translate(tree.cases, tree.type); 595 tree.type = erasure(tree.type); 596 result = retype(tree, tree.type, pt); 597 } 598 599 public void visitRecordPattern(JCRecordPattern tree) { 600 tree.fullComponentTypes = tree.record.getRecordComponents() 601 .map(rc -> types.memberType(tree.type, rc)); 602 tree.deconstructor = translate(tree.deconstructor, null); 603 tree.nested = translate(tree.nested, null); 604 result = tree; 605 } 606 607 public void visitSynchronized(JCSynchronized tree) { 608 tree.lock = translate(tree.lock, erasure(tree.lock.type)); 609 tree.body = translate(tree.body); 610 result = tree; 611 } 612 613 public void visitTry(JCTry tree) { 614 tree.resources = translate(tree.resources, syms.autoCloseableType); 615 tree.body = translate(tree.body); 616 tree.catchers = translateCatchers(tree.catchers); 617 tree.finalizer = translate(tree.finalizer); 618 result = tree; 619 } 620 621 public void visitConditional(JCConditional tree) { 622 tree.cond = translate(tree.cond, syms.booleanType); 623 tree.truepart = translate(tree.truepart, erasure(tree.type)); 624 tree.falsepart = translate(tree.falsepart, erasure(tree.type)); 625 tree.type = erasure(tree.type); 626 result = retype(tree, tree.type, pt); 627 } 628 629 public void visitIf(JCIf tree) { 630 tree.cond = translate(tree.cond, syms.booleanType); 631 tree.thenpart = translate(tree.thenpart); 632 tree.elsepart = translate(tree.elsepart); 633 result = tree; 634 } 635 636 public void visitExec(JCExpressionStatement tree) { 637 tree.expr = translate(tree.expr, null); 638 result = tree; 639 } 640 641 public void visitReturn(JCReturn tree) { 642 if (!returnType.hasTag(VOID)) 643 tree.expr = translate(tree.expr, returnType); 644 result = tree; 645 } 646 647 @Override 648 public void visitBreak(JCBreak tree) { 649 result = tree; 650 } 651 652 @Override 653 public void visitYield(JCYield tree) { 654 tree.value = translate(tree.value, erasure(tree.value.type)); 655 tree.value.type = erasure(tree.value.type); 656 tree.value = retype(tree.value, tree.value.type, pt); 657 result = tree; 658 } 659 660 public void visitThrow(JCThrow tree) { 661 tree.expr = translate(tree.expr, erasure(tree.expr.type)); 662 result = tree; 663 } 664 665 public void visitAssert(JCAssert tree) { 666 tree.cond = translate(tree.cond, syms.booleanType); 667 if (tree.detail != null) 668 tree.detail = translate(tree.detail, erasure(tree.detail.type)); 669 result = tree; 670 } 671 672 public void visitApply(JCMethodInvocation tree) { 673 tree.meth = translate(tree.meth, null); 674 Symbol meth = TreeInfo.symbol(tree.meth); 675 Type mt = meth.erasure(types); 676 boolean useInstantiatedPtArgs = !types.isSignaturePolymorphic((MethodSymbol)meth.baseSymbol()); 677 List<Type> argtypes = useInstantiatedPtArgs ? 678 tree.meth.type.getParameterTypes() : 679 mt.getParameterTypes(); 680 // TODO - is enum so <init> 681 if (meth.name == names.init && meth.owner == syms.enumSym) 682 argtypes = argtypes.tail.tail; 683 if (tree.varargsElement != null) 684 tree.varargsElement = types.erasure(tree.varargsElement); 685 else 686 if (tree.args.length() != argtypes.length()) { 687 Assert.error(String.format("Incorrect number of arguments; expected %d, found %d", 688 tree.args.length(), argtypes.length())); 689 } 690 tree.args = translateArgs(tree.args, argtypes, tree.varargsElement); 691 692 tree.type = types.erasure(tree.type); 693 // Insert casts of method invocation results as needed. 694 result = retype(tree, mt.getReturnType(), pt); 695 } 696 697 public void visitNewClass(JCNewClass tree) { 698 if (tree.encl != null) { 699 if (tree.def == null) { 700 tree.encl = translate(tree.encl, erasure(tree.encl.type)); 701 } else { 702 tree.args = tree.args.prepend(attr.makeNullCheck(tree.encl)); 703 tree.encl = null; 704 } 705 } 706 707 Type erasedConstructorType = tree.constructorType != null ? 708 erasure(tree.constructorType) : 709 null; 710 711 List<Type> argtypes = erasedConstructorType != null ? 712 erasedConstructorType.getParameterTypes() : 713 tree.constructor.erasure(types).getParameterTypes(); 714 715 tree.clazz = translate(tree.clazz, null); 716 if (tree.varargsElement != null) 717 tree.varargsElement = types.erasure(tree.varargsElement); 718 tree.args = translateArgs( 719 tree.args, argtypes, tree.varargsElement); 720 tree.def = translate(tree.def, null); 721 if (erasedConstructorType != null) 722 tree.constructorType = erasedConstructorType; 723 tree.type = erasure(tree.type); 724 result = tree; 725 } 726 727 public void visitNewArray(JCNewArray tree) { 728 tree.elemtype = translate(tree.elemtype, null); 729 translate(tree.dims, syms.intType); 730 if (tree.type != null) { 731 tree.elems = translate(tree.elems, erasure(types.elemtype(tree.type))); 732 tree.type = erasure(tree.type); 733 } else { 734 tree.elems = translate(tree.elems, null); 735 } 736 737 result = tree; 738 } 739 740 public void visitParens(JCParens tree) { 741 tree.expr = translate(tree.expr, pt); 742 tree.type = erasure(tree.expr.type); 743 result = tree; 744 } 745 746 public void visitAssign(JCAssign tree) { 747 tree.lhs = translate(tree.lhs, null); 748 tree.rhs = translate(tree.rhs, erasure(tree.lhs.type)); 749 tree.type = erasure(tree.lhs.type); 750 result = retype(tree, tree.type, pt); 751 } 752 753 public void visitAssignop(JCAssignOp tree) { 754 tree.lhs = translate(tree.lhs, null); 755 tree.rhs = translate(tree.rhs, tree.operator.type.getParameterTypes().tail.head); 756 tree.type = erasure(tree.type); 757 result = tree; 758 } 759 760 public void visitUnary(JCUnary tree) { 761 tree.arg = translate(tree.arg, (tree.getTag() == Tag.NULLCHK) 762 ? tree.type 763 : tree.operator.type.getParameterTypes().head); 764 result = tree; 765 } 766 767 public void visitBinary(JCBinary tree) { 768 tree.lhs = translate(tree.lhs, tree.operator.type.getParameterTypes().head); 769 tree.rhs = translate(tree.rhs, tree.operator.type.getParameterTypes().tail.head); 770 result = tree; 771 } 772 773 public void visitAnnotatedType(JCAnnotatedType tree) { 774 // For now, we need to keep the annotations in the tree because of the current 775 // MultiCatch implementation wrt type annotations 776 List<TypeCompound> mirrors = annotate.fromAnnotations(tree.annotations); 777 tree.underlyingType = translate(tree.underlyingType); 778 tree.type = tree.underlyingType.type.annotatedType(mirrors); 779 result = tree; 780 } 781 782 public void visitTypeCast(JCTypeCast tree) { 783 tree.clazz = translate(tree.clazz, null); 784 Type originalTarget = tree.type; 785 tree.type = erasure(tree.type); 786 JCExpression newExpression = translate(tree.expr, tree.type); 787 if (newExpression != tree.expr) { 788 JCTypeCast typeCast = newExpression.hasTag(Tag.TYPECAST) 789 ? (JCTypeCast) newExpression 790 : null; 791 tree.expr = typeCast != null && types.isSameType(typeCast.type, tree.type) 792 ? typeCast.expr 793 : newExpression; 794 } 795 if (originalTarget.isIntersection()) { 796 Type.IntersectionClassType ict = (Type.IntersectionClassType)originalTarget; 797 for (Type c : ict.getExplicitComponents()) { 798 Type ec = erasure(c); 799 if (!types.isSameType(ec, tree.type) && (!types.isSameType(ec, pt))) { 800 tree.expr = coerce(tree.expr, ec); 801 } 802 } 803 } 804 result = retype(tree, tree.type, pt); 805 } 806 807 public void visitTypeTest(JCInstanceOf tree) { 808 tree.expr = translate(tree.expr, null); 809 tree.pattern = translate(tree.pattern, null); 810 result = tree; 811 } 812 813 public void visitIndexed(JCArrayAccess tree) { 814 tree.indexed = translate(tree.indexed, erasure(tree.indexed.type)); 815 tree.index = translate(tree.index, syms.intType); 816 817 // Insert casts of indexed expressions as needed. 818 result = retype(tree, types.elemtype(tree.indexed.type), pt); 819 } 820 821 // There ought to be nothing to rewrite here; 822 // we don't generate code. 823 public void visitAnnotation(JCAnnotation tree) { 824 result = tree; 825 } 826 827 public void visitIdent(JCIdent tree) { 828 Type et = tree.sym.erasure(types); 829 830 // Map type variables to their bounds. 831 if (tree.sym.kind == TYP && tree.sym.type.hasTag(TYPEVAR)) { 832 result = make.at(tree.pos).Type(et); 833 } else 834 // Map constants expressions to themselves. 835 if (tree.type.constValue() != null) { 836 result = tree; 837 } 838 // Insert casts of variable uses as needed. 839 else if (tree.sym.kind == VAR) { 840 result = retype(tree, et, pt); 841 } 842 else { 843 tree.type = erasure(tree.type); 844 result = tree; 845 } 846 } 847 848 public void visitStringTemplate(JCStringTemplate tree) { 849 tree.processor = translate(tree.processor, erasure(tree.processor.type)); 850 tree.expressions = tree.expressions.stream() 851 .map(e -> translate(e, erasure(e.type))).collect(List.collector()); 852 tree.type = erasure(tree.type); 853 result = tree; 854 } 855 856 public void visitSelect(JCFieldAccess tree) { 857 Type t = types.skipTypeVars(tree.selected.type, false); 858 if (t.isCompound()) { 859 tree.selected = coerce( 860 translate(tree.selected, erasure(tree.selected.type)), 861 erasure(tree.sym.owner.type)); 862 } else 863 tree.selected = translate(tree.selected, erasure(t)); 864 865 // Map constants expressions to themselves. 866 if (tree.type.constValue() != null) { 867 result = tree; 868 } 869 // Insert casts of variable uses as needed. 870 else if (tree.sym.kind == VAR) { 871 result = retype(tree, tree.sym.erasure(types), pt); 872 } 873 else { 874 tree.type = erasure(tree.type); 875 result = tree; 876 } 877 } 878 879 public void visitReference(JCMemberReference tree) { 880 Type t = types.skipTypeVars(tree.expr.type, false); 881 Type receiverTarget = t.isCompound() ? erasure(tree.sym.owner.type) : erasure(t); 882 if (tree.kind == ReferenceKind.UNBOUND) { 883 tree.expr = make.Type(receiverTarget); 884 } else { 885 tree.expr = translate(tree.expr, receiverTarget); 886 } 887 if (!tree.type.isIntersection()) { 888 tree.type = erasure(tree.type); 889 } else { 890 tree.type = types.erasure(types.findDescriptorSymbol(tree.type.tsym).owner.type); 891 } 892 if (tree.varargsElement != null) 893 tree.varargsElement = erasure(tree.varargsElement); 894 result = tree; 895 } 896 897 public void visitTypeArray(JCArrayTypeTree tree) { 898 tree.elemtype = translate(tree.elemtype, null); 899 tree.type = erasure(tree.type); 900 result = tree; 901 } 902 903 /** Visitor method for parameterized types. 904 */ 905 public void visitTypeApply(JCTypeApply tree) { 906 JCTree clazz = translate(tree.clazz, null); 907 result = clazz; 908 } 909 910 public void visitTypeIntersection(JCTypeIntersection tree) { 911 tree.bounds = translate(tree.bounds, null); 912 tree.type = erasure(tree.type); 913 result = tree; 914 } 915 916 /************************************************************************** 917 * utility methods 918 *************************************************************************/ 919 920 private Type erasure(Type t) { 921 return types.erasure(t); 922 } 923 924 /************************************************************************** 925 * main method 926 *************************************************************************/ 927 928 private Env<AttrContext> env; 929 930 private static final String statePreviousToFlowAssertMsg = 931 "The current compile state [%s] of class %s is previous to FLOW"; 932 933 void translateClass(ClassSymbol c) { 934 Type st = types.supertype(c.type); 935 // process superclass before derived 936 if (st.hasTag(CLASS)) { 937 translateClass((ClassSymbol)st.tsym); 938 } 939 940 Env<AttrContext> myEnv = enter.getEnv(c); 941 if (myEnv == null || (c.flags_field & TYPE_TRANSLATED) != 0) { 942 return; 943 } 944 c.flags_field |= TYPE_TRANSLATED; 945 946 /* The two assertions below are set for early detection of any attempt 947 * to translate a class that: 948 * 949 * 1) has no compile state being it the most outer class. 950 * We accept this condition for inner classes. 951 * 952 * 2) has a compile state which is previous to Flow state. 953 */ 954 boolean envHasCompState = compileStates.get(myEnv) != null; 955 if (!envHasCompState && c.outermostClass() == c) { 956 Assert.error("No info for outermost class: " + myEnv.enclClass.sym); 957 } 958 959 if (envHasCompState && 960 CompileState.FLOW.isAfter(compileStates.get(myEnv))) { 961 Assert.error(String.format(statePreviousToFlowAssertMsg, 962 compileStates.get(myEnv), myEnv.enclClass.sym)); 963 } 964 965 Env<AttrContext> oldEnv = env; 966 try { 967 env = myEnv; 968 // class has not been translated yet 969 970 TreeMaker savedMake = make; 971 Type savedPt = pt; 972 make = make.forToplevel(env.toplevel); 973 pt = null; 974 try { 975 JCClassDecl tree = (JCClassDecl) env.tree; 976 tree.typarams = List.nil(); 977 super.visitClassDef(tree); 978 make.at(tree.pos); 979 ListBuffer<JCTree> bridges = new ListBuffer<>(); 980 addBridges(tree.pos(), c, bridges); 981 tree.defs = bridges.toList().prependList(tree.defs); 982 tree.type = erasure(tree.type); 983 } finally { 984 make = savedMake; 985 pt = savedPt; 986 } 987 } finally { 988 env = oldEnv; 989 } 990 } 991 992 /** Translate a toplevel class definition. 993 * @param cdef The definition to be translated. 994 */ 995 public JCTree translateTopLevelClass(JCTree cdef, TreeMaker make) { 996 // note that this method does NOT support recursion. 997 this.make = make; 998 pt = null; 999 return translate(cdef, null); 1000 } 1001 }