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