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