src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java

Tue, 12 Mar 2013 16:02:13 +0000

author
mcimadamore
date
Tue, 12 Mar 2013 16:02:13 +0000
changeset 1627
6db9a3b1a93f
parent 1624
d0ae21e3a382
child 1639
fbbf5376e7e4
permissions
-rw-r--r--

8008540: Constructor reference to non-reifiable array should be rejected
8008539: Spurious error when constructor reference mention an interface type
8008538: Constructor reference accepts wildcard parameterized types
Summary: Overhaul of Check.checkConstructorRefType
Reviewed-by: jjg

     1 /*
     2  * Copyright (c) 2010, 2013, 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 package com.sun.tools.javac.comp;
    27 import com.sun.tools.javac.tree.*;
    28 import com.sun.tools.javac.tree.JCTree;
    29 import com.sun.tools.javac.tree.JCTree.*;
    30 import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
    31 import com.sun.tools.javac.tree.TreeMaker;
    32 import com.sun.tools.javac.tree.TreeScanner;
    33 import com.sun.tools.javac.tree.TreeTranslator;
    34 import com.sun.tools.javac.code.Kinds;
    35 import com.sun.tools.javac.code.Scope;
    36 import com.sun.tools.javac.code.Symbol;
    37 import com.sun.tools.javac.code.Symbol.ClassSymbol;
    38 import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol;
    39 import com.sun.tools.javac.code.Symbol.MethodSymbol;
    40 import com.sun.tools.javac.code.Symbol.VarSymbol;
    41 import com.sun.tools.javac.code.Symtab;
    42 import com.sun.tools.javac.code.Type;
    43 import com.sun.tools.javac.code.Type.ClassType;
    44 import com.sun.tools.javac.code.Type.MethodType;
    45 import com.sun.tools.javac.code.Types;
    46 import com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzer.*;
    47 import com.sun.tools.javac.comp.Lower.BasicFreeVarCollector;
    48 import com.sun.tools.javac.jvm.*;
    49 import com.sun.tools.javac.util.*;
    50 import com.sun.tools.javac.util.List;
    51 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    52 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
    54 import java.util.HashMap;
    55 import java.util.LinkedHashMap;
    56 import java.util.Map;
    58 import static com.sun.tools.javac.comp.LambdaToMethod.LambdaSymbolKind.*;
    59 import static com.sun.tools.javac.code.Flags.*;
    60 import static com.sun.tools.javac.code.Kinds.*;
    61 import static com.sun.tools.javac.code.TypeTag.*;
    62 import static com.sun.tools.javac.tree.JCTree.Tag.*;
    64 /**
    65  * This pass desugars lambda expressions into static methods
    66  *
    67  *  <p><b>This is NOT part of any supported API.
    68  *  If you write code that depends on this, you do so at your own risk.
    69  *  This code and its internal interfaces are subject to change or
    70  *  deletion without notice.</b>
    71  */
    72 public class LambdaToMethod extends TreeTranslator {
    74     private Lower lower;
    75     private Names names;
    76     private Symtab syms;
    77     private Resolve rs;
    78     private TreeMaker make;
    79     private Types types;
    80     private TransTypes transTypes;
    81     private Env<AttrContext> attrEnv;
    83     /** the analyzer scanner */
    84     private LambdaAnalyzer analyzer;
    86     /** map from lambda trees to translation contexts */
    87     private Map<JCTree, TranslationContext<?>> contextMap;
    89     /** current translation context (visitor argument) */
    90     private TranslationContext<?> context;
    92     /** info about the current class being processed */
    93     private KlassInfo kInfo;
    95     /** Flag for alternate metafactories indicating the lambda object is intended to be serializable */
    96     public static final int FLAG_SERIALIZABLE = 1 << 0;
    98     /** Flag for alternate metafactories indicating the lambda object has multiple targets */
    99     public static final int FLAG_MARKERS = 1 << 1;
   101     private class KlassInfo {
   103         /**
   104          * list of methods to append
   105          */
   106         private ListBuffer<JCTree> appendedMethodList;
   108         /**
   109          * list of deserialization cases
   110          */
   111         private final Map<String, ListBuffer<JCStatement>> deserializeCases;
   113        /**
   114          * deserialize method symbol
   115          */
   116         private final MethodSymbol deserMethodSym;
   118         /**
   119          * deserialize method parameter symbol
   120          */
   121         private final VarSymbol deserParamSym;
   123         private KlassInfo(Symbol kSym) {
   124             appendedMethodList = ListBuffer.lb();
   125             deserializeCases = new HashMap<String, ListBuffer<JCStatement>>();
   126             long flags = PRIVATE | STATIC | SYNTHETIC;
   127             MethodType type = new MethodType(List.of(syms.serializedLambdaType), syms.objectType,
   128                     List.<Type>nil(), syms.methodClass);
   129             deserMethodSym = makeSyntheticMethod(flags, names.deserializeLambda, type, kSym);
   130             deserParamSym = new VarSymbol(FINAL, names.fromString("lambda"),
   131                     syms.serializedLambdaType, deserMethodSym);
   132         }
   134         private void addMethod(JCTree decl) {
   135             appendedMethodList = appendedMethodList.prepend(decl);
   136         }
   137     }
   139     // <editor-fold defaultstate="collapsed" desc="Instantiating">
   140     private static final Context.Key<LambdaToMethod> unlambdaKey =
   141             new Context.Key<LambdaToMethod>();
   143     public static LambdaToMethod instance(Context context) {
   144         LambdaToMethod instance = context.get(unlambdaKey);
   145         if (instance == null) {
   146             instance = new LambdaToMethod(context);
   147         }
   148         return instance;
   149     }
   151     private LambdaToMethod(Context context) {
   152         lower = Lower.instance(context);
   153         names = Names.instance(context);
   154         syms = Symtab.instance(context);
   155         rs = Resolve.instance(context);
   156         make = TreeMaker.instance(context);
   157         types = Types.instance(context);
   158         transTypes = TransTypes.instance(context);
   159         analyzer = new LambdaAnalyzer();
   160     }
   161     // </editor-fold>
   163     // <editor-fold defaultstate="collapsed" desc="translate methods">
   164     @Override
   165     public <T extends JCTree> T translate(T tree) {
   166         TranslationContext<?> newContext = contextMap.get(tree);
   167         return translate(tree, newContext != null ? newContext : context);
   168     }
   170     public <T extends JCTree> T translate(T tree, TranslationContext<?> newContext) {
   171         TranslationContext<?> prevContext = context;
   172         try {
   173             context = newContext;
   174             return super.translate(tree);
   175         }
   176         finally {
   177             context = prevContext;
   178         }
   179     }
   181     public <T extends JCTree> List<T> translate(List<T> trees, TranslationContext<?> newContext) {
   182         ListBuffer<T> buf = ListBuffer.lb();
   183         for (T tree : trees) {
   184             buf.append(translate(tree, newContext));
   185         }
   186         return buf.toList();
   187     }
   189     public JCTree translateTopLevelClass(Env<AttrContext> env, JCTree cdef, TreeMaker make) {
   190         this.make = make;
   191         this.attrEnv = env;
   192         this.context = null;
   193         this.contextMap = new HashMap<JCTree, TranslationContext<?>>();
   194         return translate(cdef);
   195     }
   196     // </editor-fold>
   198     // <editor-fold defaultstate="collapsed" desc="visitor methods">
   199     /**
   200      * Visit a class.
   201      * Maintain the translatedMethodList across nested classes.
   202      * Append the translatedMethodList to the class after it is translated.
   203      * @param tree
   204      */
   205     @Override
   206     public void visitClassDef(JCClassDecl tree) {
   207         if (tree.sym.owner.kind == PCK) {
   208             //analyze class
   209             analyzer.analyzeClass(tree);
   210         }
   211         KlassInfo prevKlassInfo = kInfo;
   212         try {
   213             kInfo = new KlassInfo(tree.sym);
   214             super.visitClassDef(tree);
   215             if (!kInfo.deserializeCases.isEmpty()) {
   216                 kInfo.addMethod(makeDeserializeMethod(tree.sym));
   217             }
   218             //add all translated instance methods here
   219             List<JCTree> newMethods = kInfo.appendedMethodList.toList();
   220             tree.defs = tree.defs.appendList(newMethods);
   221             for (JCTree lambda : newMethods) {
   222                 tree.sym.members().enter(((JCMethodDecl)lambda).sym);
   223             }
   224             result = tree;
   225         } finally {
   226             kInfo = prevKlassInfo;
   227         }
   228     }
   230     /**
   231      * Translate a lambda into a method to be inserted into the class.
   232      * Then replace the lambda site with an invokedynamic call of to lambda
   233      * meta-factory, which will use the lambda method.
   234      * @param tree
   235      */
   236     @Override
   237     public void visitLambda(JCLambda tree) {
   238         LambdaTranslationContext localContext = (LambdaTranslationContext)context;
   239         MethodSymbol sym = (MethodSymbol)localContext.translatedSym;
   240         MethodType lambdaType = (MethodType) sym.type;
   242         //create the method declaration hoisting the lambda body
   243         JCMethodDecl lambdaDecl = make.MethodDef(make.Modifiers(sym.flags_field),
   244                 sym.name,
   245                 make.QualIdent(lambdaType.getReturnType().tsym),
   246                 List.<JCTypeParameter>nil(),
   247                 localContext.syntheticParams,
   248                 lambdaType.getThrownTypes() == null ?
   249                     List.<JCExpression>nil() :
   250                     make.Types(lambdaType.getThrownTypes()),
   251                 null,
   252                 null);
   253         lambdaDecl.sym = sym;
   254         lambdaDecl.type = lambdaType;
   256         //translate lambda body
   257         //As the lambda body is translated, all references to lambda locals,
   258         //captured variables, enclosing members are adjusted accordingly
   259         //to refer to the static method parameters (rather than i.e. acessing to
   260         //captured members directly).
   261         lambdaDecl.body = translate(makeLambdaBody(tree, lambdaDecl));
   263         //Add the method to the list of methods to be added to this class.
   264         kInfo.addMethod(lambdaDecl);
   266         //now that we have generated a method for the lambda expression,
   267         //we can translate the lambda into a method reference pointing to the newly
   268         //created method.
   269         //
   270         //Note that we need to adjust the method handle so that it will match the
   271         //signature of the SAM descriptor - this means that the method reference
   272         //should be added the following synthetic arguments:
   273         //
   274         // * the "this" argument if it is an instance method
   275         // * enclosing locals captured by the lambda expression
   277         ListBuffer<JCExpression> syntheticInits = ListBuffer.lb();
   279         if (!sym.isStatic()) {
   280             syntheticInits.append(makeThis(
   281                     sym.owner.enclClass().asType(),
   282                     localContext.owner.enclClass()));
   283         }
   285         //add captured locals
   286         for (Symbol fv : localContext.getSymbolMap(CAPTURED_VAR).keySet()) {
   287             if (fv != localContext.self) {
   288                 JCTree captured_local = make.Ident(fv).setType(fv.type);
   289                 syntheticInits.append((JCExpression) captured_local);
   290             }
   291         }
   293         //then, determine the arguments to the indy call
   294         List<JCExpression> indy_args = translate(syntheticInits.toList(), localContext.prev);
   296         //build a sam instance using an indy call to the meta-factory
   297         int refKind = referenceKind(sym);
   299         //convert to an invokedynamic call
   300         result = makeMetaFactoryIndyCall(tree, context.needsAltMetafactory(), context.isSerializable(), refKind, sym, indy_args);
   301     }
   303     private JCIdent makeThis(Type type, Symbol owner) {
   304         VarSymbol _this = new VarSymbol(PARAMETER | FINAL | SYNTHETIC,
   305                 names._this,
   306                 type,
   307                 owner);
   308         return make.Ident(_this);
   309     }
   311     /**
   312      * Translate a method reference into an invokedynamic call to the
   313      * meta-factory.
   314      * @param tree
   315      */
   316     @Override
   317     public void visitReference(JCMemberReference tree) {
   318         ReferenceTranslationContext localContext = (ReferenceTranslationContext)context;
   320         //first determine the method symbol to be used to generate the sam instance
   321         //this is either the method reference symbol, or the bridged reference symbol
   322         Symbol refSym = localContext.needsBridge() ?
   323             localContext.bridgeSym :
   324             tree.sym;
   326         //build the bridge method, if needed
   327         if (localContext.needsBridge()) {
   328             bridgeMemberReference(tree, localContext);
   329         }
   331         //the qualifying expression is treated as a special captured arg
   332         JCExpression init;
   333         switch(tree.kind) {
   335             case IMPLICIT_INNER:    /** Inner :: new */
   336             case SUPER:             /** super :: instMethod */
   337                 init = makeThis(
   338                     localContext.owner.enclClass().asType(),
   339                     localContext.owner.enclClass());
   340                 break;
   342             case BOUND:             /** Expr :: instMethod */
   343                 init = tree.getQualifierExpression();
   344                 break;
   346             case UNBOUND:           /** Type :: instMethod */
   347             case STATIC:            /** Type :: staticMethod */
   348             case TOPLEVEL:          /** Top level :: new */
   349             case ARRAY_CTOR:        /** ArrayType :: new */
   350                 init = null;
   351                 break;
   353             default:
   354                 throw new InternalError("Should not have an invalid kind");
   355         }
   357         List<JCExpression> indy_args = init==null? List.<JCExpression>nil() : translate(List.of(init), localContext.prev);
   360         //build a sam instance using an indy call to the meta-factory
   361         result = makeMetaFactoryIndyCall(tree, localContext.needsAltMetafactory(), localContext.isSerializable(), localContext.referenceKind(), refSym, indy_args);
   362     }
   364     /**
   365      * Translate identifiers within a lambda to the mapped identifier
   366      * @param tree
   367      */
   368     @Override
   369     public void visitIdent(JCIdent tree) {
   370         if (context == null || !analyzer.lambdaIdentSymbolFilter(tree.sym)) {
   371             super.visitIdent(tree);
   372         } else {
   373             LambdaTranslationContext lambdaContext = (LambdaTranslationContext) context;
   374             if (lambdaContext.getSymbolMap(PARAM).containsKey(tree.sym)) {
   375                 Symbol translatedSym = lambdaContext.getSymbolMap(PARAM).get(tree.sym);
   376                 result = make.Ident(translatedSym).setType(tree.type);
   377             } else if (lambdaContext.getSymbolMap(LOCAL_VAR).containsKey(tree.sym)) {
   378                 Symbol translatedSym = lambdaContext.getSymbolMap(LOCAL_VAR).get(tree.sym);
   379                 result = make.Ident(translatedSym).setType(tree.type);
   380             } else if (lambdaContext.getSymbolMap(TYPE_VAR).containsKey(tree.sym)) {
   381                 Symbol translatedSym = lambdaContext.getSymbolMap(TYPE_VAR).get(tree.sym);
   382                 result = make.Ident(translatedSym).setType(translatedSym.type);
   383             } else if (lambdaContext.getSymbolMap(CAPTURED_VAR).containsKey(tree.sym)) {
   384                 Symbol translatedSym = lambdaContext.getSymbolMap(CAPTURED_VAR).get(tree.sym);
   385                 result = make.Ident(translatedSym).setType(tree.type);
   386             } else {
   387                 if (tree.sym.owner.kind == Kinds.TYP) {
   388                     for (Map.Entry<Symbol, Symbol> encl_entry : lambdaContext.getSymbolMap(CAPTURED_THIS).entrySet()) {
   389                         if (tree.sym.isMemberOf((ClassSymbol) encl_entry.getKey(), types)) {
   390                             JCExpression enclRef = make.Ident(encl_entry.getValue());
   391                             result = tree.sym.name == names._this
   392                                     ? enclRef.setType(tree.type)
   393                                     : make.Select(enclRef, tree.sym).setType(tree.type);
   394                             result = tree;
   395                             return;
   396                         }
   397                     }
   398                 }
   399                 //access to untranslated symbols (i.e. compile-time constants,
   400                 //members defined inside the lambda body, etc.) )
   401                 super.visitIdent(tree);
   402             }
   403         }
   404     }
   406     @Override
   407     public void visitVarDef(JCVariableDecl tree) {
   408         LambdaTranslationContext lambdaContext = (LambdaTranslationContext)context;
   409         if (context != null && lambdaContext.getSymbolMap(LOCAL_VAR).containsKey(tree.sym)) {
   410             JCExpression init = translate(tree.init);
   411             result = make.VarDef((VarSymbol)lambdaContext.getSymbolMap(LOCAL_VAR).get(tree.sym), init);
   412         } else if (context != null && lambdaContext.getSymbolMap(TYPE_VAR).containsKey(tree.sym)) {
   413             JCExpression init = translate(tree.init);
   414             VarSymbol xsym = (VarSymbol)lambdaContext.getSymbolMap(TYPE_VAR).get(tree.sym);
   415             result = make.VarDef(xsym, init);
   416             // Replace the entered symbol for this variable
   417             Scope sc = tree.sym.owner.members();
   418             if (sc != null) {
   419                 sc.remove(tree.sym);
   420                 sc.enter(xsym);
   421             }
   422         } else {
   423             super.visitVarDef(tree);
   424         }
   425     }
   427     // </editor-fold>
   429     // <editor-fold defaultstate="collapsed" desc="Translation helper methods">
   431     private JCBlock makeLambdaBody(JCLambda tree, JCMethodDecl lambdaMethodDecl) {
   432         return tree.getBodyKind() == JCLambda.BodyKind.EXPRESSION ?
   433                 makeLambdaExpressionBody((JCExpression)tree.body, lambdaMethodDecl) :
   434                 makeLambdaStatementBody((JCBlock)tree.body, lambdaMethodDecl, tree.canCompleteNormally);
   435     }
   437     private JCBlock makeLambdaExpressionBody(JCExpression expr, JCMethodDecl lambdaMethodDecl) {
   438         Type restype = lambdaMethodDecl.type.getReturnType();
   439         boolean isLambda_void = expr.type.hasTag(VOID);
   440         boolean isTarget_void = restype.hasTag(VOID);
   441         boolean isTarget_Void = types.isSameType(restype, types.boxedClass(syms.voidType).type);
   442         if (isTarget_void) {
   443             //target is void:
   444             // BODY;
   445             JCStatement stat = make.Exec(expr);
   446             return make.Block(0, List.<JCStatement>of(stat));
   447         } else if (isLambda_void && isTarget_Void) {
   448             //void to Void conversion:
   449             // BODY; return null;
   450             ListBuffer<JCStatement> stats = ListBuffer.lb();
   451             stats.append(make.Exec(expr));
   452             stats.append(make.Return(make.Literal(BOT, null).setType(syms.botType)));
   453             return make.Block(0, stats.toList());
   454         } else {
   455             //non-void to non-void conversion:
   456             // return (TYPE)BODY;
   457             JCExpression retExpr = transTypes.coerce(attrEnv, expr, restype);
   458             return make.Block(0, List.<JCStatement>of(make.Return(retExpr)));
   459         }
   460     }
   462     private JCBlock makeLambdaStatementBody(JCBlock block, final JCMethodDecl lambdaMethodDecl, boolean completeNormally) {
   463         final Type restype = lambdaMethodDecl.type.getReturnType();
   464         final boolean isTarget_void = restype.hasTag(VOID);
   465         boolean isTarget_Void = types.isSameType(restype, types.boxedClass(syms.voidType).type);
   467         class LambdaBodyTranslator extends TreeTranslator {
   469             @Override
   470             public void visitClassDef(JCClassDecl tree) {
   471                 //do NOT recurse on any inner classes
   472                 result = tree;
   473             }
   475             @Override
   476             public void visitLambda(JCLambda tree) {
   477                 //do NOT recurse on any nested lambdas
   478                 result = tree;
   479             }
   481             @Override
   482             public void visitReturn(JCReturn tree) {
   483                 boolean isLambda_void = tree.expr == null;
   484                 if (isTarget_void && !isLambda_void) {
   485                     //Void to void conversion:
   486                     // { TYPE $loc = RET-EXPR; return; }
   487                     VarSymbol loc = makeSyntheticVar(0, names.fromString("$loc"), tree.expr.type, lambdaMethodDecl.sym);
   488                     JCVariableDecl varDef = make.VarDef(loc, tree.expr);
   489                     result = make.Block(0, List.<JCStatement>of(varDef, make.Return(null)));
   490                 } else if (!isTarget_void || !isLambda_void) {
   491                     //non-void to non-void conversion:
   492                     // return (TYPE)RET-EXPR;
   493                     tree.expr = transTypes.coerce(attrEnv, tree.expr, restype);
   494                     result = tree;
   495                 } else {
   496                     result = tree;
   497                 }
   499             }
   500         }
   502         JCBlock trans_block = new LambdaBodyTranslator().translate(block);
   503         if (completeNormally && isTarget_Void) {
   504             //there's no return statement and the lambda (possibly inferred)
   505             //return type is java.lang.Void; emit a synthetic return statement
   506             trans_block.stats = trans_block.stats.append(make.Return(make.Literal(BOT, null).setType(syms.botType)));
   507         }
   508         return trans_block;
   509     }
   511     private JCMethodDecl makeDeserializeMethod(Symbol kSym) {
   512         ListBuffer<JCCase> cases = ListBuffer.lb();
   513         ListBuffer<JCBreak> breaks = ListBuffer.lb();
   514         for (Map.Entry<String, ListBuffer<JCStatement>> entry : kInfo.deserializeCases.entrySet()) {
   515             JCBreak br = make.Break(null);
   516             breaks.add(br);
   517             List<JCStatement> stmts = entry.getValue().append(br).toList();
   518             cases.add(make.Case(make.Literal(entry.getKey()), stmts));
   519         }
   520         JCSwitch sw = make.Switch(deserGetter("getImplMethodName", syms.stringType), cases.toList());
   521         for (JCBreak br : breaks) {
   522             br.target = sw;
   523         }
   524         JCBlock body = make.Block(0L, List.<JCStatement>of(
   525                 sw,
   526                 make.Throw(makeNewClass(
   527                     syms.illegalArgumentExceptionType,
   528                     List.<JCExpression>of(make.Literal("Invalid lambda deserialization"))))));
   529         JCMethodDecl deser = make.MethodDef(make.Modifiers(kInfo.deserMethodSym.flags()),
   530                         names.deserializeLambda,
   531                         make.QualIdent(kInfo.deserMethodSym.getReturnType().tsym),
   532                         List.<JCTypeParameter>nil(),
   533                         List.of(make.VarDef(kInfo.deserParamSym, null)),
   534                         List.<JCExpression>nil(),
   535                         body,
   536                         null);
   537         deser.sym = kInfo.deserMethodSym;
   538         deser.type = kInfo.deserMethodSym.type;
   539         //System.err.printf("DESER: '%s'\n", deser);
   540         return deser;
   541     }
   543     /** Make an attributed class instance creation expression.
   544      *  @param ctype    The class type.
   545      *  @param args     The constructor arguments.
   546      */
   547     JCNewClass makeNewClass(Type ctype, List<JCExpression> args) {
   548         JCNewClass tree = make.NewClass(null,
   549             null, make.QualIdent(ctype.tsym), args, null);
   550         tree.constructor = rs.resolveConstructor(
   551             null, attrEnv, ctype, TreeInfo.types(args), List.<Type>nil());
   552         tree.type = ctype;
   553         return tree;
   554     }
   556     private void addDeserializationCase(int implMethodKind, Symbol refSym, Type targetType, MethodSymbol samSym,
   557             DiagnosticPosition pos, List<Object> staticArgs, MethodType indyType) {
   558         String functionalInterfaceClass = classSig(targetType);
   559         String functionalInterfaceMethodName = samSym.getSimpleName().toString();
   560         String functionalInterfaceMethodSignature = methodSig(types.erasure(samSym.type));
   561         String implClass = classSig(types.erasure(refSym.owner.type));
   562         String implMethodName = refSym.getQualifiedName().toString();
   563         String implMethodSignature = methodSig(types.erasure(refSym.type));
   565         JCExpression kindTest = eqTest(syms.intType, deserGetter("getImplMethodKind", syms.intType), make.Literal(implMethodKind));
   566         ListBuffer<JCExpression> serArgs = ListBuffer.lb();
   567         int i = 0;
   568         for (Type t : indyType.getParameterTypes()) {
   569             List<JCExpression> indexAsArg = ListBuffer.<JCExpression>lb().append(make.Literal(i)).toList();
   570             List<Type> argTypes = ListBuffer.<Type>lb().append(syms.intType).toList();
   571             serArgs.add(make.TypeCast(types.erasure(t), deserGetter("getCapturedArg", syms.objectType, argTypes, indexAsArg)));
   572             ++i;
   573         }
   574         JCStatement stmt = make.If(
   575                 deserTest(deserTest(deserTest(deserTest(deserTest(
   576                     kindTest,
   577                     "getFunctionalInterfaceClass", functionalInterfaceClass),
   578                     "getFunctionalInterfaceMethodName", functionalInterfaceMethodName),
   579                     "getFunctionalInterfaceMethodSignature", functionalInterfaceMethodSignature),
   580                     "getImplClass", implClass),
   581                     "getImplMethodSignature", implMethodSignature),
   582                 make.Return(makeIndyCall(
   583                     pos,
   584                     syms.lambdaMetafactory,
   585                     names.altMetaFactory,
   586                     staticArgs, indyType, serArgs.toList())),
   587                 null);
   588         ListBuffer<JCStatement> stmts = kInfo.deserializeCases.get(implMethodName);
   589         if (stmts == null) {
   590             stmts = ListBuffer.lb();
   591             kInfo.deserializeCases.put(implMethodName, stmts);
   592         }
   593         /****
   594         System.err.printf("+++++++++++++++++\n");
   595         System.err.printf("*functionalInterfaceClass: '%s'\n", functionalInterfaceClass);
   596         System.err.printf("*functionalInterfaceMethodName: '%s'\n", functionalInterfaceMethodName);
   597         System.err.printf("*functionalInterfaceMethodSignature: '%s'\n", functionalInterfaceMethodSignature);
   598         System.err.printf("*implMethodKind: %d\n", implMethodKind);
   599         System.err.printf("*implClass: '%s'\n", implClass);
   600         System.err.printf("*implMethodName: '%s'\n", implMethodName);
   601         System.err.printf("*implMethodSignature: '%s'\n", implMethodSignature);
   602         ****/
   603         stmts.append(stmt);
   604     }
   606     private JCExpression eqTest(Type argType, JCExpression arg1, JCExpression arg2) {
   607         JCBinary testExpr = make.Binary(JCTree.Tag.EQ, arg1, arg2);
   608         testExpr.operator = rs.resolveBinaryOperator(null, JCTree.Tag.EQ, attrEnv, argType, argType);
   609         testExpr.setType(syms.booleanType);
   610         return testExpr;
   611     }
   613     private JCExpression deserTest(JCExpression prev, String func, String lit) {
   614         MethodType eqmt = new MethodType(List.of(syms.objectType), syms.booleanType, List.<Type>nil(), syms.methodClass);
   615         Symbol eqsym = rs.resolveQualifiedMethod(null, attrEnv, syms.objectType, names.equals, List.of(syms.objectType), List.<Type>nil());
   616         JCMethodInvocation eqtest = make.Apply(
   617                 List.<JCExpression>nil(),
   618                 make.Select(deserGetter(func, syms.stringType), eqsym).setType(eqmt),
   619                 List.<JCExpression>of(make.Literal(lit)));
   620         eqtest.setType(syms.booleanType);
   621         JCBinary compound = make.Binary(JCTree.Tag.AND, prev, eqtest);
   622         compound.operator = rs.resolveBinaryOperator(null, JCTree.Tag.AND, attrEnv, syms.booleanType, syms.booleanType);
   623         compound.setType(syms.booleanType);
   624         return compound;
   625     }
   627     private JCExpression deserGetter(String func, Type type) {
   628         return deserGetter(func, type, List.<Type>nil(), List.<JCExpression>nil());
   629     }
   631     private JCExpression deserGetter(String func, Type type, List<Type> argTypes, List<JCExpression> args) {
   632         MethodType getmt = new MethodType(argTypes, type, List.<Type>nil(), syms.methodClass);
   633         Symbol getsym = rs.resolveQualifiedMethod(null, attrEnv, syms.serializedLambdaType, names.fromString(func), argTypes, List.<Type>nil());
   634         return make.Apply(
   635                     List.<JCExpression>nil(),
   636                     make.Select(make.Ident(kInfo.deserParamSym).setType(syms.serializedLambdaType), getsym).setType(getmt),
   637                     args).setType(type);
   638     }
   640     /**
   641      * Create new synthetic method with given flags, name, type, owner
   642      */
   643     private MethodSymbol makeSyntheticMethod(long flags, Name name, Type type, Symbol owner) {
   644         return new MethodSymbol(flags | SYNTHETIC, name, type, owner);
   645     }
   647     /**
   648      * Create new synthetic variable with given flags, name, type, owner
   649      */
   650     private VarSymbol makeSyntheticVar(long flags, String name, Type type, Symbol owner) {
   651         return makeSyntheticVar(flags, names.fromString(name), type, owner);
   652     }
   654     /**
   655      * Create new synthetic variable with given flags, name, type, owner
   656      */
   657     private VarSymbol makeSyntheticVar(long flags, Name name, Type type, Symbol owner) {
   658         return new VarSymbol(flags | SYNTHETIC, name, type, owner);
   659     }
   661     /**
   662      * Set varargsElement field on a given tree (must be either a new class tree
   663      * or a method call tree)
   664      */
   665     private void setVarargsIfNeeded(JCTree tree, Type varargsElement) {
   666         if (varargsElement != null) {
   667             switch (tree.getTag()) {
   668                 case APPLY: ((JCMethodInvocation)tree).varargsElement = varargsElement; break;
   669                 case NEWCLASS: ((JCNewClass)tree).varargsElement = varargsElement; break;
   670                 default: throw new AssertionError();
   671             }
   672         }
   673     }
   675     /**
   676      * Convert method/constructor arguments by inserting appropriate cast
   677      * as required by type-erasure - this is needed when bridging a lambda/method
   678      * reference, as the bridged signature might require downcast to be compatible
   679      * with the generated signature.
   680      */
   681     private List<JCExpression> convertArgs(Symbol meth, List<JCExpression> args, Type varargsElement) {
   682        Assert.check(meth.kind == Kinds.MTH);
   683        List<Type> formals = types.erasure(meth.type).getParameterTypes();
   684        if (varargsElement != null) {
   685            Assert.check((meth.flags() & VARARGS) != 0);
   686        }
   687        return transTypes.translateArgs(args, formals, varargsElement, attrEnv);
   688     }
   690     // </editor-fold>
   692     /**
   693      * Generate an adapter method "bridge" for a method reference which cannot
   694      * be used directly.
   695      */
   696     private class MemberReferenceBridger {
   698         private final JCMemberReference tree;
   699         private final ReferenceTranslationContext localContext;
   700         private final ListBuffer<JCExpression> args = ListBuffer.lb();
   701         private final ListBuffer<JCVariableDecl> params = ListBuffer.lb();
   703         MemberReferenceBridger(JCMemberReference tree, ReferenceTranslationContext localContext) {
   704             this.tree = tree;
   705             this.localContext = localContext;
   706         }
   708         /**
   709          * Generate the bridge
   710          */
   711         JCMethodDecl bridge() {
   712             int prevPos = make.pos;
   713             try {
   714                 make.at(tree);
   715                 Type samDesc = localContext.bridgedRefSig();
   716                 List<Type> samPTypes = samDesc.getParameterTypes();
   718                 //an extra argument is prepended to the signature of the bridge in case
   719                 //the member reference is an instance method reference (in which case
   720                 //the receiver expression is passed to the bridge itself).
   721                 Type recType = null;
   722                 switch (tree.kind) {
   723                     case IMPLICIT_INNER:
   724                         recType = tree.sym.owner.type.getEnclosingType();
   725                         break;
   726                     case BOUND:
   727                         recType = tree.getQualifierExpression().type;
   728                         break;
   729                     case UNBOUND:
   730                         recType = samPTypes.head;
   731                         samPTypes = samPTypes.tail;
   732                         break;
   733                 }
   735                 //generate the parameter list for the bridged member reference - the
   736                 //bridge signature will match the signature of the target sam descriptor
   738                 VarSymbol rcvr = (recType == null)
   739                         ? null
   740                         : addParameter("rec$", recType, false);
   742                 List<Type> refPTypes = tree.sym.type.getParameterTypes();
   743                 int refSize = refPTypes.size();
   744                 int samSize = samPTypes.size();
   745                 // Last parameter to copy from referenced method
   746                 int last = localContext.needsVarArgsConversion() ? refSize - 1 : refSize;
   748                 List<Type> l = refPTypes;
   749                 // Use parameter types of the referenced method, excluding final var args
   750                 for (int i = 0; l.nonEmpty() && i < last; ++i) {
   751                     addParameter("x$" + i, l.head, true);
   752                     l = l.tail;
   753                 }
   754                 // Flatten out the var args
   755                 for (int i = last; i < samSize; ++i) {
   756                     addParameter("xva$" + i, tree.varargsElement, true);
   757                 }
   759                 //generate the bridge method declaration
   760                 JCMethodDecl bridgeDecl = make.MethodDef(make.Modifiers(localContext.bridgeSym.flags()),
   761                         localContext.bridgeSym.name,
   762                         make.QualIdent(samDesc.getReturnType().tsym),
   763                         List.<JCTypeParameter>nil(),
   764                         params.toList(),
   765                         tree.sym.type.getThrownTypes() == null
   766                         ? List.<JCExpression>nil()
   767                         : make.Types(tree.sym.type.getThrownTypes()),
   768                         null,
   769                         null);
   770                 bridgeDecl.sym = (MethodSymbol) localContext.bridgeSym;
   771                 bridgeDecl.type = localContext.bridgeSym.type =
   772                         types.createMethodTypeWithParameters(samDesc, TreeInfo.types(params.toList()));
   774                 //bridge method body generation - this can be either a method call or a
   775                 //new instance creation expression, depending on the member reference kind
   776                 JCExpression bridgeExpr = (tree.getMode() == ReferenceMode.INVOKE)
   777                         ? bridgeExpressionInvoke(makeReceiver(rcvr))
   778                         : bridgeExpressionNew();
   780                 //the body is either a return expression containing a method call,
   781                 //or the method call itself, depending on whether the return type of
   782                 //the bridge is non-void/void.
   783                 bridgeDecl.body = makeLambdaExpressionBody(bridgeExpr, bridgeDecl);
   785                 return bridgeDecl;
   786             } finally {
   787                 make.at(prevPos);
   788             }
   789         }
   790         //where
   791             private JCExpression makeReceiver(VarSymbol rcvr) {
   792                 if (rcvr == null) return null;
   793                 JCExpression rcvrExpr = make.Ident(rcvr);
   794                 Type rcvrType = tree.sym.enclClass().type;
   795                 if (!rcvr.type.tsym.isSubClass(rcvrType.tsym, types)) {
   796                     rcvrExpr = make.TypeCast(make.Type(rcvrType), rcvrExpr).setType(rcvrType);
   797                 }
   798                 return rcvrExpr;
   799             }
   801         /**
   802          * determine the receiver of the bridged method call - the receiver can
   803          * be either the synthetic receiver parameter or a type qualifier; the
   804          * original qualifier expression is never used here, as it might refer
   805          * to symbols not available in the static context of the bridge
   806          */
   807         private JCExpression bridgeExpressionInvoke(JCExpression rcvr) {
   808             JCExpression qualifier =
   809                     tree.sym.isStatic() ?
   810                         make.Type(tree.sym.owner.type) :
   811                         (rcvr != null) ?
   812                             rcvr :
   813                             tree.getQualifierExpression();
   815             //create the qualifier expression
   816             JCFieldAccess select = make.Select(qualifier, tree.sym.name);
   817             select.sym = tree.sym;
   818             select.type = tree.sym.erasure(types);
   820             //create the method call expression
   821             JCExpression apply = make.Apply(List.<JCExpression>nil(), select,
   822                     convertArgs(tree.sym, args.toList(), tree.varargsElement)).
   823                     setType(tree.sym.erasure(types).getReturnType());
   825             apply = transTypes.coerce(apply, localContext.generatedRefSig().getReturnType());
   826             setVarargsIfNeeded(apply, tree.varargsElement);
   827             return apply;
   828         }
   830         /**
   831          * the enclosing expression is either 'null' (no enclosing type) or set
   832          * to the first bridge synthetic parameter
   833          */
   834         private JCExpression bridgeExpressionNew() {
   835             if (tree.kind == ReferenceKind.ARRAY_CTOR) {
   836                 //create the array creation expression
   837                 JCNewArray newArr = make.NewArray(
   838                         make.Type(types.elemtype(tree.getQualifierExpression().type)),
   839                         List.of(make.Ident(params.first())),
   840                         null);
   841                 newArr.type = tree.getQualifierExpression().type;
   842                 return newArr;
   843             } else {
   844                 JCExpression encl = null;
   845                 switch (tree.kind) {
   846                     case UNBOUND:
   847                     case IMPLICIT_INNER:
   848                         encl = make.Ident(params.first());
   849                 }
   851                 //create the instance creation expression
   852                 JCNewClass newClass = make.NewClass(encl,
   853                         List.<JCExpression>nil(),
   854                         make.Type(tree.getQualifierExpression().type),
   855                         convertArgs(tree.sym, args.toList(), tree.varargsElement),
   856                         null);
   857                 newClass.constructor = tree.sym;
   858                 newClass.constructorType = tree.sym.erasure(types);
   859                 newClass.type = tree.getQualifierExpression().type;
   860                 setVarargsIfNeeded(newClass, tree.varargsElement);
   861                 return newClass;
   862             }
   863         }
   865         private VarSymbol addParameter(String name, Type p, boolean genArg) {
   866             VarSymbol vsym = new VarSymbol(0, names.fromString(name), p, localContext.bridgeSym);
   867             params.append(make.VarDef(vsym, null));
   868             if (genArg) {
   869                 args.append(make.Ident(vsym));
   870             }
   871             return vsym;
   872         }
   873     }
   875     /**
   876      * Bridges a member reference - this is needed when:
   877      * * Var args in the referenced method need to be flattened away
   878      * * super is used
   879      */
   880     private void bridgeMemberReference(JCMemberReference tree, ReferenceTranslationContext localContext) {
   881         kInfo.addMethod(new MemberReferenceBridger(tree, localContext).bridge());
   882     }
   884     /**
   885      * Generate an indy method call to the meta factory
   886      */
   887     private JCExpression makeMetaFactoryIndyCall(JCFunctionalExpression tree, boolean needsAltMetafactory,
   888             boolean isSerializable, int refKind, Symbol refSym, List<JCExpression> indy_args) {
   889         //determine the static bsm args
   890         Type mtype = types.erasure(tree.descriptorType);
   891         MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.type.tsym);
   892         List<Object> staticArgs = List.<Object>of(
   893                 new Pool.MethodHandle(ClassFile.REF_invokeInterface,
   894                     types.findDescriptorSymbol(tree.type.tsym), types),
   895                 new Pool.MethodHandle(refKind, refSym, types),
   896                 new MethodType(mtype.getParameterTypes(),
   897                         mtype.getReturnType(),
   898                         mtype.getThrownTypes(),
   899                         syms.methodClass));
   901         //computed indy arg types
   902         ListBuffer<Type> indy_args_types = ListBuffer.lb();
   903         for (JCExpression arg : indy_args) {
   904             indy_args_types.append(arg.type);
   905         }
   907         //finally, compute the type of the indy call
   908         MethodType indyType = new MethodType(indy_args_types.toList(),
   909                 tree.type,
   910                 List.<Type>nil(),
   911                 syms.methodClass);
   913         Name metafactoryName = needsAltMetafactory ?
   914                 names.altMetaFactory : names.metaFactory;
   916         if (needsAltMetafactory) {
   917             ListBuffer<Object> markers = ListBuffer.lb();
   918             for (Symbol t : tree.targets.tail) {
   919                 if (t != syms.serializableType.tsym) {
   920                     markers.append(t);
   921                 }
   922             }
   923             int flags = isSerializable? FLAG_SERIALIZABLE : 0;
   924             boolean hasMarkers = markers.nonEmpty();
   925             flags |= hasMarkers ? FLAG_MARKERS : 0;
   926             staticArgs = staticArgs.append(flags);
   927             if (hasMarkers) {
   928                 staticArgs = staticArgs.append(markers.length());
   929                 staticArgs = staticArgs.appendList(markers.toList());
   930             }
   931             if (isSerializable) {
   932                 addDeserializationCase(refKind, refSym, tree.type, samSym,
   933                         tree, staticArgs, indyType);
   934             }
   935         }
   937         return makeIndyCall(tree, syms.lambdaMetafactory, metafactoryName, staticArgs, indyType, indy_args);
   938     }
   940     /**
   941      * Generate an indy method call with given name, type and static bootstrap
   942      * arguments types
   943      */
   944     private JCExpression makeIndyCall(DiagnosticPosition pos, Type site, Name bsmName,
   945             List<Object> staticArgs, MethodType indyType, List<JCExpression> indyArgs) {
   946         int prevPos = make.pos;
   947         try {
   948             make.at(pos);
   949             List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType,
   950                     syms.stringType,
   951                     syms.methodTypeType).appendList(bsmStaticArgToTypes(staticArgs));
   953             Symbol bsm = rs.resolveInternalMethod(pos, attrEnv, site,
   954                     bsmName, bsm_staticArgs, List.<Type>nil());
   956             DynamicMethodSymbol dynSym =
   957                     new DynamicMethodSymbol(names.lambda,
   958                                             syms.noSymbol,
   959                                             bsm.isStatic() ?
   960                                                 ClassFile.REF_invokeStatic :
   961                                                 ClassFile.REF_invokeVirtual,
   962                                             (MethodSymbol)bsm,
   963                                             indyType,
   964                                             staticArgs.toArray());
   966             JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), bsmName);
   967             qualifier.sym = dynSym;
   968             qualifier.type = indyType.getReturnType();
   970             JCMethodInvocation proxyCall = make.Apply(List.<JCExpression>nil(), qualifier, indyArgs);
   971             proxyCall.type = indyType.getReturnType();
   972             return proxyCall;
   973         } finally {
   974             make.at(prevPos);
   975         }
   976     }
   977     //where
   978     private List<Type> bsmStaticArgToTypes(List<Object> args) {
   979         ListBuffer<Type> argtypes = ListBuffer.lb();
   980         for (Object arg : args) {
   981             argtypes.append(bsmStaticArgToType(arg));
   982         }
   983         return argtypes.toList();
   984     }
   986     private Type bsmStaticArgToType(Object arg) {
   987         Assert.checkNonNull(arg);
   988         if (arg instanceof ClassSymbol) {
   989             return syms.classType;
   990         } else if (arg instanceof Integer) {
   991             return syms.intType;
   992         } else if (arg instanceof Long) {
   993             return syms.longType;
   994         } else if (arg instanceof Float) {
   995             return syms.floatType;
   996         } else if (arg instanceof Double) {
   997             return syms.doubleType;
   998         } else if (arg instanceof String) {
   999             return syms.stringType;
  1000         } else if (arg instanceof Pool.MethodHandle) {
  1001             return syms.methodHandleType;
  1002         } else if (arg instanceof MethodType) {
  1003             return syms.methodTypeType;
  1004         } else {
  1005             Assert.error("bad static arg " + arg.getClass());
  1006             return null;
  1010     /**
  1011      * Get the opcode associated with this method reference
  1012      */
  1013     private int referenceKind(Symbol refSym) {
  1014         if (refSym.isConstructor()) {
  1015             return ClassFile.REF_newInvokeSpecial;
  1016         } else {
  1017             if (refSym.isStatic()) {
  1018                 return ClassFile.REF_invokeStatic;
  1019             } else if (refSym.enclClass().isInterface()) {
  1020                 return ClassFile.REF_invokeInterface;
  1021             } else {
  1022                 return ClassFile.REF_invokeVirtual;
  1027     // </editor-fold>
  1029     // <editor-fold defaultstate="collapsed" desc="Lambda/reference analyzer">\
  1030     /**
  1031      * This visitor collects information about translation of a lambda expression.
  1032      * More specifically, it keeps track of the enclosing contexts and captured locals
  1033      * accessed by the lambda being translated (as well as other useful info).
  1034      */
  1035     class LambdaAnalyzer extends TreeScanner {
  1037         /** the frame stack - used to reconstruct translation info about enclosing scopes */
  1038         private List<Frame> frameStack;
  1040         /**
  1041          * keep the count of lambda expression (used to generate unambiguous
  1042          * names)
  1043          */
  1044         private int lambdaCount = 0;
  1046         /**
  1047          * keep the count of lambda expression defined in given context (used to
  1048          * generate unambiguous names for serializable lambdas)
  1049          */
  1050         private Map<String, Integer> serializableLambdaCounts =
  1051                 new HashMap<String, Integer>();
  1053         private Map<Symbol, JCClassDecl> localClassDefs;
  1055         /**
  1056          * maps for fake clinit symbols to be used as owners of lambda occurring in
  1057          * a static var init context
  1058          */
  1059         private Map<ClassSymbol, Symbol> clinits =
  1060                 new HashMap<ClassSymbol, Symbol>();
  1062         private void analyzeClass(JCClassDecl tree) {
  1063             frameStack = List.nil();
  1064             localClassDefs = new HashMap<Symbol, JCClassDecl>();
  1065             scan(tree);
  1068         @Override
  1069         public void visitBlock(JCBlock tree) {
  1070             List<Frame> prevStack = frameStack;
  1071             try {
  1072                 if (frameStack.nonEmpty() && frameStack.head.tree.hasTag(CLASSDEF)) {
  1073                     frameStack = frameStack.prepend(new Frame(tree));
  1075                 super.visitBlock(tree);
  1077             finally {
  1078                 frameStack = prevStack;
  1082         @Override
  1083         public void visitClassDef(JCClassDecl tree) {
  1084             List<Frame> prevStack = frameStack;
  1085             Map<String, Integer> prevSerializableLambdaCount =
  1086                     serializableLambdaCounts;
  1087             Map<ClassSymbol, Symbol> prevClinits = clinits;
  1088             try {
  1089                 serializableLambdaCounts = new HashMap<String, Integer>();
  1090                 prevClinits = new HashMap<ClassSymbol, Symbol>();
  1091                 if (tree.sym.owner.kind == MTH) {
  1092                     localClassDefs.put(tree.sym, tree);
  1094                 if (directlyEnclosingLambda() != null) {
  1095                     tree.sym.owner = owner();
  1096                     if (tree.sym.hasOuterInstance()) {
  1097                         //if a class is defined within a lambda, the lambda must capture
  1098                         //its enclosing instance (if any)
  1099                         TranslationContext<?> localContext = context();
  1100                         while (localContext != null) {
  1101                             if (localContext.tree.getTag() == LAMBDA) {
  1102                                 ((LambdaTranslationContext)localContext)
  1103                                         .addSymbol(tree.sym.type.getEnclosingType().tsym, CAPTURED_THIS);
  1105                             localContext = localContext.prev;
  1109                 frameStack = frameStack.prepend(new Frame(tree));
  1110                 super.visitClassDef(tree);
  1112             finally {
  1113                 frameStack = prevStack;
  1114                 serializableLambdaCounts = prevSerializableLambdaCount;
  1115                 clinits = prevClinits;
  1119         @Override
  1120         public void visitIdent(JCIdent tree) {
  1121             if (context() != null && lambdaIdentSymbolFilter(tree.sym)) {
  1122                 if (tree.sym.kind == VAR &&
  1123                         tree.sym.owner.kind == MTH &&
  1124                         tree.type.constValue() == null) {
  1125                     TranslationContext<?> localContext = context();
  1126                     while (localContext != null) {
  1127                         if (localContext.tree.getTag() == LAMBDA) {
  1128                             JCTree block = capturedDecl(localContext.depth, tree.sym);
  1129                             if (block == null) break;
  1130                             ((LambdaTranslationContext)localContext)
  1131                                     .addSymbol(tree.sym, CAPTURED_VAR);
  1133                         localContext = localContext.prev;
  1135                 } else if (tree.sym.owner.kind == TYP) {
  1136                     TranslationContext<?> localContext = context();
  1137                     while (localContext != null) {
  1138                         if (localContext.tree.hasTag(LAMBDA)) {
  1139                             JCTree block = capturedDecl(localContext.depth, tree.sym);
  1140                             if (block == null) break;
  1141                             switch (block.getTag()) {
  1142                                 case CLASSDEF:
  1143                                     JCClassDecl cdecl = (JCClassDecl)block;
  1144                                     ((LambdaTranslationContext)localContext)
  1145                                             .addSymbol(cdecl.sym, CAPTURED_THIS);
  1146                                     break;
  1147                                 default:
  1148                                     Assert.error("bad block kind");
  1151                         localContext = localContext.prev;
  1155             super.visitIdent(tree);
  1158         @Override
  1159         public void visitLambda(JCLambda tree) {
  1160             List<Frame> prevStack = frameStack;
  1161             try {
  1162                 LambdaTranslationContext context = (LambdaTranslationContext)makeLambdaContext(tree);
  1163                 frameStack = frameStack.prepend(new Frame(tree));
  1164                 for (JCVariableDecl param : tree.params) {
  1165                     context.addSymbol(param.sym, PARAM);
  1166                     frameStack.head.addLocal(param.sym);
  1168                 contextMap.put(tree, context);
  1169                 scan(tree.body);
  1170                 context.complete();
  1172             finally {
  1173                 frameStack = prevStack;
  1177         @Override
  1178         public void visitMethodDef(JCMethodDecl tree) {
  1179             List<Frame> prevStack = frameStack;
  1180             try {
  1181                 frameStack = frameStack.prepend(new Frame(tree));
  1182                 super.visitMethodDef(tree);
  1184             finally {
  1185                 frameStack = prevStack;
  1189         @Override
  1190         public void visitNewClass(JCNewClass tree) {
  1191             if (lambdaNewClassFilter(context(), tree)) {
  1192                 TranslationContext<?> localContext = context();
  1193                 while (localContext != null) {
  1194                     if (localContext.tree.getTag() == LAMBDA) {
  1195                         ((LambdaTranslationContext)localContext)
  1196                                 .addSymbol(tree.type.getEnclosingType().tsym, CAPTURED_THIS);
  1198                     localContext = localContext.prev;
  1201             if (context() != null && tree.type.tsym.owner.kind == MTH) {
  1202                 LambdaTranslationContext lambdaContext = (LambdaTranslationContext)context();
  1203                 captureLocalClassDefs(tree.type.tsym, lambdaContext);
  1205             super.visitNewClass(tree);
  1207         //where
  1208             void captureLocalClassDefs(Symbol csym, final LambdaTranslationContext lambdaContext) {
  1209                 JCClassDecl localCDef = localClassDefs.get(csym);
  1210                 if (localCDef != null && localCDef.pos < lambdaContext.tree.pos) {
  1211                     BasicFreeVarCollector fvc = lower.new BasicFreeVarCollector() {
  1212                         @Override
  1213                         void addFreeVars(ClassSymbol c) {
  1214                             captureLocalClassDefs(c, lambdaContext);
  1216                         @Override
  1217                         void visitSymbol(Symbol sym) {
  1218                             if (sym.kind == VAR &&
  1219                                     sym.owner.kind == MTH &&
  1220                                     ((VarSymbol)sym).getConstValue() == null) {
  1221                                 TranslationContext<?> localContext = context();
  1222                                 while (localContext != null) {
  1223                                     if (localContext.tree.getTag() == LAMBDA) {
  1224                                         JCTree block = capturedDecl(localContext.depth, sym);
  1225                                         if (block == null) break;
  1226                                         ((LambdaTranslationContext)localContext).addSymbol(sym, CAPTURED_VAR);
  1228                                     localContext = localContext.prev;
  1232                     };
  1233                     fvc.scan(localCDef);
  1237         @Override
  1238         public void visitReference(JCMemberReference tree) {
  1239             scan(tree.getQualifierExpression());
  1240             contextMap.put(tree, makeReferenceContext(tree));
  1243         @Override
  1244         public void visitSelect(JCFieldAccess tree) {
  1245             if (context() != null && lambdaSelectSymbolFilter(tree.sym)) {
  1246                 TranslationContext<?> localContext = context();
  1247                 while (localContext != null) {
  1248                     if (localContext.tree.hasTag(LAMBDA)) {
  1249                         JCClassDecl clazz = (JCClassDecl)capturedDecl(localContext.depth, tree.sym);
  1250                         if (clazz == null) break;
  1251                         ((LambdaTranslationContext)localContext).addSymbol(clazz.sym, CAPTURED_THIS);
  1253                     localContext = localContext.prev;
  1255                 scan(tree.selected);
  1256             } else {
  1257                 super.visitSelect(tree);
  1261         @Override
  1262         public void visitVarDef(JCVariableDecl tree) {
  1263             TranslationContext<?> context = context();
  1264             LambdaTranslationContext ltc = (context != null && context instanceof LambdaTranslationContext)?
  1265                     (LambdaTranslationContext)context :
  1266                     null;
  1267             if (ltc != null) {
  1268                 if (frameStack.head.tree.hasTag(LAMBDA)) {
  1269                     ltc.addSymbol(tree.sym, LOCAL_VAR);
  1271                 // Check for type variables (including as type arguments).
  1272                 // If they occur within class nested in a lambda, mark for erasure
  1273                 Type type = tree.sym.asType();
  1274                 if (inClassWithinLambda() && !types.isSameType(types.erasure(type), type)) {
  1275                     ltc.addSymbol(tree.sym, TYPE_VAR);
  1279             List<Frame> prevStack = frameStack;
  1280             try {
  1281                 if (tree.sym.owner.kind == MTH) {
  1282                     frameStack.head.addLocal(tree.sym);
  1284                 frameStack = frameStack.prepend(new Frame(tree));
  1285                 super.visitVarDef(tree);
  1287             finally {
  1288                 frameStack = prevStack;
  1292         private Name lambdaName() {
  1293             return names.lambda.append(names.fromString("" + lambdaCount++));
  1296         private Name serializedLambdaName(Symbol owner) {
  1297             StringBuilder buf = new StringBuilder();
  1298             buf.append(names.lambda);
  1299             String methodName = owner.name.toString();
  1300             if (methodName.equals("<clinit>"))
  1301                 methodName = "static";
  1302             else if (methodName.equals("<init>"))
  1303                 methodName = "new";
  1304             buf.append(methodName);
  1305             buf.append('$');
  1306             int methTypeHash = methodSig(owner.type).hashCode();
  1307             buf.append(Integer.toHexString(methTypeHash));
  1308             buf.append('$');
  1309             String temp = buf.toString();
  1310             Integer count = serializableLambdaCounts.get(temp);
  1311             if (count == null) {
  1312                 count = 0;
  1314             buf.append(count++);
  1315             serializableLambdaCounts.put(temp, count);
  1316             return names.fromString(buf.toString());
  1319         /**
  1320          * Return a valid owner given the current declaration stack
  1321          * (required to skip synthetic lambda symbols)
  1322          */
  1323         private Symbol owner() {
  1324             return owner(false);
  1327         @SuppressWarnings("fallthrough")
  1328         private Symbol owner(boolean skipLambda) {
  1329             List<Frame> frameStack2 = frameStack;
  1330             while (frameStack2.nonEmpty()) {
  1331                 switch (frameStack2.head.tree.getTag()) {
  1332                     case VARDEF:
  1333                         if (((JCVariableDecl)frameStack2.head.tree).sym.isLocal()) {
  1334                             frameStack2 = frameStack2.tail;
  1335                             break;
  1337                         JCClassDecl cdecl = (JCClassDecl)frameStack2.tail.head.tree;
  1338                         return initSym(cdecl.sym,
  1339                                 ((JCVariableDecl)frameStack2.head.tree).sym.flags() & STATIC);
  1340                     case BLOCK:
  1341                         JCClassDecl cdecl2 = (JCClassDecl)frameStack2.tail.head.tree;
  1342                         return initSym(cdecl2.sym,
  1343                                 ((JCBlock)frameStack2.head.tree).flags & STATIC);
  1344                     case CLASSDEF:
  1345                         return ((JCClassDecl)frameStack2.head.tree).sym;
  1346                     case METHODDEF:
  1347                         return ((JCMethodDecl)frameStack2.head.tree).sym;
  1348                     case LAMBDA:
  1349                         if (!skipLambda)
  1350                             return ((LambdaTranslationContext)contextMap
  1351                                     .get(frameStack2.head.tree)).translatedSym;
  1352                     default:
  1353                         frameStack2 = frameStack2.tail;
  1356             Assert.error();
  1357             return null;
  1360         private Symbol initSym(ClassSymbol csym, long flags) {
  1361             boolean isStatic = (flags & STATIC) != 0;
  1362             if (isStatic) {
  1363                 //static clinits are generated in Gen - so we need to fake them
  1364                 Symbol clinit = clinits.get(csym);
  1365                 if (clinit == null) {
  1366                     clinit = makeSyntheticMethod(STATIC,
  1367                             names.clinit,
  1368                             new MethodType(List.<Type>nil(), syms.voidType, List.<Type>nil(), syms.methodClass),
  1369                             csym);
  1370                     clinits.put(csym, clinit);
  1372                 return clinit;
  1373             } else {
  1374                 //get the first constructor and treat it as the instance init sym
  1375                 for (Symbol s : csym.members_field.getElementsByName(names.init)) {
  1376                     return s;
  1379             Assert.error("init not found");
  1380             return null;
  1383         private JCTree directlyEnclosingLambda() {
  1384             if (frameStack.isEmpty()) {
  1385                 return null;
  1387             List<Frame> frameStack2 = frameStack;
  1388             while (frameStack2.nonEmpty()) {
  1389                 switch (frameStack2.head.tree.getTag()) {
  1390                     case CLASSDEF:
  1391                     case METHODDEF:
  1392                         return null;
  1393                     case LAMBDA:
  1394                         return frameStack2.head.tree;
  1395                     default:
  1396                         frameStack2 = frameStack2.tail;
  1399             Assert.error();
  1400             return null;
  1403         private boolean inClassWithinLambda() {
  1404             if (frameStack.isEmpty()) {
  1405                 return false;
  1407             List<Frame> frameStack2 = frameStack;
  1408             boolean classFound = false;
  1409             while (frameStack2.nonEmpty()) {
  1410                 switch (frameStack2.head.tree.getTag()) {
  1411                     case LAMBDA:
  1412                         return classFound;
  1413                     case CLASSDEF:
  1414                         classFound = true;
  1415                         frameStack2 = frameStack2.tail;
  1416                         break;
  1417                     default:
  1418                         frameStack2 = frameStack2.tail;
  1421             // No lambda
  1422             return false;
  1425         /**
  1426          * Return the declaration corresponding to a symbol in the enclosing
  1427          * scope; the depth parameter is used to filter out symbols defined
  1428          * in nested scopes (which do not need to undergo capture).
  1429          */
  1430         private JCTree capturedDecl(int depth, Symbol sym) {
  1431             int currentDepth = frameStack.size() - 1;
  1432             for (Frame block : frameStack) {
  1433                 switch (block.tree.getTag()) {
  1434                     case CLASSDEF:
  1435                         ClassSymbol clazz = ((JCClassDecl)block.tree).sym;
  1436                         if (sym.isMemberOf(clazz, types)) {
  1437                             return currentDepth > depth ? null : block.tree;
  1439                         break;
  1440                     case VARDEF:
  1441                         if (((JCVariableDecl)block.tree).sym == sym &&
  1442                                 sym.owner.kind == MTH) { //only locals are captured
  1443                             return currentDepth > depth ? null : block.tree;
  1445                         break;
  1446                     case BLOCK:
  1447                     case METHODDEF:
  1448                     case LAMBDA:
  1449                         if (block.locals != null && block.locals.contains(sym)) {
  1450                             return currentDepth > depth ? null : block.tree;
  1452                         break;
  1453                     default:
  1454                         Assert.error("bad decl kind " + block.tree.getTag());
  1456                 currentDepth--;
  1458             return null;
  1461         private TranslationContext<?> context() {
  1462             for (Frame frame : frameStack) {
  1463                 TranslationContext<?> context = contextMap.get(frame.tree);
  1464                 if (context != null) {
  1465                     return context;
  1468             return null;
  1471         /**
  1472          *  This is used to filter out those identifiers that needs to be adjusted
  1473          *  when translating away lambda expressions
  1474          */
  1475         private boolean lambdaIdentSymbolFilter(Symbol sym) {
  1476             return (sym.kind == VAR || sym.kind == MTH)
  1477                     && !sym.isStatic()
  1478                     && sym.name != names.init;
  1481         private boolean lambdaSelectSymbolFilter(Symbol sym) {
  1482             return (sym.kind == VAR || sym.kind == MTH) &&
  1483                         !sym.isStatic() &&
  1484                         (sym.name == names._this ||
  1485                         sym.name == names._super);
  1488         /**
  1489          * This is used to filter out those new class expressions that need to
  1490          * be qualified with an enclosing tree
  1491          */
  1492         private boolean lambdaNewClassFilter(TranslationContext<?> context, JCNewClass tree) {
  1493             if (context != null
  1494                     && tree.encl == null
  1495                     && tree.def == null
  1496                     && !tree.type.getEnclosingType().hasTag(NONE)) {
  1497                 Type encl = tree.type.getEnclosingType();
  1498                 Type current = context.owner.enclClass().type;
  1499                 while (!current.hasTag(NONE)) {
  1500                     if (current.tsym.isSubClass(encl.tsym, types)) {
  1501                         return true;
  1503                     current = current.getEnclosingType();
  1505                 return false;
  1506             } else {
  1507                 return false;
  1511         private TranslationContext<JCLambda> makeLambdaContext(JCLambda tree) {
  1512             return new LambdaTranslationContext(tree);
  1515         private TranslationContext<JCMemberReference> makeReferenceContext(JCMemberReference tree) {
  1516             return new ReferenceTranslationContext(tree);
  1519         private class Frame {
  1520             final JCTree tree;
  1521             List<Symbol> locals;
  1523             public Frame(JCTree tree) {
  1524                 this.tree = tree;
  1527             void addLocal(Symbol sym) {
  1528                 if (locals == null) {
  1529                     locals = List.nil();
  1531                 locals = locals.prepend(sym);
  1535         /**
  1536          * This class is used to store important information regarding translation of
  1537          * lambda expression/method references (see subclasses).
  1538          */
  1539         private abstract class TranslationContext<T extends JCFunctionalExpression> {
  1541             /** the underlying (untranslated) tree */
  1542             T tree;
  1544             /** points to the adjusted enclosing scope in which this lambda/mref expression occurs */
  1545             Symbol owner;
  1547             /** the depth of this lambda expression in the frame stack */
  1548             int depth;
  1550             /** the enclosing translation context (set for nested lambdas/mref) */
  1551             TranslationContext<?> prev;
  1553             TranslationContext(T tree) {
  1554                 this.tree = tree;
  1555                 this.owner = owner();
  1556                 this.depth = frameStack.size() - 1;
  1557                 this.prev = context();
  1560             /** does this functional expression need to be created using alternate metafactory? */
  1561             boolean needsAltMetafactory() {
  1562                 return (tree.targets.length() > 1 ||
  1563                         isSerializable());
  1566             /** does this functional expression require serialization support? */
  1567             boolean isSerializable() {
  1568                 for (Symbol target : tree.targets) {
  1569                     if (types.asSuper(target.type, syms.serializableType.tsym) != null) {
  1570                         return true;
  1573                 return false;
  1577         /**
  1578          * This class retains all the useful information about a lambda expression;
  1579          * the contents of this class are filled by the LambdaAnalyzer visitor,
  1580          * and the used by the main translation routines in order to adjust references
  1581          * to captured locals/members, etc.
  1582          */
  1583         private class LambdaTranslationContext extends TranslationContext<JCLambda> {
  1585             /** variable in the enclosing context to which this lambda is assigned */
  1586             Symbol self;
  1588             /** map from original to translated lambda parameters */
  1589             Map<Symbol, Symbol> lambdaParams = new LinkedHashMap<Symbol, Symbol>();
  1591             /** map from original to translated lambda locals */
  1592             Map<Symbol, Symbol> lambdaLocals = new LinkedHashMap<Symbol, Symbol>();
  1594             /** map from variables in enclosing scope to translated synthetic parameters */
  1595             Map<Symbol, Symbol> capturedLocals  = new LinkedHashMap<Symbol, Symbol>();
  1597             /** map from class symbols to translated synthetic parameters (for captured member access) */
  1598             Map<Symbol, Symbol> capturedThis = new LinkedHashMap<Symbol, Symbol>();
  1600             /** map from original to translated lambda locals */
  1601             Map<Symbol, Symbol> typeVars = new LinkedHashMap<Symbol, Symbol>();
  1603             /** the synthetic symbol for the method hoisting the translated lambda */
  1604             Symbol translatedSym;
  1606             List<JCVariableDecl> syntheticParams;
  1608             LambdaTranslationContext(JCLambda tree) {
  1609                 super(tree);
  1610                 Frame frame = frameStack.head;
  1611                 if (frame.tree.hasTag(VARDEF)) {
  1612                     self = ((JCVariableDecl)frame.tree).sym;
  1614                 Name name = isSerializable() ? serializedLambdaName(owner) : lambdaName();
  1615                 this.translatedSym = makeSyntheticMethod(0, name, null, owner.enclClass());
  1618             /**
  1619              * Translate a symbol of a given kind into something suitable for the
  1620              * synthetic lambda body
  1621              */
  1622             Symbol translate(String name, final Symbol sym, LambdaSymbolKind skind) {
  1623                 switch (skind) {
  1624                     case CAPTURED_THIS:
  1625                         return sym;  // self represented
  1626                     case TYPE_VAR:
  1627                         // Just erase the type var
  1628                         return new VarSymbol(sym.flags(), names.fromString(name),
  1629                                 types.erasure(sym.type), sym.owner);
  1630                     case CAPTURED_VAR:
  1631                         return new VarSymbol(SYNTHETIC | FINAL, names.fromString(name), types.erasure(sym.type), translatedSym) {
  1632                             @Override
  1633                             public Symbol baseSymbol() {
  1634                                 //keep mapping with original captured symbol
  1635                                 return sym;
  1637                         };
  1638                     default:
  1639                         return makeSyntheticVar(FINAL, name, types.erasure(sym.type), translatedSym);
  1643             void addSymbol(Symbol sym, LambdaSymbolKind skind) {
  1644                 Map<Symbol, Symbol> transMap = null;
  1645                 String preferredName;
  1646                 switch (skind) {
  1647                     case CAPTURED_THIS:
  1648                         transMap = capturedThis;
  1649                         preferredName = "encl$" + capturedThis.size();
  1650                         break;
  1651                     case CAPTURED_VAR:
  1652                         transMap = capturedLocals;
  1653                         preferredName = "cap$" + capturedLocals.size();
  1654                         break;
  1655                     case LOCAL_VAR:
  1656                         transMap = lambdaLocals;
  1657                         preferredName = sym.name.toString();
  1658                         break;
  1659                     case PARAM:
  1660                         transMap = lambdaParams;
  1661                         preferredName = sym.name.toString();
  1662                         break;
  1663                     case TYPE_VAR:
  1664                         transMap = typeVars;
  1665                         preferredName = sym.name.toString();
  1666                         break;
  1667                     default: throw new AssertionError();
  1669                 if (!transMap.containsKey(sym)) {
  1670                     transMap.put(sym, translate(preferredName, sym, skind));
  1674             Map<Symbol, Symbol> getSymbolMap(LambdaSymbolKind... skinds) {
  1675                 LinkedHashMap<Symbol, Symbol> translationMap = new LinkedHashMap<Symbol, Symbol>();
  1676                 for (LambdaSymbolKind skind : skinds) {
  1677                     switch (skind) {
  1678                         case CAPTURED_THIS:
  1679                             translationMap.putAll(capturedThis);
  1680                             break;
  1681                         case CAPTURED_VAR:
  1682                             translationMap.putAll(capturedLocals);
  1683                             break;
  1684                         case LOCAL_VAR:
  1685                             translationMap.putAll(lambdaLocals);
  1686                             break;
  1687                         case PARAM:
  1688                             translationMap.putAll(lambdaParams);
  1689                             break;
  1690                         case TYPE_VAR:
  1691                             translationMap.putAll(typeVars);
  1692                             break;
  1693                         default: throw new AssertionError();
  1696                 return translationMap;
  1699             /**
  1700              * The translatedSym is not complete/accurate until the analysis is
  1701              * finished.  Once the analysis is finished, the translatedSym is
  1702              * "completed" -- updated with type information, access modifiers,
  1703              * and full parameter list.
  1704              */
  1705             void complete() {
  1706                 if (syntheticParams != null) {
  1707                     return;
  1709                 boolean inInterface = translatedSym.owner.isInterface();
  1710                 boolean thisReferenced = !getSymbolMap(CAPTURED_THIS).isEmpty();
  1711                 boolean needInstance = thisReferenced || inInterface;
  1713                 // If instance access isn't needed, make it static
  1714                 // Interface methods much be public default methods, otherwise make it private
  1715                 translatedSym.flags_field = SYNTHETIC | (needInstance? 0 : STATIC) |
  1716                         (inInterface? PUBLIC | DEFAULT : PRIVATE);
  1718                 //compute synthetic params
  1719                 ListBuffer<JCVariableDecl> params = ListBuffer.lb();
  1721                 // The signature of the method is augmented with the following
  1722                 // synthetic parameters:
  1723                 //
  1724                 // 1) reference to enclosing contexts captured by the lambda expression
  1725                 // 2) enclosing locals captured by the lambda expression
  1726                 for (Symbol thisSym : getSymbolMap(CAPTURED_VAR, PARAM).values()) {
  1727                     params.append(make.VarDef((VarSymbol) thisSym, null));
  1730                 syntheticParams = params.toList();
  1732                 //prepend synthetic args to translated lambda method signature
  1733                 translatedSym.type = types.createMethodTypeWithParameters(
  1734                         generatedLambdaSig(),
  1735                         TreeInfo.types(syntheticParams));
  1738             Type generatedLambdaSig() {
  1739                 return types.erasure(tree.descriptorType);
  1743         /**
  1744          * This class retains all the useful information about a method reference;
  1745          * the contents of this class are filled by the LambdaAnalyzer visitor,
  1746          * and the used by the main translation routines in order to adjust method
  1747          * references (i.e. in case a bridge is needed)
  1748          */
  1749         private class ReferenceTranslationContext extends TranslationContext<JCMemberReference> {
  1751             final boolean isSuper;
  1752             final Symbol bridgeSym;
  1754             ReferenceTranslationContext(JCMemberReference tree) {
  1755                 super(tree);
  1756                 this.isSuper = tree.hasKind(ReferenceKind.SUPER);
  1757                 this.bridgeSym = needsBridge()
  1758                         ? makeSyntheticMethod(isSuper ? 0 : STATIC,
  1759                                               lambdaName().append(names.fromString("$bridge")), null,
  1760                                               owner.enclClass())
  1761                         : null;
  1764             /**
  1765              * Get the opcode associated with this method reference
  1766              */
  1767             int referenceKind() {
  1768                 return LambdaToMethod.this.referenceKind(needsBridge() ? bridgeSym : tree.sym);
  1771             boolean needsVarArgsConversion() {
  1772                 return tree.varargsElement != null;
  1775             /**
  1776              * @return Is this an array operation like clone()
  1777              */
  1778             boolean isArrayOp() {
  1779                 return tree.sym.owner == syms.arrayClass;
  1782             boolean isPrivateConstructor() {
  1783                 //hack needed to workaround 292 bug (8005122)
  1784                 //when 292 issue is fixed we should simply remove this
  1785                 return tree.sym.name == names.init &&
  1786                         (tree.sym.flags() & PRIVATE) != 0;
  1789             boolean receiverAccessible() {
  1790                 //hack needed to workaround 292 bug (7087658)
  1791                 //when 292 issue is fixed we should remove this and change the backend
  1792                 //code to always generate a method handle to an accessible method
  1793                 return tree.ownerAccessible;
  1796             /**
  1797              * Does this reference needs a bridge (i.e. var args need to be
  1798              * expanded or "super" is used)
  1799              */
  1800             final boolean needsBridge() {
  1801                 return isSuper || needsVarArgsConversion() || isArrayOp() ||
  1802                         isPrivateConstructor() || !receiverAccessible();
  1805             Type generatedRefSig() {
  1806                 return types.erasure(tree.sym.type);
  1809             Type bridgedRefSig() {
  1810                 return types.erasure(types.findDescriptorSymbol(tree.targets.head).type);
  1814     // </editor-fold>
  1816     enum LambdaSymbolKind {
  1817         CAPTURED_VAR,
  1818         CAPTURED_THIS,
  1819         LOCAL_VAR,
  1820         PARAM,
  1821         TYPE_VAR;
  1824     /**
  1825      * ****************************************************************
  1826      * Signature Generation
  1827      * ****************************************************************
  1828      */
  1830     private String methodSig(Type type) {
  1831         L2MSignatureGenerator sg = new L2MSignatureGenerator();
  1832         sg.assembleSig(type);
  1833         return sg.toString();
  1836     private String classSig(Type type) {
  1837         L2MSignatureGenerator sg = new L2MSignatureGenerator();
  1838         sg.assembleClassSig(type);
  1839         return sg.toString();
  1842     /**
  1843      * Signature Generation
  1844      */
  1845     private class L2MSignatureGenerator extends Types.SignatureGenerator {
  1847         /**
  1848          * An output buffer for type signatures.
  1849          */
  1850         StringBuilder sb = new StringBuilder();
  1852         L2MSignatureGenerator() {
  1853             super(types);
  1856         @Override
  1857         protected void append(char ch) {
  1858             sb.append(ch);
  1861         @Override
  1862         protected void append(byte[] ba) {
  1863             sb.append(new String(ba));
  1866         @Override
  1867         protected void append(Name name) {
  1868             sb.append(name.toString());
  1871         @Override
  1872         public String toString() {
  1873             return sb.toString();

mercurial