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