Search in sources :

Example 1 with ReferenceExpression

use of org.eclipse.jdt.internal.compiler.ast.ReferenceExpression in project bazel-jdt-java-toolchain by salesforce.

the class ConstraintExpressionFormula method inputVariables.

@Override
Collection<InferenceVariable> inputVariables(final InferenceContext18 context) {
    // from 18.5.2.
    if (this.left instanceof LambdaExpression) {
        if (this.right instanceof InferenceVariable) {
            return Collections.singletonList((InferenceVariable) this.right);
        }
        if (this.right.isFunctionalInterface(context.scope)) {
            LambdaExpression lambda = (LambdaExpression) this.left;
            ReferenceBinding targetType = (ReferenceBinding) this.right;
            ParameterizedTypeBinding withWildCards = InferenceContext18.parameterizedWithWildcard(targetType);
            if (withWildCards != null) {
                targetType = ConstraintExpressionFormula.findGroundTargetType(context, lambda.enclosingScope, lambda, withWildCards);
            }
            if (targetType == null) {
                return EMPTY_VARIABLE_LIST;
            }
            MethodBinding sam = targetType.getSingleAbstractMethod(context.scope, true);
            final Set<InferenceVariable> variables = new LinkedHashSet<>();
            if (lambda.argumentsTypeElided()) {
                // i)
                int len = sam.parameters.length;
                for (int i = 0; i < len; i++) {
                    sam.parameters[i].collectInferenceVariables(variables);
                }
            }
            if (sam.returnType != TypeBinding.VOID) {
                // ii)
                final TypeBinding r = sam.returnType;
                LambdaExpression resolved = lambda.resolveExpressionExpecting(this.right, context.scope, context);
                Expression[] resultExpressions = resolved != null ? resolved.resultExpressions() : null;
                for (int i = 0, length = resultExpressions == null ? 0 : resultExpressions.length; i < length; i++) {
                    variables.addAll(new ConstraintExpressionFormula(resultExpressions[i], r, COMPATIBLE).inputVariables(context));
                }
            }
            return variables;
        }
    } else if (this.left instanceof ReferenceExpression) {
        if (this.right instanceof InferenceVariable) {
            return Collections.singletonList((InferenceVariable) this.right);
        }
        if (this.right.isFunctionalInterface(context.scope) && !this.left.isExactMethodReference()) {
            MethodBinding sam = this.right.getSingleAbstractMethod(context.scope, true);
            final Set<InferenceVariable> variables = new LinkedHashSet<>();
            int len = sam.parameters.length;
            for (int i = 0; i < len; i++) {
                sam.parameters[i].collectInferenceVariables(variables);
            }
            return variables;
        }
    } else if (this.left instanceof ConditionalExpression && this.left.isPolyExpression()) {
        ConditionalExpression expr = (ConditionalExpression) this.left;
        Set<InferenceVariable> variables = new LinkedHashSet<>();
        variables.addAll(new ConstraintExpressionFormula(expr.valueIfTrue, this.right, COMPATIBLE).inputVariables(context));
        variables.addAll(new ConstraintExpressionFormula(expr.valueIfFalse, this.right, COMPATIBLE).inputVariables(context));
        return variables;
    } else if (this.left instanceof SwitchExpression && this.left.isPolyExpression()) {
        SwitchExpression expr = (SwitchExpression) this.left;
        Set<InferenceVariable> variables = new LinkedHashSet<>();
        for (Expression re : expr.resultExpressions) {
            variables.addAll(new ConstraintExpressionFormula(re, this.right, COMPATIBLE).inputVariables(context));
        }
        return variables;
    }
    return EMPTY_VARIABLE_LIST;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Set(java.util.Set) LinkedHashSet(java.util.LinkedHashSet) SwitchExpression(org.eclipse.jdt.internal.compiler.ast.SwitchExpression) ConditionalExpression(org.eclipse.jdt.internal.compiler.ast.ConditionalExpression) ConditionalExpression(org.eclipse.jdt.internal.compiler.ast.ConditionalExpression) LambdaExpression(org.eclipse.jdt.internal.compiler.ast.LambdaExpression) Expression(org.eclipse.jdt.internal.compiler.ast.Expression) SwitchExpression(org.eclipse.jdt.internal.compiler.ast.SwitchExpression) ReferenceExpression(org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) ReferenceExpression(org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) LambdaExpression(org.eclipse.jdt.internal.compiler.ast.LambdaExpression)

Example 2 with ReferenceExpression

use of org.eclipse.jdt.internal.compiler.ast.ReferenceExpression in project bazel-jdt-java-toolchain by salesforce.

the class ConstraintExpressionFormula method reduce.

@Override
public Object reduce(InferenceContext18 inferenceContext) throws InferenceFailureException {
    if (this.relation == POTENTIALLY_COMPATIBLE) {
        return this.left.isPotentiallyCompatibleWith(this.right, inferenceContext.scope) ? TRUE : FALSE;
    }
    // JLS 18.2.1
    if (this.right.isProperType(true)) {
        if (this.left.isCompatibleWith(this.right, inferenceContext.scope) || this.left.isBoxingCompatibleWith(this.right, inferenceContext.scope)) {
            if (this.left.resolvedType != null && this.left.resolvedType.needsUncheckedConversion(this.right)) {
                inferenceContext.usesUncheckedConversion = true;
            }
            return TRUE;
        }
        return FALSE;
    }
    if (!canBePolyExpression(this.left)) {
        TypeBinding exprType = this.left.resolvedType;
        if (exprType == null || !exprType.isValidBinding()) {
            if (this.left instanceof MessageSend && ((MessageSend) this.left).actualReceiverType instanceof InferenceVariable)
                // nothing valuable to infer from this
                return null;
            return FALSE;
        }
        return ConstraintTypeFormula.create(exprType, this.right, COMPATIBLE, this.isSoft);
    } else {
        // - parenthesized expression : these are transparent in our AST
        if (this.left instanceof Invocation) {
            Invocation invocation = (Invocation) this.left;
            MethodBinding previousMethod = invocation.binding();
            if (// can happen, e.g., if inside a copied lambda with ignored errors
            previousMethod == null)
                // -> proceed with no new constraints
                return null;
            MethodBinding method = previousMethod;
            // ignore previous (inner) inference result and do a fresh start:
            // avoid original(), since we only want to discard one level of instantiation
            // (method type variables - not class type variables)!
            method = previousMethod.shallowOriginal();
            SuspendedInferenceRecord prevInvocation = inferenceContext.enterPolyInvocation(invocation, invocation.arguments());
            // Invocation Applicability Inference: 18.5.1 & Invocation Type Inference: 18.5.2
            InferenceContext18 innerCtx = null;
            try {
                Expression[] arguments = invocation.arguments();
                TypeBinding[] argumentTypes = arguments == null ? Binding.NO_PARAMETERS : new TypeBinding[arguments.length];
                for (int i = 0; i < argumentTypes.length; i++) argumentTypes[i] = arguments[i].resolvedType;
                if (previousMethod instanceof ParameterizedGenericMethodBinding) {
                    // find the previous inner inference context to see what inference kind this invocation needs:
                    innerCtx = invocation.getInferenceContext((ParameterizedGenericMethodBinding) previousMethod);
                    if (innerCtx == null) {
                        /* No inference context -> the method was likely manufactured by Scope.findExactMethod -> assume it wasn't really poly after all.
							   -> proceed as for non-poly expressions.
							*/
                        TypeBinding exprType = this.left.resolvedType;
                        if (exprType == null || !exprType.isValidBinding())
                            return FALSE;
                        return ConstraintTypeFormula.create(exprType, this.right, COMPATIBLE, this.isSoft);
                    }
                    if (innerCtx.stepCompleted >= InferenceContext18.APPLICABILITY_INFERRED) {
                        inferenceContext.integrateInnerInferenceB2(innerCtx);
                    } else {
                        // should not reach here.
                        return FALSE;
                    }
                // b2 has been lifted, inferring poly invocation type amounts to lifting b3.
                } else {
                    inferenceContext.inferenceKind = inferenceContext.getInferenceKind(previousMethod, argumentTypes);
                    boolean isDiamond = method.isConstructor() && this.left.isPolyExpression(method);
                    inferInvocationApplicability(inferenceContext, method, argumentTypes, isDiamond, inferenceContext.inferenceKind);
                // b2 has been lifted, inferring poly invocation type amounts to lifting b3.
                }
                if (!inferenceContext.computeB3(invocation, this.right, method))
                    return FALSE;
                // already incorporated
                return null;
            } finally {
                inferenceContext.resumeSuspendedInference(prevInvocation, innerCtx);
            }
        } else if (this.left instanceof ConditionalExpression) {
            ConditionalExpression conditional = (ConditionalExpression) this.left;
            return new ConstraintFormula[] { new ConstraintExpressionFormula(conditional.valueIfTrue, this.right, this.relation, this.isSoft), new ConstraintExpressionFormula(conditional.valueIfFalse, this.right, this.relation, this.isSoft) };
        } else if (this.left instanceof SwitchExpression) {
            SwitchExpression se = (SwitchExpression) this.left;
            ConstraintFormula[] cfs = new ConstraintFormula[se.resultExpressions.size()];
            int i = 0;
            for (Expression re : se.resultExpressions) {
                cfs[i++] = new ConstraintExpressionFormula(re, this.right, this.relation, this.isSoft);
            }
            return cfs;
        } else if (this.left instanceof LambdaExpression) {
            LambdaExpression lambda = (LambdaExpression) this.left;
            BlockScope scope = lambda.enclosingScope;
            if (this.right instanceof InferenceVariable)
                // assume inner inference will handle the fine print
                return TRUE;
            if (!this.right.isFunctionalInterface(scope))
                return FALSE;
            ReferenceBinding t = (ReferenceBinding) this.right;
            ParameterizedTypeBinding withWildCards = InferenceContext18.parameterizedWithWildcard(t);
            if (withWildCards != null) {
                t = findGroundTargetType(inferenceContext, scope, lambda, withWildCards);
            }
            if (t == null)
                return FALSE;
            MethodBinding functionType = t.getSingleAbstractMethod(scope, true);
            if (functionType == null)
                return FALSE;
            TypeBinding[] parameters = functionType.parameters;
            if (parameters.length != lambda.arguments().length)
                return FALSE;
            if (lambda.argumentsTypeElided())
                for (int i = 0; i < parameters.length; i++) if (!parameters[i].isProperType(true))
                    return FALSE;
            lambda = lambda.resolveExpressionExpecting(t, inferenceContext.scope, inferenceContext);
            if (lambda == null)
                // not strictly unreduceable, but proceeding with TRUE would likely produce secondary errors
                return FALSE;
            if (functionType.returnType == TypeBinding.VOID) {
                if (!lambda.isVoidCompatible())
                    return FALSE;
            } else {
                if (!lambda.isValueCompatible())
                    return FALSE;
            }
            List<ConstraintFormula> result = new ArrayList<>();
            if (!lambda.argumentsTypeElided()) {
                Argument[] arguments = lambda.arguments();
                for (int i = 0; i < parameters.length; i++) result.add(ConstraintTypeFormula.create(parameters[i], arguments[i].type.resolvedType, SAME));
                // in addition, ⟨T' <: T⟩:
                if (lambda.resolvedType != null)
                    result.add(ConstraintTypeFormula.create(lambda.resolvedType, this.right, SUBTYPE));
            }
            if (functionType.returnType != TypeBinding.VOID) {
                TypeBinding r = functionType.returnType;
                Expression[] exprs = lambda.resultExpressions();
                for (int i = 0, length = exprs == null ? 0 : exprs.length; i < length; i++) {
                    Expression expr = exprs[i];
                    if (r.isProperType(true) && expr.resolvedType != null) {
                        TypeBinding exprType = expr.resolvedType;
                        // "not compatible in an assignment context with R"?
                        if (!(expr.isConstantValueOfTypeAssignableToType(exprType, r) || exprType.isCompatibleWith(r) || expr.isBoxingCompatible(exprType, r, expr, scope)))
                            return FALSE;
                    } else {
                        result.add(new ConstraintExpressionFormula(expr, r, COMPATIBLE, this.isSoft));
                    }
                }
            }
            if (result.size() == 0)
                return TRUE;
            return result.toArray(new ConstraintFormula[result.size()]);
        } else if (this.left instanceof ReferenceExpression) {
            return reduceReferenceExpressionCompatibility((ReferenceExpression) this.left, inferenceContext);
        }
    }
    return FALSE;
}
Also used : Invocation(org.eclipse.jdt.internal.compiler.ast.Invocation) SwitchExpression(org.eclipse.jdt.internal.compiler.ast.SwitchExpression) MessageSend(org.eclipse.jdt.internal.compiler.ast.MessageSend) ArrayList(java.util.ArrayList) List(java.util.List) SuspendedInferenceRecord(org.eclipse.jdt.internal.compiler.lookup.InferenceContext18.SuspendedInferenceRecord) ConditionalExpression(org.eclipse.jdt.internal.compiler.ast.ConditionalExpression) ConditionalExpression(org.eclipse.jdt.internal.compiler.ast.ConditionalExpression) LambdaExpression(org.eclipse.jdt.internal.compiler.ast.LambdaExpression) Expression(org.eclipse.jdt.internal.compiler.ast.Expression) SwitchExpression(org.eclipse.jdt.internal.compiler.ast.SwitchExpression) ReferenceExpression(org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) ReferenceExpression(org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) LambdaExpression(org.eclipse.jdt.internal.compiler.ast.LambdaExpression)

Example 3 with ReferenceExpression

use of org.eclipse.jdt.internal.compiler.ast.ReferenceExpression in project bazel-jdt-java-toolchain by salesforce.

the class CodeStream method generateSyntheticBodyForDeserializeLambda.

// TODO what about blowing the method limit? Ignore for now?
/**
 * This is intended to match what javac generates. First there is a switch statement on the hashcode of the lambda method name - based on that
 * an id is computed (0..N). An unrecognized hash gets the id -1. Then a second switch is on the id and each case here checks all the properties
 * of the serialized lambda. If they all checkout OK an invokedynamic call to a bootstrap method targeting the altMetafactory. If any of the tests
 * fail an IllegalArgumentException is thrown. This exception is not typically seen by the 'user', instead they seem to see a NPE when
 * the lambda does not deserialize properly.
 */
public void generateSyntheticBodyForDeserializeLambda(SyntheticMethodBinding methodBinding, SyntheticMethodBinding[] syntheticMethodBindings) {
    initializeMaxLocals(methodBinding);
    // Compute a map of hashcodes to a list of synthetic methods whose names share a hashcode
    Map hashcodesTosynthetics = new LinkedHashMap();
    for (int i = 0, max = syntheticMethodBindings.length; i < max; i++) {
        SyntheticMethodBinding syntheticMethodBinding = syntheticMethodBindings[i];
        if (syntheticMethodBinding.lambda != null && syntheticMethodBinding.lambda.isSerializable || syntheticMethodBinding.serializableMethodRef != null) {
            // TODO can I use > Java 1.4 features here?
            Integer hashcode = Integer.valueOf(new String(syntheticMethodBinding.selector).hashCode());
            List syntheticssForThisHashcode = (List) hashcodesTosynthetics.get(hashcode);
            if (syntheticssForThisHashcode == null) {
                syntheticssForThisHashcode = new ArrayList();
                hashcodesTosynthetics.put(hashcode, syntheticssForThisHashcode);
            }
            syntheticssForThisHashcode.add(syntheticMethodBinding);
        }
    }
    ClassScope scope = ((SourceTypeBinding) methodBinding.declaringClass).scope;
    // Generate the first switch, on method name hashcode
    aload_0();
    invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, ConstantPool.GetImplMethodName, ConstantPool.GetImplMethodNameSignature, getPopularBinding(ConstantPool.JavaLangStringConstantPoolName));
    astore_1();
    // $NON-NLS-1$
    LocalVariableBinding lvb1 = new LocalVariableBinding("hashcode".toCharArray(), scope.getJavaLangString(), 0, false);
    lvb1.resolvedPosition = 1;
    addVariable(lvb1);
    iconst_m1();
    istore_2();
    // $NON-NLS-1$
    LocalVariableBinding lvb2 = new LocalVariableBinding("id".toCharArray(), TypeBinding.INT, 0, false);
    lvb2.resolvedPosition = 2;
    addVariable(lvb2);
    aload_1();
    invokeStringHashCode();
    BranchLabel label = new BranchLabel(this);
    CaseLabel defaultLabel = new CaseLabel(this);
    int numberOfHashcodes = hashcodesTosynthetics.size();
    CaseLabel[] switchLabels = new CaseLabel[numberOfHashcodes];
    int[] keys = new int[numberOfHashcodes];
    int[] sortedIndexes = new int[numberOfHashcodes];
    Set hashcodes = hashcodesTosynthetics.keySet();
    Iterator hashcodeIterator = hashcodes.iterator();
    int index = 0;
    while (hashcodeIterator.hasNext()) {
        Integer hashcode = (Integer) hashcodeIterator.next();
        switchLabels[index] = new CaseLabel(this);
        keys[index] = hashcode.intValue();
        sortedIndexes[index] = index;
        index++;
    }
    int[] localKeysCopy;
    System.arraycopy(keys, 0, (localKeysCopy = new int[numberOfHashcodes]), 0, numberOfHashcodes);
    sort(localKeysCopy, 0, numberOfHashcodes - 1, sortedIndexes);
    // TODO need to use a tableswitch at some size threshold?
    lookupswitch(defaultLabel, keys, sortedIndexes, switchLabels);
    // TODO cope with multiple names that share the same hashcode
    hashcodeIterator = hashcodes.iterator();
    index = 0;
    while (hashcodeIterator.hasNext()) {
        Integer hashcode = (Integer) hashcodeIterator.next();
        List synthetics = (List) hashcodesTosynthetics.get(hashcode);
        switchLabels[index].place();
        BranchLabel nextOne = new BranchLabel(this);
        // the same name?
        for (int j = 0, max = synthetics.size(); j < max; j++) {
            SyntheticMethodBinding syntheticMethodBinding = (SyntheticMethodBinding) synthetics.get(j);
            aload_1();
            ldc(new String(syntheticMethodBinding.selector));
            invokeStringEquals();
            ifeq(nextOne);
            loadInt(index);
            istore_2();
            goto_(label);
            nextOne.place();
            nextOne = new BranchLabel(this);
        }
        index++;
        goto_(label);
    }
    defaultLabel.place();
    label.place();
    int syntheticsCount = hashcodes.size();
    // Second block is switching on the lambda id, -1 is the error (unrecognized) case
    switchLabels = new CaseLabel[syntheticsCount];
    keys = new int[syntheticsCount];
    sortedIndexes = new int[syntheticsCount];
    BranchLabel errorLabel = new BranchLabel(this);
    defaultLabel = new CaseLabel(this);
    iload_2();
    for (int j = 0; j < syntheticsCount; j++) {
        switchLabels[j] = new CaseLabel(this);
        keys[j] = j;
        sortedIndexes[j] = j;
    }
    System.arraycopy(keys, 0, (localKeysCopy = new int[syntheticsCount]), 0, syntheticsCount);
    // TODO no need to sort here? They should all be in order
    sort(localKeysCopy, 0, syntheticsCount - 1, sortedIndexes);
    // TODO need to use a tableswitch at some size threshold?
    lookupswitch(defaultLabel, keys, sortedIndexes, switchLabels);
    hashcodeIterator = hashcodes.iterator();
    int hashcodeIndex = 0;
    while (hashcodeIterator.hasNext()) {
        Integer hashcode = (Integer) hashcodeIterator.next();
        List synthetics = (List) hashcodesTosynthetics.get(hashcode);
        switchLabels[hashcodeIndex++].place();
        BranchLabel nextOne = synthetics.size() > 1 ? new BranchLabel(this) : errorLabel;
        // Loop through all lambdas that share the same hashcode
        for (int j = 0, count = synthetics.size(); j < count; j++) {
            SyntheticMethodBinding syntheticMethodBinding = (SyntheticMethodBinding) synthetics.get(j);
            // Compare ImplMethodKind
            aload_0();
            FunctionalExpression funcEx = syntheticMethodBinding.lambda != null ? syntheticMethodBinding.lambda : syntheticMethodBinding.serializableMethodRef;
            MethodBinding mb = funcEx.binding;
            invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, ConstantPool.GetImplMethodKind, ConstantPool.GetImplMethodKindSignature, TypeIds.T_int, TypeBinding.INT);
            byte methodKind = 0;
            if (mb.isStatic()) {
                methodKind = ClassFileConstants.MethodHandleRefKindInvokeStatic;
            } else if (mb.isPrivate()) {
                methodKind = ClassFileConstants.MethodHandleRefKindInvokeSpecial;
            } else if (mb.isConstructor()) {
                methodKind = ClassFileConstants.MethodHandleRefKindNewInvokeSpecial;
            } else if (mb.declaringClass.isInterface()) {
                methodKind = ClassFileConstants.MethodHandleRefKindInvokeInterface;
            } else {
                methodKind = ClassFileConstants.MethodHandleRefKindInvokeVirtual;
            }
            // TODO see table below
            bipush(methodKind);
            if_icmpne(nextOne);
            // Compare FunctionalInterfaceClass
            aload_0();
            invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, ConstantPool.GetFunctionalInterfaceClass, ConstantPool.GetFunctionalInterfaceClassSignature, getPopularBinding(ConstantPool.JavaLangStringConstantPoolName));
            String functionalInterface = null;
            final TypeBinding expectedType = funcEx.expectedType();
            if (expectedType instanceof IntersectionTypeBinding18) {
                functionalInterface = new String(((IntersectionTypeBinding18) expectedType).getSAMType(scope).constantPoolName());
            } else {
                functionalInterface = new String(expectedType.constantPoolName());
            }
            // e.g. "com/foo/X$Foo"
            ldc(functionalInterface);
            invokeObjectEquals();
            ifeq(nextOne);
            // Compare FunctionalInterfaceMethodName
            aload_0();
            invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, ConstantPool.GetFunctionalInterfaceMethodName, ConstantPool.GetFunctionalInterfaceMethodNameSignature, getPopularBinding(ConstantPool.JavaLangStringConstantPoolName));
            // e.g. "m"
            ldc(new String(funcEx.descriptor.selector));
            invokeObjectEquals();
            ifeq(nextOne);
            // Compare FunctionalInterfaceMethodSignature
            aload_0();
            invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, ConstantPool.GetFunctionalInterfaceMethodSignature, ConstantPool.GetFunctionalInterfaceMethodSignatureSignature, getPopularBinding(ConstantPool.JavaLangStringConstantPoolName));
            // e.g "()I"
            ldc(new String(funcEx.descriptor.original().signature()));
            invokeObjectEquals();
            ifeq(nextOne);
            // Compare ImplClass
            aload_0();
            invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, ConstantPool.GetImplClass, ConstantPool.GetImplClassSignature, getPopularBinding(ConstantPool.JavaLangStringConstantPoolName));
            // e.g. "com/foo/X"
            ldc(new String(mb.declaringClass.constantPoolName()));
            invokeObjectEquals();
            ifeq(nextOne);
            // Compare ImplMethodSignature
            aload_0();
            invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, ConstantPool.GetImplMethodSignature, ConstantPool.GetImplMethodSignatureSignature, getPopularBinding(ConstantPool.JavaLangStringConstantPoolName));
            // e.g. "(I)I"
            ldc(new String(mb.signature()));
            invokeObjectEquals();
            ifeq(nextOne);
            // Captured arguments
            // $NON-NLS-1$
            StringBuilder sig = new StringBuilder("(");
            index = 0;
            boolean isLambda = funcEx instanceof LambdaExpression;
            TypeBinding receiverType = null;
            SyntheticArgumentBinding[] outerLocalVariables = null;
            if (isLambda) {
                LambdaExpression lambdaEx = (LambdaExpression) funcEx;
                if (lambdaEx.shouldCaptureInstance)
                    receiverType = mb.declaringClass;
                outerLocalVariables = lambdaEx.outerLocalVariables;
            } else {
                ReferenceExpression refEx = (ReferenceExpression) funcEx;
                if (refEx.haveReceiver)
                    receiverType = ((ReferenceExpression) funcEx).receiverType;
            // Should never have outer locals
            }
            if (receiverType != null) {
                aload_0();
                loadInt(index++);
                invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, ConstantPool.GetCapturedArg, ConstantPool.GetCapturedArgSignature, getPopularBinding(ConstantPool.JavaLangStringConstantPoolName));
                checkcast(receiverType);
                sig.append(receiverType.signature());
            }
            for (int p = 0, max = outerLocalVariables == null ? 0 : outerLocalVariables.length; p < max; p++) {
                TypeBinding varType = outerLocalVariables[p].type;
                aload_0();
                loadInt(index);
                invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, ConstantPool.GetCapturedArg, ConstantPool.GetCapturedArgSignature, getPopularBinding(ConstantPool.JavaLangStringConstantPoolName));
                if (varType.isBaseType()) {
                    checkcast(scope.boxing(varType));
                    generateUnboxingConversion(varType.id);
                    if (varType.id == TypeIds.T_JavaLangLong || varType.id == TypeIds.T_JavaLangDouble) {
                        index++;
                    }
                } else {
                    checkcast(varType);
                }
                index++;
                sig.append(varType.signature());
            }
            // $NON-NLS-1$
            sig.append(")");
            if (funcEx.resolvedType instanceof IntersectionTypeBinding18) {
                sig.append(((IntersectionTypeBinding18) funcEx.resolvedType).getSAMType(scope).signature());
            } else {
                sig.append(funcEx.resolvedType.signature());
            }
            // Example: invokeDynamic(0, 0, 1, "m".toCharArray(), "()Lcom/foo/X$Foo;".toCharArray());
            invokeDynamic(funcEx.bootstrapMethodNumber, index, 1, funcEx.descriptor.selector, sig.toString().toCharArray(), funcEx.resolvedType.id, funcEx.resolvedType);
            areturn();
            if (j < count - 1) {
                nextOne.place();
                nextOne = j < count - 2 ? new BranchLabel(this) : errorLabel;
            }
        }
    }
    removeVariable(lvb1);
    removeVariable(lvb2);
    defaultLabel.place();
    errorLabel.place();
    // Code: throw new IllegalArgumentException("Invalid lambda deserialization")
    new_(scope.getJavaLangIllegalArgumentException());
    dup();
    // $NON-NLS-1$ // TODO into a constant?
    ldc("Invalid lambda deserialization");
    // invokespecial: java.lang.IllegalArgumentException.<init>(Ljava/lang/String;)V
    invoke(Opcodes.OPC_invokespecial, // receiverAndArgsSize
    2, // return type size
    0, ConstantPool.JavaLangIllegalArgumentExceptionConstantPoolName, ConstantPool.Init, ConstantPool.IllegalArgumentExceptionConstructorSignature, null);
    athrow();
}
Also used : Set(java.util.Set) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) Iterator(java.util.Iterator) ArrayList(java.util.ArrayList) List(java.util.List) ReferenceExpression(org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) FunctionalExpression(org.eclipse.jdt.internal.compiler.ast.FunctionalExpression) LambdaExpression(org.eclipse.jdt.internal.compiler.ast.LambdaExpression)

Example 4 with ReferenceExpression

use of org.eclipse.jdt.internal.compiler.ast.ReferenceExpression in project bazel-jdt-java-toolchain by salesforce.

the class ConstraintExceptionFormula method inputVariables.

@Override
Collection<InferenceVariable> inputVariables(final InferenceContext18 context) {
    // from 18.5.2.
    if (this.left instanceof LambdaExpression) {
        if (this.right instanceof InferenceVariable) {
            return Collections.singletonList((InferenceVariable) this.right);
        }
        if (this.right.isFunctionalInterface(context.scope)) {
            LambdaExpression lambda = (LambdaExpression) this.left;
            // TODO derive with target type?
            MethodBinding sam = this.right.getSingleAbstractMethod(context.scope, true);
            final Set<InferenceVariable> variables = new LinkedHashSet<>();
            if (lambda.argumentsTypeElided()) {
                // i)
                int len = sam.parameters.length;
                for (int i = 0; i < len; i++) {
                    sam.parameters[i].collectInferenceVariables(variables);
                }
            }
            if (sam.returnType != TypeBinding.VOID) {
                // ii)
                sam.returnType.collectInferenceVariables(variables);
            }
            return variables;
        }
    } else if (this.left instanceof ReferenceExpression) {
        if (this.right instanceof InferenceVariable) {
            return Collections.singletonList((InferenceVariable) this.right);
        }
        if (this.right.isFunctionalInterface(context.scope)) {
            // TODO: && this.left is inexact
            // TODO derive with target type?
            MethodBinding sam = this.right.getSingleAbstractMethod(context.scope, true);
            final Set<InferenceVariable> variables = new LinkedHashSet<>();
            int len = sam.parameters.length;
            for (int i = 0; i < len; i++) {
                sam.parameters[i].collectInferenceVariables(variables);
            }
            sam.returnType.collectInferenceVariables(variables);
            return variables;
        }
    }
    return EMPTY_VARIABLE_LIST;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Set(java.util.Set) LinkedHashSet(java.util.LinkedHashSet) ReferenceExpression(org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) LambdaExpression(org.eclipse.jdt.internal.compiler.ast.LambdaExpression)

Example 5 with ReferenceExpression

use of org.eclipse.jdt.internal.compiler.ast.ReferenceExpression in project bazel-jdt-java-toolchain by salesforce.

the class ConstraintExceptionFormula method reduce.

@Override
public Object reduce(InferenceContext18 inferenceContext) {
    // JLS 18.2.5
    Scope scope = inferenceContext.scope;
    if (!this.right.isFunctionalInterface(scope))
        return FALSE;
    MethodBinding sam = this.right.getSingleAbstractMethod(scope, true);
    if (sam == null)
        return FALSE;
    if (this.left instanceof LambdaExpression) {
        if (((LambdaExpression) this.left).argumentsTypeElided()) {
            int nParam = sam.parameters.length;
            for (int i = 0; i < nParam; i++) if (!sam.parameters[i].isProperType(true))
                return FALSE;
        }
        if (sam.returnType != TypeBinding.VOID && !sam.returnType.isProperType(true))
            return FALSE;
    } else {
        // reference expression
        if (!((ReferenceExpression) this.left).isExactMethodReference()) {
            int nParam = sam.parameters.length;
            for (int i = 0; i < nParam; i++) if (!sam.parameters[i].isProperType(true))
                return FALSE;
            if (sam.returnType != TypeBinding.VOID && !sam.returnType.isProperType(true))
                return FALSE;
        }
    }
    TypeBinding[] thrown = sam.thrownExceptions;
    InferenceVariable[] e = new InferenceVariable[thrown.length];
    int n = 0;
    for (int i = 0; i < thrown.length; i++) if (!thrown[i].isProperType(true))
        // thrown[i] is not a proper type, since it's an exception it must be an inferenceVariable, right?
        e[n++] = (InferenceVariable) thrown[i];
    /* If throw specification does not encode any type parameters, there are no constraints to be gleaned/gathered from the throw sites.
		   See also that thrown exceptions are not allowed to influence compatibility and overload resolution.
		*/
    if (n == 0)
        return TRUE;
    TypeBinding[] ePrime = null;
    if (this.left instanceof LambdaExpression) {
        LambdaExpression lambda = ((LambdaExpression) this.left).resolveExpressionExpecting(this.right, inferenceContext.scope, inferenceContext);
        if (lambda == null)
            // cannot make use of this buggy constraint
            return TRUE;
        Set<TypeBinding> ePrimeSet = lambda.getThrownExceptions();
        ePrime = ePrimeSet.toArray(new TypeBinding[ePrimeSet.size()]);
    } else {
        ReferenceExpression referenceExpression = ((ReferenceExpression) this.left).resolveExpressionExpecting(this.right, scope, inferenceContext);
        MethodBinding method = referenceExpression != null ? referenceExpression.binding : null;
        if (method != null)
            ePrime = method.thrownExceptions;
    }
    if (ePrime == null)
        return TRUE;
    int m = ePrime.length;
    List<ConstraintFormula> result = new ArrayList<>();
    actual: for (int i = 0; i < m; i++) {
        if (ePrime[i].isUncheckedException(false))
            continue;
        for (int j = 0; j < thrown.length; j++) if (thrown[j].isProperType(true) && ePrime[i].isCompatibleWith(thrown[j]))
            continue actual;
        for (int j = 0; j < n; j++) result.add(ConstraintTypeFormula.create(ePrime[i], e[j], SUBTYPE));
    }
    for (int j = 0; j < n; j++) inferenceContext.currentBounds.inThrows.add(e[j].prototype());
    return result.toArray(new ConstraintFormula[result.size()]);
}
Also used : ArrayList(java.util.ArrayList) ReferenceExpression(org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) LambdaExpression(org.eclipse.jdt.internal.compiler.ast.LambdaExpression)

Aggregations

ReferenceExpression (org.eclipse.jdt.internal.compiler.ast.ReferenceExpression)7 LambdaExpression (org.eclipse.jdt.internal.compiler.ast.LambdaExpression)6 Expression (org.eclipse.jdt.internal.compiler.ast.Expression)4 ArrayList (java.util.ArrayList)3 Set (java.util.Set)3 ConditionalExpression (org.eclipse.jdt.internal.compiler.ast.ConditionalExpression)3 SwitchExpression (org.eclipse.jdt.internal.compiler.ast.SwitchExpression)3 LinkedHashSet (java.util.LinkedHashSet)2 List (java.util.List)2 FunctionalExpression (org.eclipse.jdt.internal.compiler.ast.FunctionalExpression)2 Invocation (org.eclipse.jdt.internal.compiler.ast.Invocation)2 Iterator (java.util.Iterator)1 LinkedHashMap (java.util.LinkedHashMap)1 Map (java.util.Map)1 MessageSend (org.eclipse.jdt.internal.compiler.ast.MessageSend)1 CompilerOptions (org.eclipse.jdt.internal.compiler.impl.CompilerOptions)1 SuspendedInferenceRecord (org.eclipse.jdt.internal.compiler.lookup.InferenceContext18.SuspendedInferenceRecord)1