1 /* 2 * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.javac.comp; 27 28 import java.util.*; 29 30 import com.sun.tools.javac.code.*; 31 import com.sun.tools.javac.code.Attribute.TypeCompound; 32 import com.sun.tools.javac.code.Source.Feature; 33 import com.sun.tools.javac.code.Symbol.*; 34 import com.sun.tools.javac.code.Type.IntersectionClassType; 35 import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError; 36 import com.sun.tools.javac.resources.CompilerProperties.Errors; 37 import com.sun.tools.javac.tree.*; 38 import com.sun.tools.javac.tree.JCTree.*; 39 import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind; 40 import com.sun.tools.javac.util.*; 41 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 42 import com.sun.tools.javac.util.List; 43 44 import static com.sun.tools.javac.code.Flags.*; 45 import static com.sun.tools.javac.code.Kinds.Kind.*; 46 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; 47 import static com.sun.tools.javac.code.TypeTag.CLASS; 48 import static com.sun.tools.javac.code.TypeTag.TYPEVAR; 49 import static com.sun.tools.javac.code.TypeTag.VOID; 50 import static com.sun.tools.javac.comp.CompileStates.CompileState; 51 import com.sun.tools.javac.tree.JCTree.JCBreak; 52 53 /** This pass translates Generic Java to conventional Java. 54 * 55 * <p><b>This is NOT part of any supported API. 56 * If you write code that depends on this, you do so at your own risk. 57 * This code and its internal interfaces are subject to change or 58 * deletion without notice.</b> 59 */ 60 public class TransTypes extends TreeTranslator { 61 /** The context key for the TransTypes phase. */ 62 protected static final Context.Key<TransTypes> transTypesKey = new Context.Key<>(); 63 64 /** Get the instance for this context. */ instance(Context context)65 public static TransTypes instance(Context context) { 66 TransTypes instance = context.get(transTypesKey); 67 if (instance == null) 68 instance = new TransTypes(context); 69 return instance; 70 } 71 72 private Names names; 73 private Log log; 74 private Symtab syms; 75 private TreeMaker make; 76 private Enter enter; 77 private Types types; 78 private Annotate annotate; 79 private Attr attr; 80 private final Resolve resolve; 81 private final CompileStates compileStates; 82 83 /** Switch: is complex graph inference supported? */ 84 private final boolean allowGraphInference; 85 86 /** Switch: are default methods supported? */ 87 private final boolean allowInterfaceBridges; 88 TransTypes(Context context)89 protected TransTypes(Context context) { 90 context.put(transTypesKey, this); 91 compileStates = CompileStates.instance(context); 92 names = Names.instance(context); 93 log = Log.instance(context); 94 syms = Symtab.instance(context); 95 enter = Enter.instance(context); 96 types = Types.instance(context); 97 make = TreeMaker.instance(context); 98 resolve = Resolve.instance(context); 99 Source source = Source.instance(context); 100 allowInterfaceBridges = Feature.DEFAULT_METHODS.allowedInSource(source); 101 allowGraphInference = Feature.GRAPH_INFERENCE.allowedInSource(source); 102 annotate = Annotate.instance(context); 103 attr = Attr.instance(context); 104 } 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 */ cast(JCExpression tree, Type target)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 */ coerce(Env<AttrContext> env, JCExpression tree, Type target)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 } coerce(JCExpression tree, Type target)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 */ retype(JCExpression tree, Type erasedType, Type target)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 */ translateArgs(List<T> _args, List<Type> parameters, Type varargsElement)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 translateArgs(List<T> _args, List<Type> parameters, Type varargsElement, Env<AttrContext> localEnv)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 bridges The list buffer to which the bridge will be added 240 */ addBridge(DiagnosticPosition pos, MethodSymbol meth, MethodSymbol impl, ClassSymbol origin, ListBuffer<JCTree> bridges)241 void addBridge(DiagnosticPosition pos, 242 MethodSymbol meth, 243 MethodSymbol impl, 244 ClassSymbol origin, 245 ListBuffer<JCTree> bridges) { 246 make.at(pos); 247 Type implTypeErasure = erasure(impl.type); 248 249 // Create a bridge method symbol and a bridge definition without a body. 250 Type bridgeType = meth.erasure(types); 251 long flags = impl.flags() & AccessFlags | SYNTHETIC | BRIDGE | 252 (origin.isInterface() ? DEFAULT : 0); 253 MethodSymbol bridge = new MethodSymbol(flags, 254 meth.name, 255 bridgeType, 256 origin); 257 /* once JDK-6996415 is solved it should be checked if this approach can 258 * be applied to method addOverrideBridgesIfNeeded 259 */ 260 bridge.params = createBridgeParams(impl, bridge, bridgeType); 261 bridge.setAttributes(impl); 262 263 JCMethodDecl md = make.MethodDef(bridge, null); 264 265 // The bridge calls this.impl(..), if we have an implementation 266 // in the current class, super.impl(...) otherwise. 267 JCExpression receiver = (impl.owner == origin) 268 ? make.This(origin.erasure(types)) 269 : make.Super(types.supertype(origin.type).tsym.erasure(types), origin); 270 271 // The type returned from the original method. 272 Type calltype = implTypeErasure.getReturnType(); 273 274 // Construct a call of this.impl(params), or super.impl(params), 275 // casting params and possibly results as needed. 276 JCExpression call = 277 make.Apply( 278 null, 279 make.Select(receiver, impl).setType(calltype), 280 translateArgs(make.Idents(md.params), implTypeErasure.getParameterTypes(), null)) 281 .setType(calltype); 282 JCStatement stat = (implTypeErasure.getReturnType().hasTag(VOID)) 283 ? make.Exec(call) 284 : make.Return(coerce(call, bridgeType.getReturnType())); 285 md.body = make.Block(0, List.of(stat)); 286 287 // Add bridge to `bridges' buffer 288 bridges.append(md); 289 290 // Add bridge to scope of enclosing class and keep track of the bridge span. 291 origin.members().enter(bridge); 292 } 293 createBridgeParams(MethodSymbol impl, MethodSymbol bridge, Type bridgeType)294 private List<VarSymbol> createBridgeParams(MethodSymbol impl, MethodSymbol bridge, 295 Type bridgeType) { 296 List<VarSymbol> bridgeParams = null; 297 if (impl.params != null) { 298 bridgeParams = List.nil(); 299 List<VarSymbol> implParams = impl.params; 300 Type.MethodType mType = (Type.MethodType)bridgeType; 301 List<Type> argTypes = mType.argtypes; 302 while (implParams.nonEmpty() && argTypes.nonEmpty()) { 303 VarSymbol param = new VarSymbol(implParams.head.flags() | SYNTHETIC | PARAMETER, 304 implParams.head.name, argTypes.head, bridge); 305 param.setAttributes(implParams.head); 306 bridgeParams = bridgeParams.append(param); 307 implParams = implParams.tail; 308 argTypes = argTypes.tail; 309 } 310 } 311 return bridgeParams; 312 } 313 314 /** Add bridge if given symbol is a non-private, non-static member 315 * of the given class, which is either defined in the class or non-final 316 * inherited, and one of the two following conditions holds: 317 * 1. The method's type changes in the given class, as compared to the 318 * class where the symbol was defined, (in this case 319 * we have extended a parameterized class with non-trivial parameters). 320 * 2. The method has an implementation with a different erased return type. 321 * (in this case we have used co-variant returns). 322 * If a bridge already exists in some other class, no new bridge is added. 323 * Instead, it is checked that the bridge symbol overrides the method symbol. 324 * (Spec ???). 325 * todo: what about bridges for privates??? 326 * 327 * @param pos The source code position to be used for the definition. 328 * @param sym The symbol for which a bridge might have to be added. 329 * @param origin The class in which the bridge would go. 330 * @param bridges The list buffer to which the bridge would be added. 331 */ addBridgeIfNeeded(DiagnosticPosition pos, Symbol sym, ClassSymbol origin, ListBuffer<JCTree> bridges)332 void addBridgeIfNeeded(DiagnosticPosition pos, 333 Symbol sym, 334 ClassSymbol origin, 335 ListBuffer<JCTree> bridges) { 336 if (sym.kind == MTH && 337 sym.name != names.init && 338 (sym.flags() & (PRIVATE | STATIC)) == 0 && 339 (sym.flags() & SYNTHETIC) != SYNTHETIC && 340 sym.isMemberOf(origin, types)) { 341 MethodSymbol meth = (MethodSymbol)sym; 342 MethodSymbol bridge = meth.binaryImplementation(origin, types); 343 MethodSymbol impl = meth.implementation(origin, types, true); 344 if (bridge == null || 345 bridge == meth || 346 (impl != null && !bridge.owner.isSubClass(impl.owner, types))) { 347 // No bridge was added yet. 348 if (impl != null && bridge != impl && isBridgeNeeded(meth, impl, origin.type)) { 349 addBridge(pos, meth, impl, origin, bridges); 350 } else if (impl == meth 351 && impl.owner != origin 352 && (impl.flags() & FINAL) == 0 353 && (meth.flags() & (ABSTRACT|PUBLIC)) == PUBLIC 354 && (origin.flags() & PUBLIC) > (impl.owner.flags() & PUBLIC)) { 355 // this is to work around a horrible but permanent 356 // reflection design error. 357 addBridge(pos, meth, impl, origin, bridges); 358 } 359 } 360 } 361 } 362 // where 363 364 /** 365 * @param method The symbol for which a bridge might have to be added 366 * @param impl The implementation of method 367 * @param dest The type in which the bridge would go 368 */ isBridgeNeeded(MethodSymbol method, MethodSymbol impl, Type dest)369 private boolean isBridgeNeeded(MethodSymbol method, 370 MethodSymbol impl, 371 Type dest) { 372 if (impl != method) { 373 // If either method or impl have different erasures as 374 // members of dest, a bridge is needed. 375 Type method_erasure = method.erasure(types); 376 if (!isSameMemberWhenErased(dest, method, method_erasure)) 377 return true; 378 Type impl_erasure = impl.erasure(types); 379 if (!isSameMemberWhenErased(dest, impl, impl_erasure)) 380 return true; 381 382 /* Bottom line: A bridge is needed if the erasure of the implementation 383 is different from that of the method that it overrides. 384 */ 385 return !types.isSameType(impl_erasure, method_erasure); 386 } else { 387 // method and impl are the same... 388 if ((method.flags() & ABSTRACT) != 0) { 389 // ...and abstract so a bridge is not needed. 390 // Concrete subclasses will bridge as needed. 391 return false; 392 } 393 394 // The erasure of the return type is always the same 395 // for the same symbol. Reducing the three tests in 396 // the other branch to just one: 397 return !isSameMemberWhenErased(dest, method, method.erasure(types)); 398 } 399 } 400 /** 401 * Lookup the method as a member of the type. Compare the 402 * erasures. 403 * @param type the class where to look for the method 404 * @param method the method to look for in class 405 * @param erasure the erasure of method 406 */ isSameMemberWhenErased(Type type, MethodSymbol method, Type erasure)407 private boolean isSameMemberWhenErased(Type type, 408 MethodSymbol method, 409 Type erasure) { 410 return types.isSameType(erasure(types.memberType(type, method)), 411 erasure); 412 } 413 addBridges(DiagnosticPosition pos, TypeSymbol i, ClassSymbol origin, ListBuffer<JCTree> bridges)414 void addBridges(DiagnosticPosition pos, 415 TypeSymbol i, 416 ClassSymbol origin, 417 ListBuffer<JCTree> bridges) { 418 for (Symbol sym : i.members().getSymbols(NON_RECURSIVE)) 419 addBridgeIfNeeded(pos, sym, origin, bridges); 420 for (List<Type> l = types.interfaces(i.type); l.nonEmpty(); l = l.tail) 421 addBridges(pos, l.head.tsym, origin, bridges); 422 } 423 424 /** Add all necessary bridges to some class appending them to list buffer. 425 * @param pos The source code position to be used for the bridges. 426 * @param origin The class in which the bridges go. 427 * @param bridges The list buffer to which the bridges are added. 428 */ addBridges(DiagnosticPosition pos, ClassSymbol origin, ListBuffer<JCTree> bridges)429 void addBridges(DiagnosticPosition pos, ClassSymbol origin, ListBuffer<JCTree> bridges) { 430 Type st = types.supertype(origin.type); 431 while (st.hasTag(CLASS)) { 432 // if (isSpecialization(st)) 433 addBridges(pos, st.tsym, origin, bridges); 434 st = types.supertype(st); 435 } 436 for (List<Type> l = types.interfaces(origin.type); l.nonEmpty(); l = l.tail) 437 // if (isSpecialization(l.head)) 438 addBridges(pos, l.head.tsym, origin, bridges); 439 } 440 441 /* ************************************************************************ 442 * Visitor methods 443 *************************************************************************/ 444 445 /** Visitor argument: proto-type. 446 */ 447 private Type pt; 448 449 /** Visitor method: perform a type translation on tree. 450 */ translate(T tree, Type pt)451 public <T extends JCTree> T translate(T tree, Type pt) { 452 Type prevPt = this.pt; 453 try { 454 this.pt = pt; 455 return translate(tree); 456 } finally { 457 this.pt = prevPt; 458 } 459 } 460 461 /** Visitor method: perform a type translation on list of trees. 462 */ translate(List<T> trees, Type pt)463 public <T extends JCTree> List<T> translate(List<T> trees, Type pt) { 464 Type prevPt = this.pt; 465 List<T> res; 466 try { 467 this.pt = pt; 468 res = translate(trees); 469 } finally { 470 this.pt = prevPt; 471 } 472 return res; 473 } 474 visitClassDef(JCClassDecl tree)475 public void visitClassDef(JCClassDecl tree) { 476 translateClass(tree.sym); 477 result = tree; 478 } 479 480 Type returnType = null; visitMethodDef(JCMethodDecl tree)481 public void visitMethodDef(JCMethodDecl tree) { 482 Type prevRetType = returnType; 483 try { 484 returnType = erasure(tree.type).getReturnType(); 485 tree.restype = translate(tree.restype, null); 486 tree.typarams = List.nil(); 487 tree.params = translateVarDefs(tree.params); 488 tree.recvparam = translate(tree.recvparam, null); 489 tree.thrown = translate(tree.thrown, null); 490 tree.body = translate(tree.body, tree.sym.erasure(types).getReturnType()); 491 tree.type = erasure(tree.type); 492 result = tree; 493 } finally { 494 returnType = prevRetType; 495 } 496 } 497 visitVarDef(JCVariableDecl tree)498 public void visitVarDef(JCVariableDecl tree) { 499 tree.vartype = translate(tree.vartype, null); 500 tree.init = translate(tree.init, tree.sym.erasure(types)); 501 tree.type = erasure(tree.type); 502 result = tree; 503 } 504 visitDoLoop(JCDoWhileLoop tree)505 public void visitDoLoop(JCDoWhileLoop tree) { 506 tree.body = translate(tree.body); 507 tree.cond = translate(tree.cond, syms.booleanType); 508 result = tree; 509 } 510 visitWhileLoop(JCWhileLoop tree)511 public void visitWhileLoop(JCWhileLoop tree) { 512 tree.cond = translate(tree.cond, syms.booleanType); 513 tree.body = translate(tree.body); 514 result = tree; 515 } 516 visitForLoop(JCForLoop tree)517 public void visitForLoop(JCForLoop tree) { 518 tree.init = translate(tree.init, null); 519 if (tree.cond != null) 520 tree.cond = translate(tree.cond, syms.booleanType); 521 tree.step = translate(tree.step, null); 522 tree.body = translate(tree.body); 523 result = tree; 524 } 525 visitForeachLoop(JCEnhancedForLoop tree)526 public void visitForeachLoop(JCEnhancedForLoop tree) { 527 tree.var = translate(tree.var, null); 528 Type iterableType = tree.expr.type; 529 tree.expr = translate(tree.expr, erasure(tree.expr.type)); 530 if (types.elemtype(tree.expr.type) == null) 531 tree.expr.type = iterableType; // preserve type for Lower 532 tree.body = translate(tree.body); 533 result = tree; 534 } 535 visitLambda(JCLambda tree)536 public void visitLambda(JCLambda tree) { 537 Type prevRetType = returnType; 538 try { 539 returnType = erasure(tree.getDescriptorType(types)).getReturnType(); 540 tree.params = translate(tree.params); 541 tree.body = translate(tree.body, tree.body.type == null || returnType.hasTag(VOID) ? null : returnType); 542 if (!tree.type.isIntersection()) { 543 tree.type = erasure(tree.type); 544 } else { 545 tree.type = types.erasure(types.findDescriptorSymbol(tree.type.tsym).owner.type); 546 } 547 result = tree; 548 } 549 finally { 550 returnType = prevRetType; 551 } 552 } 553 visitSwitch(JCSwitch tree)554 public void visitSwitch(JCSwitch tree) { 555 Type selsuper = types.supertype(tree.selector.type); 556 boolean enumSwitch = selsuper != null && 557 selsuper.tsym == syms.enumSym; 558 Type target = enumSwitch ? erasure(tree.selector.type) : syms.intType; 559 tree.selector = translate(tree.selector, target); 560 tree.cases = translateCases(tree.cases); 561 result = tree; 562 } 563 visitCase(JCCase tree)564 public void visitCase(JCCase tree) { 565 tree.pats = translate(tree.pats, null); 566 tree.stats = translate(tree.stats); 567 result = tree; 568 } 569 visitBindingPattern(JCBindingPattern tree)570 public void visitBindingPattern(JCBindingPattern tree) { 571 tree.var = translate(tree.var, null); 572 result = tree; 573 } 574 visitSwitchExpression(JCSwitchExpression tree)575 public void visitSwitchExpression(JCSwitchExpression tree) { 576 Type selsuper = types.supertype(tree.selector.type); 577 boolean enumSwitch = selsuper != null && 578 selsuper.tsym == syms.enumSym; 579 Type target = enumSwitch ? erasure(tree.selector.type) : syms.intType; 580 tree.selector = translate(tree.selector, target); 581 tree.cases = translate(tree.cases); 582 tree.type = erasure(tree.type); 583 result = retype(tree, tree.type, pt); 584 } 585 visitSynchronized(JCSynchronized tree)586 public void visitSynchronized(JCSynchronized tree) { 587 tree.lock = translate(tree.lock, erasure(tree.lock.type)); 588 tree.body = translate(tree.body); 589 result = tree; 590 } 591 visitTry(JCTry tree)592 public void visitTry(JCTry tree) { 593 tree.resources = translate(tree.resources, syms.autoCloseableType); 594 tree.body = translate(tree.body); 595 tree.catchers = translateCatchers(tree.catchers); 596 tree.finalizer = translate(tree.finalizer); 597 result = tree; 598 } 599 visitConditional(JCConditional tree)600 public void visitConditional(JCConditional tree) { 601 tree.cond = translate(tree.cond, syms.booleanType); 602 tree.truepart = translate(tree.truepart, erasure(tree.type)); 603 tree.falsepart = translate(tree.falsepart, erasure(tree.type)); 604 tree.type = erasure(tree.type); 605 result = retype(tree, tree.type, pt); 606 } 607 visitIf(JCIf tree)608 public void visitIf(JCIf tree) { 609 tree.cond = translate(tree.cond, syms.booleanType); 610 tree.thenpart = translate(tree.thenpart); 611 tree.elsepart = translate(tree.elsepart); 612 result = tree; 613 } 614 visitExec(JCExpressionStatement tree)615 public void visitExec(JCExpressionStatement tree) { 616 tree.expr = translate(tree.expr, null); 617 result = tree; 618 } 619 visitReturn(JCReturn tree)620 public void visitReturn(JCReturn tree) { 621 if (!returnType.hasTag(VOID)) 622 tree.expr = translate(tree.expr, returnType); 623 result = tree; 624 } 625 626 @Override visitBreak(JCBreak tree)627 public void visitBreak(JCBreak tree) { 628 result = tree; 629 } 630 631 @Override visitYield(JCYield tree)632 public void visitYield(JCYield tree) { 633 tree.value = translate(tree.value, erasure(tree.value.type)); 634 tree.value.type = erasure(tree.value.type); 635 tree.value = retype(tree.value, tree.value.type, pt); 636 result = tree; 637 } 638 visitThrow(JCThrow tree)639 public void visitThrow(JCThrow tree) { 640 tree.expr = translate(tree.expr, erasure(tree.expr.type)); 641 result = tree; 642 } 643 visitAssert(JCAssert tree)644 public void visitAssert(JCAssert tree) { 645 tree.cond = translate(tree.cond, syms.booleanType); 646 if (tree.detail != null) 647 tree.detail = translate(tree.detail, erasure(tree.detail.type)); 648 result = tree; 649 } 650 visitApply(JCMethodInvocation tree)651 public void visitApply(JCMethodInvocation tree) { 652 tree.meth = translate(tree.meth, null); 653 Symbol meth = TreeInfo.symbol(tree.meth); 654 Type mt = meth.erasure(types); 655 boolean useInstantiatedPtArgs = 656 allowGraphInference && !types.isSignaturePolymorphic((MethodSymbol)meth.baseSymbol()); 657 List<Type> argtypes = useInstantiatedPtArgs ? 658 tree.meth.type.getParameterTypes() : 659 mt.getParameterTypes(); 660 if (meth.name == names.init && meth.owner == syms.enumSym) 661 argtypes = argtypes.tail.tail; 662 if (tree.varargsElement != null) 663 tree.varargsElement = types.erasure(tree.varargsElement); 664 else 665 if (tree.args.length() != argtypes.length()) { 666 Assert.error(String.format("Incorrect number of arguments; expected %d, found %d", 667 tree.args.length(), argtypes.length())); 668 } 669 tree.args = translateArgs(tree.args, argtypes, tree.varargsElement); 670 671 tree.type = types.erasure(tree.type); 672 // Insert casts of method invocation results as needed. 673 result = retype(tree, mt.getReturnType(), pt); 674 } 675 visitNewClass(JCNewClass tree)676 public void visitNewClass(JCNewClass tree) { 677 if (tree.encl != null) { 678 if (tree.def == null) { 679 tree.encl = translate(tree.encl, erasure(tree.encl.type)); 680 } else { 681 tree.args = tree.args.prepend(attr.makeNullCheck(tree.encl)); 682 tree.encl = null; 683 } 684 } 685 686 Type erasedConstructorType = tree.constructorType != null ? 687 erasure(tree.constructorType) : 688 null; 689 690 List<Type> argtypes = erasedConstructorType != null && allowGraphInference ? 691 erasedConstructorType.getParameterTypes() : 692 tree.constructor.erasure(types).getParameterTypes(); 693 694 tree.clazz = translate(tree.clazz, null); 695 if (tree.varargsElement != null) 696 tree.varargsElement = types.erasure(tree.varargsElement); 697 tree.args = translateArgs( 698 tree.args, argtypes, tree.varargsElement); 699 tree.def = translate(tree.def, null); 700 if (erasedConstructorType != null) 701 tree.constructorType = erasedConstructorType; 702 tree.type = erasure(tree.type); 703 result = tree; 704 } 705 visitNewArray(JCNewArray tree)706 public void visitNewArray(JCNewArray tree) { 707 tree.elemtype = translate(tree.elemtype, null); 708 translate(tree.dims, syms.intType); 709 if (tree.type != null) { 710 tree.elems = translate(tree.elems, erasure(types.elemtype(tree.type))); 711 tree.type = erasure(tree.type); 712 } else { 713 tree.elems = translate(tree.elems, null); 714 } 715 716 result = tree; 717 } 718 visitParens(JCParens tree)719 public void visitParens(JCParens tree) { 720 tree.expr = translate(tree.expr, pt); 721 tree.type = erasure(tree.expr.type); 722 result = tree; 723 } 724 visitAssign(JCAssign tree)725 public void visitAssign(JCAssign tree) { 726 tree.lhs = translate(tree.lhs, null); 727 tree.rhs = translate(tree.rhs, erasure(tree.lhs.type)); 728 tree.type = erasure(tree.lhs.type); 729 result = retype(tree, tree.type, pt); 730 } 731 visitAssignop(JCAssignOp tree)732 public void visitAssignop(JCAssignOp tree) { 733 tree.lhs = translate(tree.lhs, null); 734 tree.rhs = translate(tree.rhs, tree.operator.type.getParameterTypes().tail.head); 735 tree.type = erasure(tree.type); 736 result = tree; 737 } 738 visitUnary(JCUnary tree)739 public void visitUnary(JCUnary tree) { 740 tree.arg = translate(tree.arg, (tree.getTag() == Tag.NULLCHK) 741 ? tree.type 742 : tree.operator.type.getParameterTypes().head); 743 result = tree; 744 } 745 visitBinary(JCBinary tree)746 public void visitBinary(JCBinary tree) { 747 tree.lhs = translate(tree.lhs, tree.operator.type.getParameterTypes().head); 748 tree.rhs = translate(tree.rhs, tree.operator.type.getParameterTypes().tail.head); 749 result = tree; 750 } 751 visitAnnotatedType(JCAnnotatedType tree)752 public void visitAnnotatedType(JCAnnotatedType tree) { 753 // For now, we need to keep the annotations in the tree because of the current 754 // MultiCatch implementation wrt type annotations 755 List<TypeCompound> mirrors = annotate.fromAnnotations(tree.annotations); 756 tree.underlyingType = translate(tree.underlyingType); 757 tree.type = tree.underlyingType.type.annotatedType(mirrors); 758 result = tree; 759 } 760 visitTypeCast(JCTypeCast tree)761 public void visitTypeCast(JCTypeCast tree) { 762 tree.clazz = translate(tree.clazz, null); 763 Type originalTarget = tree.type; 764 tree.type = erasure(tree.type); 765 JCExpression newExpression = translate(tree.expr, tree.type); 766 if (newExpression != tree.expr) { 767 JCTypeCast typeCast = newExpression.hasTag(Tag.TYPECAST) 768 ? (JCTypeCast) newExpression 769 : null; 770 tree.expr = typeCast != null && types.isSameType(typeCast.type, originalTarget) 771 ? typeCast.expr 772 : newExpression; 773 } 774 if (originalTarget.isIntersection()) { 775 Type.IntersectionClassType ict = (Type.IntersectionClassType)originalTarget; 776 for (Type c : ict.getExplicitComponents()) { 777 Type ec = erasure(c); 778 if (!types.isSameType(ec, tree.type)) { 779 tree.expr = coerce(tree.expr, ec); 780 } 781 } 782 } 783 result = retype(tree, tree.type, pt); 784 } 785 visitTypeTest(JCInstanceOf tree)786 public void visitTypeTest(JCInstanceOf tree) { 787 tree.expr = translate(tree.expr, null); 788 tree.pattern = translate(tree.pattern, null); 789 result = tree; 790 } 791 visitIndexed(JCArrayAccess tree)792 public void visitIndexed(JCArrayAccess tree) { 793 tree.indexed = translate(tree.indexed, erasure(tree.indexed.type)); 794 tree.index = translate(tree.index, syms.intType); 795 796 // Insert casts of indexed expressions as needed. 797 result = retype(tree, types.elemtype(tree.indexed.type), pt); 798 } 799 800 // There ought to be nothing to rewrite here; 801 // we don't generate code. visitAnnotation(JCAnnotation tree)802 public void visitAnnotation(JCAnnotation tree) { 803 result = tree; 804 } 805 visitIdent(JCIdent tree)806 public void visitIdent(JCIdent tree) { 807 Type et = tree.sym.erasure(types); 808 809 // Map type variables to their bounds. 810 if (tree.sym.kind == TYP && tree.sym.type.hasTag(TYPEVAR)) { 811 result = make.at(tree.pos).Type(et); 812 } else 813 // Map constants expressions to themselves. 814 if (tree.type.constValue() != null) { 815 result = tree; 816 } 817 // Insert casts of variable uses as needed. 818 else if (tree.sym.kind == VAR) { 819 result = retype(tree, et, pt); 820 } 821 else { 822 tree.type = erasure(tree.type); 823 result = tree; 824 } 825 } 826 visitSelect(JCFieldAccess tree)827 public void visitSelect(JCFieldAccess tree) { 828 Type t = types.skipTypeVars(tree.selected.type, false); 829 if (t.isCompound()) { 830 tree.selected = coerce( 831 translate(tree.selected, erasure(tree.selected.type)), 832 erasure(tree.sym.owner.type)); 833 } else 834 tree.selected = translate(tree.selected, erasure(t)); 835 836 // Map constants expressions to themselves. 837 if (tree.type.constValue() != null) { 838 result = tree; 839 } 840 // Insert casts of variable uses as needed. 841 else if (tree.sym.kind == VAR) { 842 result = retype(tree, tree.sym.erasure(types), pt); 843 } 844 else { 845 tree.type = erasure(tree.type); 846 result = tree; 847 } 848 } 849 visitReference(JCMemberReference tree)850 public void visitReference(JCMemberReference tree) { 851 Type t = types.skipTypeVars(tree.expr.type, false); 852 Type receiverTarget = t.isCompound() ? erasure(tree.sym.owner.type) : erasure(t); 853 if (tree.kind == ReferenceKind.UNBOUND) { 854 tree.expr = make.Type(receiverTarget); 855 } else { 856 tree.expr = translate(tree.expr, receiverTarget); 857 } 858 if (!tree.type.isIntersection()) { 859 tree.type = erasure(tree.type); 860 } else { 861 tree.type = types.erasure(types.findDescriptorSymbol(tree.type.tsym).owner.type); 862 } 863 if (tree.varargsElement != null) 864 tree.varargsElement = erasure(tree.varargsElement); 865 result = tree; 866 } 867 visitTypeArray(JCArrayTypeTree tree)868 public void visitTypeArray(JCArrayTypeTree tree) { 869 tree.elemtype = translate(tree.elemtype, null); 870 tree.type = erasure(tree.type); 871 result = tree; 872 } 873 874 /** Visitor method for parameterized types. 875 */ visitTypeApply(JCTypeApply tree)876 public void visitTypeApply(JCTypeApply tree) { 877 JCTree clazz = translate(tree.clazz, null); 878 result = clazz; 879 } 880 visitTypeIntersection(JCTypeIntersection tree)881 public void visitTypeIntersection(JCTypeIntersection tree) { 882 tree.bounds = translate(tree.bounds, null); 883 tree.type = erasure(tree.type); 884 result = tree; 885 } 886 887 /************************************************************************** 888 * utility methods 889 *************************************************************************/ 890 erasure(Type t)891 private Type erasure(Type t) { 892 return types.erasure(t); 893 } 894 895 /************************************************************************** 896 * main method 897 *************************************************************************/ 898 899 private Env<AttrContext> env; 900 901 private static final String statePreviousToFlowAssertMsg = 902 "The current compile state [%s] of class %s is previous to FLOW"; 903 translateClass(ClassSymbol c)904 void translateClass(ClassSymbol c) { 905 Type st = types.supertype(c.type); 906 // process superclass before derived 907 if (st.hasTag(CLASS)) { 908 translateClass((ClassSymbol)st.tsym); 909 } 910 911 Env<AttrContext> myEnv = enter.getEnv(c); 912 if (myEnv == null || (c.flags_field & TYPE_TRANSLATED) != 0) { 913 return; 914 } 915 c.flags_field |= TYPE_TRANSLATED; 916 917 /* The two assertions below are set for early detection of any attempt 918 * to translate a class that: 919 * 920 * 1) has no compile state being it the most outer class. 921 * We accept this condition for inner classes. 922 * 923 * 2) has a compile state which is previous to Flow state. 924 */ 925 boolean envHasCompState = compileStates.get(myEnv) != null; 926 if (!envHasCompState && c.outermostClass() == c) { 927 Assert.error("No info for outermost class: " + myEnv.enclClass.sym); 928 } 929 930 if (envHasCompState && 931 CompileState.FLOW.isAfter(compileStates.get(myEnv))) { 932 Assert.error(String.format(statePreviousToFlowAssertMsg, 933 compileStates.get(myEnv), myEnv.enclClass.sym)); 934 } 935 936 Env<AttrContext> oldEnv = env; 937 try { 938 env = myEnv; 939 // class has not been translated yet 940 941 TreeMaker savedMake = make; 942 Type savedPt = pt; 943 make = make.forToplevel(env.toplevel); 944 pt = null; 945 try { 946 JCClassDecl tree = (JCClassDecl) env.tree; 947 tree.typarams = List.nil(); 948 super.visitClassDef(tree); 949 make.at(tree.pos); 950 ListBuffer<JCTree> bridges = new ListBuffer<>(); 951 if (allowInterfaceBridges || (tree.sym.flags() & INTERFACE) == 0) { 952 addBridges(tree.pos(), c, bridges); 953 } 954 tree.defs = bridges.toList().prependList(tree.defs); 955 tree.type = erasure(tree.type); 956 } finally { 957 make = savedMake; 958 pt = savedPt; 959 } 960 } finally { 961 env = oldEnv; 962 } 963 } 964 965 /** Translate a toplevel class definition. 966 * @param cdef The definition to be translated. 967 */ translateTopLevelClass(JCTree cdef, TreeMaker make)968 public JCTree translateTopLevelClass(JCTree cdef, TreeMaker make) { 969 // note that this method does NOT support recursion. 970 this.make = make; 971 pt = null; 972 return translate(cdef, null); 973 } 974 } 975