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