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

changeset 2614
b5c8adb2206a
parent 2607
10e9228e77b0
child 2701
6906fc8bc514
child 2733
7974f6da2d76
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Tue Nov 25 08:30:52 2014 -0500
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Tue Nov 25 13:37:34 2014 -0800
     1.3 @@ -41,6 +41,7 @@
     1.4  import com.sun.tools.javac.code.Symtab;
     1.5  import com.sun.tools.javac.code.Type;
     1.6  import com.sun.tools.javac.code.Type.MethodType;
     1.7 +import com.sun.tools.javac.code.Type.TypeVar;
     1.8  import com.sun.tools.javac.code.Types;
     1.9  import com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzerPreprocessor.*;
    1.10  import com.sun.tools.javac.comp.Lower.BasicFreeVarCollector;
    1.11 @@ -61,6 +62,7 @@
    1.12  import static com.sun.tools.javac.code.Kinds.*;
    1.13  import static com.sun.tools.javac.code.TypeTag.*;
    1.14  import static com.sun.tools.javac.tree.JCTree.Tag.*;
    1.15 +import javax.lang.model.type.TypeKind;
    1.16  
    1.17  /**
    1.18   * This pass desugars lambda expressions into static methods
    1.19 @@ -761,49 +763,10 @@
    1.20              int prevPos = make.pos;
    1.21              try {
    1.22                  make.at(tree);
    1.23 -                Type samDesc = localContext.bridgedRefSig();
    1.24 -                List<Type> samPTypes = samDesc.getParameterTypes();
    1.25 -
    1.26 -                // an extra argument is prepended in the case where the member
    1.27 -                // reference is an unbound instance method reference (in which
    1.28 -                // case the receiver expression in passed.
    1.29 -                VarSymbol rcvr;
    1.30 -                switch (tree.kind) {
    1.31 -                    case BOUND:
    1.32 -                        rcvr = addParameter("rec$", tree.getQualifierExpression().type, false);
    1.33 -                        receiverExpression = attr.makeNullCheck(tree.getQualifierExpression());
    1.34 -                        break;
    1.35 -                    case UNBOUND:
    1.36 -                        rcvr = addParameter("rec$", samPTypes.head, false);
    1.37 -                        samPTypes = samPTypes.tail;
    1.38 -                        break;
    1.39 -                    default:
    1.40 -                        rcvr = null;
    1.41 -                        break;
    1.42 -                }
    1.43 -
    1.44 -                // generate the parameter list for the coverted member reference.
    1.45 -                // the signature will match the signature of the target sam descriptor
    1.46 -
    1.47 -                List<Type> refPTypes = tree.sym.type.getParameterTypes();
    1.48 -                int refSize = refPTypes.size();
    1.49 -                int samSize = samPTypes.size();
    1.50 -                // Last parameter to copy from referenced method
    1.51 -                int last = localContext.needsVarArgsConversion() ? refSize - 1 : refSize;
    1.52 -
    1.53 -                List<Type> l = refPTypes;
    1.54 -                // Use parameter types of the referenced method, excluding final var args
    1.55 -                for (int i = 0; l.nonEmpty() && i < last; ++i) {
    1.56 -                    addParameter("x$" + i, l.head, true);
    1.57 -                    l = l.tail;
    1.58 -                }
    1.59 -                // Flatten out the var args
    1.60 -                for (int i = last; i < samSize; ++i) {
    1.61 -                    addParameter("xva$" + i, tree.varargsElement, true);
    1.62 -                }
    1.63  
    1.64                  //body generation - this can be either a method call or a
    1.65                  //new instance creation expression, depending on the member reference kind
    1.66 +                VarSymbol rcvr = addParametersReturnReceiver();
    1.67                  JCExpression expr = (tree.getMode() == ReferenceMode.INVOKE)
    1.68                          ? expressionInvoke(rcvr)
    1.69                          : expressionNew();
    1.70 @@ -818,6 +781,78 @@
    1.71              }
    1.72          }
    1.73  
    1.74 +        /**
    1.75 +         * Generate the parameter list for the converted member reference.
    1.76 +         *
    1.77 +         * @return The receiver variable symbol, if any
    1.78 +         */
    1.79 +        VarSymbol addParametersReturnReceiver() {
    1.80 +            Type samDesc = localContext.bridgedRefSig();
    1.81 +            List<Type> samPTypes = samDesc.getParameterTypes();
    1.82 +            List<Type> descPTypes = tree.getDescriptorType(types).getParameterTypes();
    1.83 +
    1.84 +            // Determine the receiver, if any
    1.85 +            VarSymbol rcvr;
    1.86 +            switch (tree.kind) {
    1.87 +                case BOUND:
    1.88 +                    // The receiver is explicit in the method reference
    1.89 +                    rcvr = addParameter("rec$", tree.getQualifierExpression().type, false);
    1.90 +                    receiverExpression = attr.makeNullCheck(tree.getQualifierExpression());
    1.91 +                    break;
    1.92 +                case UNBOUND:
    1.93 +                    // The receiver is the first parameter, extract it and
    1.94 +                    // adjust the SAM and unerased type lists accordingly
    1.95 +                    rcvr = addParameter("rec$", samDesc.getParameterTypes().head, false);
    1.96 +                    samPTypes = samPTypes.tail;
    1.97 +                    descPTypes = descPTypes.tail;
    1.98 +                    break;
    1.99 +                default:
   1.100 +                    rcvr = null;
   1.101 +                    break;
   1.102 +            }
   1.103 +            List<Type> implPTypes = tree.sym.type.getParameterTypes();
   1.104 +            int implSize = implPTypes.size();
   1.105 +            int samSize = samPTypes.size();
   1.106 +            // Last parameter to copy from referenced method, exclude final var args
   1.107 +            int last = localContext.needsVarArgsConversion() ? implSize - 1 : implSize;
   1.108 +
   1.109 +            // Failsafe -- assure match-up
   1.110 +            boolean checkForIntersection = tree.varargsElement != null || implSize == descPTypes.size();
   1.111 +
   1.112 +            // Use parameter types of the implementation method unless the unerased
   1.113 +            // SAM parameter type is an intersection type, in that case use the
   1.114 +            // erased SAM parameter type so that the supertype relationship
   1.115 +            // the implementation method parameters is not obscured.
   1.116 +            // Note: in this loop, the lists implPTypes, samPTypes, and descPTypes
   1.117 +            // are used as pointers to the current parameter type information
   1.118 +            // and are thus not usable afterwards.
   1.119 +            for (int i = 0; implPTypes.nonEmpty() && i < last; ++i) {
   1.120 +                // By default use the implementation method parmeter type
   1.121 +                Type parmType = implPTypes.head;
   1.122 +                // If the unerased parameter type is a type variable whose
   1.123 +                // bound is an intersection (eg. <T extends A & B>) then
   1.124 +                // use the SAM parameter type
   1.125 +                if (checkForIntersection && descPTypes.head.getKind() == TypeKind.TYPEVAR) {
   1.126 +                    TypeVar tv = (TypeVar) descPTypes.head;
   1.127 +                    if (tv.bound.getKind() == TypeKind.INTERSECTION) {
   1.128 +                        parmType = samPTypes.head;
   1.129 +                    }
   1.130 +                }
   1.131 +                addParameter("x$" + i, parmType, true);
   1.132 +
   1.133 +                // Advance to the next parameter
   1.134 +                implPTypes = implPTypes.tail;
   1.135 +                samPTypes = samPTypes.tail;
   1.136 +                descPTypes = descPTypes.tail;
   1.137 +            }
   1.138 +            // Flatten out the var args
   1.139 +            for (int i = last; i < samSize; ++i) {
   1.140 +                addParameter("xva$" + i, tree.varargsElement, true);
   1.141 +            }
   1.142 +
   1.143 +            return rcvr;
   1.144 +        }
   1.145 +
   1.146          JCExpression getReceiverExpression() {
   1.147              return receiverExpression;
   1.148          }
   1.149 @@ -2067,11 +2102,35 @@
   1.150              }
   1.151  
   1.152              /**
   1.153 +             * Erasure destroys the implementation parameter subtype
   1.154 +             * relationship for intersection types
   1.155 +             */
   1.156 +            boolean interfaceParameterIsIntersectionType() {
   1.157 +                List<Type> tl = tree.getDescriptorType(types).getParameterTypes();
   1.158 +                if (tree.kind == ReferenceKind.UNBOUND) {
   1.159 +                    tl = tl.tail;
   1.160 +                }
   1.161 +                for (; tl.nonEmpty(); tl = tl.tail) {
   1.162 +                    Type pt = tl.head;
   1.163 +                    if (pt.getKind() == TypeKind.TYPEVAR) {
   1.164 +                        TypeVar tv = (TypeVar) pt;
   1.165 +                        if (tv.bound.getKind() == TypeKind.INTERSECTION) {
   1.166 +                            return true;
   1.167 +                        }
   1.168 +                    }
   1.169 +                }
   1.170 +                return false;
   1.171 +            }
   1.172 +
   1.173 +            /**
   1.174               * Does this reference need to be converted to a lambda
   1.175               * (i.e. var args need to be expanded or "super" is used)
   1.176               */
   1.177              final boolean needsConversionToLambda() {
   1.178 -                return isSuper || needsVarArgsConversion() || isArrayOp() ||
   1.179 +                return interfaceParameterIsIntersectionType() ||
   1.180 +                        isSuper ||
   1.181 +                        needsVarArgsConversion() ||
   1.182 +                        isArrayOp() ||
   1.183                          isPrivateInOtherClass() ||
   1.184                          !receiverAccessible() ||
   1.185                          (tree.getMode() == ReferenceMode.NEW &&

mercurial