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