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

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

mercurial