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())); |