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