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