langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
changeset 27855 7afea3897f9b
parent 27224 228abfa87080
child 28145 365419055307
equal deleted inserted replaced
27854:22b4bfc4e22f 27855:7afea3897f9b
    38 import com.sun.tools.javac.code.Symbol.TypeSymbol;
    38 import com.sun.tools.javac.code.Symbol.TypeSymbol;
    39 import com.sun.tools.javac.code.Symbol.VarSymbol;
    39 import com.sun.tools.javac.code.Symbol.VarSymbol;
    40 import com.sun.tools.javac.code.Symtab;
    40 import com.sun.tools.javac.code.Symtab;
    41 import com.sun.tools.javac.code.Type;
    41 import com.sun.tools.javac.code.Type;
    42 import com.sun.tools.javac.code.Type.MethodType;
    42 import com.sun.tools.javac.code.Type.MethodType;
       
    43 import com.sun.tools.javac.code.Type.TypeVar;
    43 import com.sun.tools.javac.code.Types;
    44 import com.sun.tools.javac.code.Types;
    44 import com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzerPreprocessor.*;
    45 import com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzerPreprocessor.*;
    45 import com.sun.tools.javac.comp.Lower.BasicFreeVarCollector;
    46 import com.sun.tools.javac.comp.Lower.BasicFreeVarCollector;
    46 import com.sun.tools.javac.jvm.*;
    47 import com.sun.tools.javac.jvm.*;
    47 import com.sun.tools.javac.util.*;
    48 import com.sun.tools.javac.util.*;
    58 import static com.sun.tools.javac.comp.LambdaToMethod.LambdaSymbolKind.*;
    59 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.Flags.*;
    60 import static com.sun.tools.javac.code.Kinds.Kind.*;
    61 import static com.sun.tools.javac.code.Kinds.Kind.*;
    61 import static com.sun.tools.javac.code.TypeTag.*;
    62 import static com.sun.tools.javac.code.TypeTag.*;
    62 import static com.sun.tools.javac.tree.JCTree.Tag.*;
    63 import static com.sun.tools.javac.tree.JCTree.Tag.*;
       
    64 import javax.lang.model.type.TypeKind;
    63 
    65 
    64 /**
    66 /**
    65  * This pass desugars lambda expressions into static methods
    67  * This pass desugars lambda expressions into static methods
    66  *
    68  *
    67  *  <p><b>This is NOT part of any supported API.
    69  *  <p><b>This is NOT part of any supported API.
   757 
   759 
   758         JCLambda lambda() {
   760         JCLambda lambda() {
   759             int prevPos = make.pos;
   761             int prevPos = make.pos;
   760             try {
   762             try {
   761                 make.at(tree);
   763                 make.at(tree);
   762                 Type samDesc = localContext.bridgedRefSig();
       
   763                 List<Type> samPTypes = samDesc.getParameterTypes();
       
   764 
       
   765                 // an extra argument is prepended in the case where the member
       
   766                 // reference is an unbound instance method reference (in which
       
   767                 // case the receiver expression in passed.
       
   768                 VarSymbol rcvr;
       
   769                 switch (tree.kind) {
       
   770                     case BOUND:
       
   771                         rcvr = addParameter("rec$", tree.getQualifierExpression().type, false);
       
   772                         receiverExpression = attr.makeNullCheck(tree.getQualifierExpression());
       
   773                         break;
       
   774                     case UNBOUND:
       
   775                         rcvr = addParameter("rec$", samPTypes.head, false);
       
   776                         samPTypes = samPTypes.tail;
       
   777                         break;
       
   778                     default:
       
   779                         rcvr = null;
       
   780                         break;
       
   781                 }
       
   782 
       
   783                 // generate the parameter list for the coverted member reference.
       
   784                 // the signature will match the signature of the target sam descriptor
       
   785 
       
   786                 List<Type> refPTypes = tree.sym.type.getParameterTypes();
       
   787                 int refSize = refPTypes.size();
       
   788                 int samSize = samPTypes.size();
       
   789                 // Last parameter to copy from referenced method
       
   790                 int last = localContext.needsVarArgsConversion() ? refSize - 1 : refSize;
       
   791 
       
   792                 List<Type> l = refPTypes;
       
   793                 // Use parameter types of the referenced method, excluding final var args
       
   794                 for (int i = 0; l.nonEmpty() && i < last; ++i) {
       
   795                     addParameter("x$" + i, l.head, true);
       
   796                     l = l.tail;
       
   797                 }
       
   798                 // Flatten out the var args
       
   799                 for (int i = last; i < samSize; ++i) {
       
   800                     addParameter("xva$" + i, tree.varargsElement, true);
       
   801                 }
       
   802 
   764 
   803                 //body generation - this can be either a method call or a
   765                 //body generation - this can be either a method call or a
   804                 //new instance creation expression, depending on the member reference kind
   766                 //new instance creation expression, depending on the member reference kind
       
   767                 VarSymbol rcvr = addParametersReturnReceiver();
   805                 JCExpression expr = (tree.getMode() == ReferenceMode.INVOKE)
   768                 JCExpression expr = (tree.getMode() == ReferenceMode.INVOKE)
   806                         ? expressionInvoke(rcvr)
   769                         ? expressionInvoke(rcvr)
   807                         : expressionNew();
   770                         : expressionNew();
   808 
   771 
   809                 JCLambda slam = make.Lambda(params.toList(), expr);
   772                 JCLambda slam = make.Lambda(params.toList(), expr);
   812                 slam.pos = tree.pos;
   775                 slam.pos = tree.pos;
   813                 return slam;
   776                 return slam;
   814             } finally {
   777             } finally {
   815                 make.at(prevPos);
   778                 make.at(prevPos);
   816             }
   779             }
       
   780         }
       
   781 
       
   782         /**
       
   783          * Generate the parameter list for the converted member reference.
       
   784          *
       
   785          * @return The receiver variable symbol, if any
       
   786          */
       
   787         VarSymbol addParametersReturnReceiver() {
       
   788             Type samDesc = localContext.bridgedRefSig();
       
   789             List<Type> samPTypes = samDesc.getParameterTypes();
       
   790             List<Type> descPTypes = tree.getDescriptorType(types).getParameterTypes();
       
   791 
       
   792             // Determine the receiver, if any
       
   793             VarSymbol rcvr;
       
   794             switch (tree.kind) {
       
   795                 case BOUND:
       
   796                     // The receiver is explicit in the method reference
       
   797                     rcvr = addParameter("rec$", tree.getQualifierExpression().type, false);
       
   798                     receiverExpression = attr.makeNullCheck(tree.getQualifierExpression());
       
   799                     break;
       
   800                 case UNBOUND:
       
   801                     // The receiver is the first parameter, extract it and
       
   802                     // adjust the SAM and unerased type lists accordingly
       
   803                     rcvr = addParameter("rec$", samDesc.getParameterTypes().head, false);
       
   804                     samPTypes = samPTypes.tail;
       
   805                     descPTypes = descPTypes.tail;
       
   806                     break;
       
   807                 default:
       
   808                     rcvr = null;
       
   809                     break;
       
   810             }
       
   811             List<Type> implPTypes = tree.sym.type.getParameterTypes();
       
   812             int implSize = implPTypes.size();
       
   813             int samSize = samPTypes.size();
       
   814             // Last parameter to copy from referenced method, exclude final var args
       
   815             int last = localContext.needsVarArgsConversion() ? implSize - 1 : implSize;
       
   816 
       
   817             // Failsafe -- assure match-up
       
   818             boolean checkForIntersection = tree.varargsElement != null || implSize == descPTypes.size();
       
   819 
       
   820             // Use parameter types of the implementation method unless the unerased
       
   821             // SAM parameter type is an intersection type, in that case use the
       
   822             // erased SAM parameter type so that the supertype relationship
       
   823             // the implementation method parameters is not obscured.
       
   824             // Note: in this loop, the lists implPTypes, samPTypes, and descPTypes
       
   825             // are used as pointers to the current parameter type information
       
   826             // and are thus not usable afterwards.
       
   827             for (int i = 0; implPTypes.nonEmpty() && i < last; ++i) {
       
   828                 // By default use the implementation method parmeter type
       
   829                 Type parmType = implPTypes.head;
       
   830                 // If the unerased parameter type is a type variable whose
       
   831                 // bound is an intersection (eg. <T extends A & B>) then
       
   832                 // use the SAM parameter type
       
   833                 if (checkForIntersection && descPTypes.head.getKind() == TypeKind.TYPEVAR) {
       
   834                     TypeVar tv = (TypeVar) descPTypes.head;
       
   835                     if (tv.bound.getKind() == TypeKind.INTERSECTION) {
       
   836                         parmType = samPTypes.head;
       
   837                     }
       
   838                 }
       
   839                 addParameter("x$" + i, parmType, true);
       
   840 
       
   841                 // Advance to the next parameter
       
   842                 implPTypes = implPTypes.tail;
       
   843                 samPTypes = samPTypes.tail;
       
   844                 descPTypes = descPTypes.tail;
       
   845             }
       
   846             // Flatten out the var args
       
   847             for (int i = last; i < samSize; ++i) {
       
   848                 addParameter("xva$" + i, tree.varargsElement, true);
       
   849             }
       
   850 
       
   851             return rcvr;
   817         }
   852         }
   818 
   853 
   819         JCExpression getReceiverExpression() {
   854         JCExpression getReceiverExpression() {
   820             return receiverExpression;
   855             return receiverExpression;
   821         }
   856         }
  2062                 return  tree.sym.kind == MTH &&
  2097                 return  tree.sym.kind == MTH &&
  2063                         types.isSignaturePolymorphic((MethodSymbol)tree.sym);
  2098                         types.isSignaturePolymorphic((MethodSymbol)tree.sym);
  2064             }
  2099             }
  2065 
  2100 
  2066             /**
  2101             /**
       
  2102              * Erasure destroys the implementation parameter subtype
       
  2103              * relationship for intersection types
       
  2104              */
       
  2105             boolean interfaceParameterIsIntersectionType() {
       
  2106                 List<Type> tl = tree.getDescriptorType(types).getParameterTypes();
       
  2107                 if (tree.kind == ReferenceKind.UNBOUND) {
       
  2108                     tl = tl.tail;
       
  2109                 }
       
  2110                 for (; tl.nonEmpty(); tl = tl.tail) {
       
  2111                     Type pt = tl.head;
       
  2112                     if (pt.getKind() == TypeKind.TYPEVAR) {
       
  2113                         TypeVar tv = (TypeVar) pt;
       
  2114                         if (tv.bound.getKind() == TypeKind.INTERSECTION) {
       
  2115                             return true;
       
  2116                         }
       
  2117                     }
       
  2118                 }
       
  2119                 return false;
       
  2120             }
       
  2121 
       
  2122             /**
  2067              * Does this reference need to be converted to a lambda
  2123              * Does this reference need to be converted to a lambda
  2068              * (i.e. var args need to be expanded or "super" is used)
  2124              * (i.e. var args need to be expanded or "super" is used)
  2069              */
  2125              */
  2070             final boolean needsConversionToLambda() {
  2126             final boolean needsConversionToLambda() {
  2071                 return isSuper || needsVarArgsConversion() || isArrayOp() ||
  2127                 return interfaceParameterIsIntersectionType() ||
       
  2128                         isSuper ||
       
  2129                         needsVarArgsConversion() ||
       
  2130                         isArrayOp() ||
  2072                         isPrivateInOtherClass() ||
  2131                         isPrivateInOtherClass() ||
  2073                         !receiverAccessible() ||
  2132                         !receiverAccessible() ||
  2074                         (tree.getMode() == ReferenceMode.NEW &&
  2133                         (tree.getMode() == ReferenceMode.NEW &&
  2075                           tree.kind != ReferenceKind.ARRAY_CTOR &&
  2134                           tree.kind != ReferenceKind.ARRAY_CTOR &&
  2076                           (tree.sym.owner.isLocal() || tree.sym.owner.isInner()));
  2135                           (tree.sym.owner.isLocal() || tree.sym.owner.isInner()));