1 /*
   2  * Copyright (c) 1999, 2018, 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. */
  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 
  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      */
 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 bridges The list buffer to which the bridge will be added
 240      */
 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 
 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      */
 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          */
 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          */
 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 
 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      */
 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      */
 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      */
 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 
 475     public void visitClassDef(JCClassDecl tree) {
 476         translateClass(tree.sym);
 477         result = tree;
 478     }
 479 
 480     Type returnType = null;
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 564     public void visitCase(JCCase tree) {
 565         tree.pats = translate(tree.pats, null);
 566         tree.stats = translate(tree.stats);
 567         result = tree;
 568     }
 569 
 570     public void visitSwitchExpression(JCSwitchExpression tree) {
 571         Type selsuper = types.supertype(tree.selector.type);
 572         boolean enumSwitch = selsuper != null &&
 573             selsuper.tsym == syms.enumSym;
 574         Type target = enumSwitch ? erasure(tree.selector.type) : syms.intType;
 575         tree.selector = translate(tree.selector, target);
 576         tree.cases = translate(tree.cases);
 577         tree.type = erasure(tree.type);
 578         result = retype(tree, tree.type, pt);
 579     }
 580 
 581     public void visitSynchronized(JCSynchronized tree) {
 582         tree.lock = translate(tree.lock, erasure(tree.lock.type));
 583         tree.body = translate(tree.body);
 584         result = tree;
 585     }
 586 
 587     public void visitTry(JCTry tree) {
 588         tree.resources = translate(tree.resources, syms.autoCloseableType);
 589         tree.body = translate(tree.body);
 590         tree.catchers = translateCatchers(tree.catchers);
 591         tree.finalizer = translate(tree.finalizer);
 592         result = tree;
 593     }
 594 
 595     public void visitConditional(JCConditional tree) {
 596         tree.cond = translate(tree.cond, syms.booleanType);
 597         tree.truepart = translate(tree.truepart, erasure(tree.type));
 598         tree.falsepart = translate(tree.falsepart, erasure(tree.type));
 599         tree.type = erasure(tree.type);
 600         result = retype(tree, tree.type, pt);
 601     }
 602 
 603    public void visitIf(JCIf tree) {
 604         tree.cond = translate(tree.cond, syms.booleanType);
 605         tree.thenpart = translate(tree.thenpart);
 606         tree.elsepart = translate(tree.elsepart);
 607         result = tree;
 608     }
 609 
 610     public void visitExec(JCExpressionStatement tree) {
 611         tree.expr = translate(tree.expr, null);
 612         result = tree;
 613     }
 614 
 615     public void visitReturn(JCReturn tree) {
 616         if (!returnType.hasTag(VOID))
 617             tree.expr = translate(tree.expr, returnType);
 618         result = tree;
 619     }
 620 
 621     @Override
 622     public void visitBreak(JCBreak tree) {
 623         if (tree.isValueBreak()) {
 624             tree.value = translate(tree.value, erasure(tree.value.type));
 625             tree.value.type = erasure(tree.value.type);
 626             tree.value = retype(tree.value, tree.value.type, pt);
 627         }
 628         result = tree;
 629     }
 630 
 631     public void visitThrow(JCThrow tree) {
 632         tree.expr = translate(tree.expr, erasure(tree.expr.type));
 633         result = tree;
 634     }
 635 
 636     public void visitAssert(JCAssert tree) {
 637         tree.cond = translate(tree.cond, syms.booleanType);
 638         if (tree.detail != null)
 639             tree.detail = translate(tree.detail, erasure(tree.detail.type));
 640         result = tree;
 641     }
 642 
 643     public void visitApply(JCMethodInvocation tree) {
 644         tree.meth = translate(tree.meth, null);
 645         Symbol meth = TreeInfo.symbol(tree.meth);
 646         Type mt = meth.erasure(types);
 647         boolean useInstantiatedPtArgs =
 648                 allowGraphInference && !types.isSignaturePolymorphic((MethodSymbol)meth.baseSymbol());
 649         List<Type> argtypes = useInstantiatedPtArgs ?
 650                 tree.meth.type.getParameterTypes() :
 651                 mt.getParameterTypes();
 652         if (meth.name == names.init && meth.owner == syms.enumSym)
 653             argtypes = argtypes.tail.tail;
 654         if (tree.varargsElement != null)
 655             tree.varargsElement = types.erasure(tree.varargsElement);
 656         else
 657             if (tree.args.length() != argtypes.length()) {
 658                 Assert.error(String.format("Incorrect number of arguments; expected %d, found %d",
 659                         tree.args.length(), argtypes.length()));
 660             }
 661         tree.args = translateArgs(tree.args, argtypes, tree.varargsElement);
 662 
 663         tree.type = types.erasure(tree.type);
 664         // Insert casts of method invocation results as needed.
 665         result = retype(tree, mt.getReturnType(), pt);
 666     }
 667 
 668     public void visitNewClass(JCNewClass tree) {
 669         if (tree.encl != null) {
 670             if (tree.def == null) {
 671                 tree.encl = translate(tree.encl, erasure(tree.encl.type));
 672             } else {
 673                 tree.args = tree.args.prepend(attr.makeNullCheck(tree.encl));
 674                 tree.encl = null;
 675             }
 676         }
 677 
 678         Type erasedConstructorType = tree.constructorType != null ?
 679                 erasure(tree.constructorType) :
 680                 null;
 681 
 682         List<Type> argtypes = erasedConstructorType != null && allowGraphInference ?
 683                 erasedConstructorType.getParameterTypes() :
 684                 tree.constructor.erasure(types).getParameterTypes();
 685 
 686         tree.clazz = translate(tree.clazz, null);
 687         if (tree.varargsElement != null)
 688             tree.varargsElement = types.erasure(tree.varargsElement);
 689         tree.args = translateArgs(
 690             tree.args, argtypes, tree.varargsElement);
 691         tree.def = translate(tree.def, null);
 692         if (erasedConstructorType != null)
 693             tree.constructorType = erasedConstructorType;
 694         tree.type = erasure(tree.type);
 695         result = tree;
 696     }
 697 
 698     public void visitNewArray(JCNewArray tree) {
 699         tree.elemtype = translate(tree.elemtype, null);
 700         translate(tree.dims, syms.intType);
 701         if (tree.type != null) {
 702             tree.elems = translate(tree.elems, erasure(types.elemtype(tree.type)));
 703             tree.type = erasure(tree.type);
 704         } else {
 705             tree.elems = translate(tree.elems, null);
 706         }
 707 
 708         result = tree;
 709     }
 710 
 711     public void visitParens(JCParens tree) {
 712         tree.expr = translate(tree.expr, pt);
 713         tree.type = erasure(tree.expr.type);
 714         result = tree;
 715     }
 716 
 717     public void visitAssign(JCAssign tree) {
 718         tree.lhs = translate(tree.lhs, null);
 719         tree.rhs = translate(tree.rhs, erasure(tree.lhs.type));
 720         tree.type = erasure(tree.lhs.type);
 721         result = retype(tree, tree.type, pt);
 722     }
 723 
 724     public void visitAssignop(JCAssignOp tree) {
 725         tree.lhs = translate(tree.lhs, null);
 726         tree.rhs = translate(tree.rhs, tree.operator.type.getParameterTypes().tail.head);
 727         tree.type = erasure(tree.type);
 728         result = tree;
 729     }
 730 
 731     public void visitUnary(JCUnary tree) {
 732         tree.arg = translate(tree.arg, (tree.getTag() == Tag.NULLCHK)
 733             ? tree.type
 734             : tree.operator.type.getParameterTypes().head);
 735         result = tree;
 736     }
 737 
 738     public void visitBinary(JCBinary tree) {
 739         tree.lhs = translate(tree.lhs, tree.operator.type.getParameterTypes().head);
 740         tree.rhs = translate(tree.rhs, tree.operator.type.getParameterTypes().tail.head);
 741         result = tree;
 742     }
 743 
 744     public void visitAnnotatedType(JCAnnotatedType tree) {
 745         // For now, we need to keep the annotations in the tree because of the current
 746         // MultiCatch implementation wrt type annotations
 747         List<TypeCompound> mirrors = annotate.fromAnnotations(tree.annotations);
 748         tree.underlyingType = translate(tree.underlyingType);
 749         tree.type = tree.underlyingType.type.annotatedType(mirrors);
 750         result = tree;
 751     }
 752 
 753     public void visitTypeCast(JCTypeCast tree) {
 754         tree.clazz = translate(tree.clazz, null);
 755         Type originalTarget = tree.type;
 756         tree.type = erasure(tree.type);
 757         JCExpression newExpression = translate(tree.expr, tree.type);
 758         if (newExpression != tree.expr) {
 759             JCTypeCast typeCast = newExpression.hasTag(Tag.TYPECAST)
 760                 ? (JCTypeCast) newExpression
 761                 : null;
 762             tree.expr = typeCast != null && types.isSameType(typeCast.type, originalTarget)
 763                 ? typeCast.expr
 764                 : newExpression;
 765         }
 766         if (originalTarget.isIntersection()) {
 767             Type.IntersectionClassType ict = (Type.IntersectionClassType)originalTarget;
 768             for (Type c : ict.getExplicitComponents()) {
 769                 Type ec = erasure(c);
 770                 if (!types.isSameType(ec, tree.type)) {
 771                     tree.expr = coerce(tree.expr, ec);
 772                 }
 773             }
 774         }
 775         result = tree;
 776     }
 777 
 778     public void visitTypeTest(JCInstanceOf tree) {
 779         tree.expr = translate(tree.expr, null);
 780         tree.clazz = translate(tree.clazz, null);
 781         result = tree;
 782     }
 783 
 784     public void visitIndexed(JCArrayAccess tree) {
 785         tree.indexed = translate(tree.indexed, erasure(tree.indexed.type));
 786         tree.index = translate(tree.index, syms.intType);
 787 
 788         // Insert casts of indexed expressions as needed.
 789         result = retype(tree, types.elemtype(tree.indexed.type), pt);
 790     }
 791 
 792     // There ought to be nothing to rewrite here;
 793     // we don't generate code.
 794     public void visitAnnotation(JCAnnotation tree) {
 795         result = tree;
 796     }
 797 
 798     public void visitIdent(JCIdent tree) {
 799         Type et = tree.sym.erasure(types);
 800 
 801         // Map type variables to their bounds.
 802         if (tree.sym.kind == TYP && tree.sym.type.hasTag(TYPEVAR)) {
 803             result = make.at(tree.pos).Type(et);
 804         } else
 805         // Map constants expressions to themselves.
 806         if (tree.type.constValue() != null) {
 807             result = tree;
 808         }
 809         // Insert casts of variable uses as needed.
 810         else if (tree.sym.kind == VAR) {
 811             result = retype(tree, et, pt);
 812         }
 813         else {
 814             tree.type = erasure(tree.type);
 815             result = tree;
 816         }
 817     }
 818 
 819     public void visitSelect(JCFieldAccess tree) {
 820         Type t = types.skipTypeVars(tree.selected.type, false);
 821         if (t.isCompound()) {
 822             tree.selected = coerce(
 823                 translate(tree.selected, erasure(tree.selected.type)),
 824                 erasure(tree.sym.owner.type));
 825         } else
 826             tree.selected = translate(tree.selected, erasure(t));
 827 
 828         // Map constants expressions to themselves.
 829         if (tree.type.constValue() != null) {
 830             result = tree;
 831         }
 832         // Insert casts of variable uses as needed.
 833         else if (tree.sym.kind == VAR) {
 834             result = retype(tree, tree.sym.erasure(types), pt);
 835         }
 836         else {
 837             tree.type = erasure(tree.type);
 838             result = tree;
 839         }
 840     }
 841 
 842     public void visitReference(JCMemberReference tree) {
 843         Type t = types.skipTypeVars(tree.expr.type, false);
 844         Type receiverTarget = t.isCompound() ? erasure(tree.sym.owner.type) : erasure(t);
 845         if (tree.kind == ReferenceKind.UNBOUND) {
 846             tree.expr = make.Type(receiverTarget);
 847         } else {
 848             tree.expr = translate(tree.expr, receiverTarget);
 849         }
 850         if (!tree.type.isIntersection()) {
 851             tree.type = erasure(tree.type);
 852         } else {
 853             tree.type = types.erasure(types.findDescriptorSymbol(tree.type.tsym).owner.type);
 854         }
 855         if (tree.varargsElement != null)
 856             tree.varargsElement = erasure(tree.varargsElement);
 857         result = tree;
 858     }
 859 
 860     public void visitTypeArray(JCArrayTypeTree tree) {
 861         tree.elemtype = translate(tree.elemtype, null);
 862         tree.type = erasure(tree.type);
 863         result = tree;
 864     }
 865 
 866     /** Visitor method for parameterized types.
 867      */
 868     public void visitTypeApply(JCTypeApply tree) {
 869         JCTree clazz = translate(tree.clazz, null);
 870         result = clazz;
 871     }
 872 
 873     public void visitTypeIntersection(JCTypeIntersection tree) {
 874         tree.bounds = translate(tree.bounds, null);
 875         tree.type = erasure(tree.type);
 876         result = tree;
 877     }
 878 
 879 /**************************************************************************
 880  * utility methods
 881  *************************************************************************/
 882 
 883     private Type erasure(Type t) {
 884         return types.erasure(t);
 885     }
 886 
 887 /**************************************************************************
 888  * main method
 889  *************************************************************************/
 890 
 891     private Env<AttrContext> env;
 892 
 893     private static final String statePreviousToFlowAssertMsg =
 894             "The current compile state [%s] of class %s is previous to FLOW";
 895 
 896     void translateClass(ClassSymbol c) {
 897         Type st = types.supertype(c.type);
 898         // process superclass before derived
 899         if (st.hasTag(CLASS)) {
 900             translateClass((ClassSymbol)st.tsym);
 901         }
 902 
 903         Env<AttrContext> myEnv = enter.getEnv(c);
 904         if (myEnv == null || (c.flags_field & TYPE_TRANSLATED) != 0) {
 905             return;
 906         }
 907         c.flags_field |= TYPE_TRANSLATED;
 908 
 909         /*  The two assertions below are set for early detection of any attempt
 910          *  to translate a class that:
 911          *
 912          *  1) has no compile state being it the most outer class.
 913          *     We accept this condition for inner classes.
 914          *
 915          *  2) has a compile state which is previous to Flow state.
 916          */
 917         boolean envHasCompState = compileStates.get(myEnv) != null;
 918         if (!envHasCompState && c.outermostClass() == c) {
 919             Assert.error("No info for outermost class: " + myEnv.enclClass.sym);
 920         }
 921 
 922         if (envHasCompState &&
 923                 CompileState.FLOW.isAfter(compileStates.get(myEnv))) {
 924             Assert.error(String.format(statePreviousToFlowAssertMsg,
 925                     compileStates.get(myEnv), myEnv.enclClass.sym));
 926         }
 927 
 928         Env<AttrContext> oldEnv = env;
 929         try {
 930             env = myEnv;
 931             // class has not been translated yet
 932 
 933             TreeMaker savedMake = make;
 934             Type savedPt = pt;
 935             make = make.forToplevel(env.toplevel);
 936             pt = null;
 937             try {
 938                 JCClassDecl tree = (JCClassDecl) env.tree;
 939                 tree.typarams = List.nil();
 940                 super.visitClassDef(tree);
 941                 make.at(tree.pos);
 942                 ListBuffer<JCTree> bridges = new ListBuffer<>();
 943                 if (allowInterfaceBridges || (tree.sym.flags() & INTERFACE) == 0) {
 944                     addBridges(tree.pos(), c, bridges);
 945                 }
 946                 tree.defs = bridges.toList().prependList(tree.defs);
 947                 tree.type = erasure(tree.type);
 948             } finally {
 949                 make = savedMake;
 950                 pt = savedPt;
 951             }
 952         } finally {
 953             env = oldEnv;
 954         }
 955     }
 956 
 957     /** Translate a toplevel class definition.
 958      *  @param cdef    The definition to be translated.
 959      */
 960     public JCTree translateTopLevelClass(JCTree cdef, TreeMaker make) {
 961         // note that this method does NOT support recursion.
 962         this.make = make;
 963         pt = null;
 964         return translate(cdef, null);
 965     }
 966 }