use of org.eclipse.jdt.internal.compiler.lookup.InferenceContext18.SuspendedInferenceRecord 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;
}
use of org.eclipse.jdt.internal.compiler.lookup.InferenceContext18.SuspendedInferenceRecord in project bazel-jdt-java-toolchain by salesforce.
the class ConstraintExpressionFormula method reduceReferenceExpressionCompatibility.
private Object reduceReferenceExpressionCompatibility(ReferenceExpression reference, InferenceContext18 inferenceContext) {
TypeBinding t = this.right;
if (t.isProperType(true))
// $NON-NLS-1$
throw new IllegalStateException("Should not reach here with T being a proper type");
if (!t.isFunctionalInterface(inferenceContext.scope))
return FALSE;
MethodBinding functionType = t.getSingleAbstractMethod(inferenceContext.scope, true);
if (functionType == null)
return FALSE;
// potentially-applicable method for the method reference when targeting T (15.13.1),
reference = reference.resolveExpressionExpecting(t, inferenceContext.scope, inferenceContext);
MethodBinding potentiallyApplicable = reference != null ? reference.binding : null;
if (potentiallyApplicable == null)
return FALSE;
if (reference.isExactMethodReference()) {
List<ConstraintFormula> newConstraints = new ArrayList<>();
TypeBinding[] p = functionType.parameters;
int n = p.length;
TypeBinding[] pPrime = potentiallyApplicable.parameters;
int k = pPrime.length;
int offset = 0;
if (n == k + 1) {
newConstraints.add(ConstraintTypeFormula.create(p[0], reference.lhs.resolvedType, COMPATIBLE));
offset = 1;
}
for (int i = offset; i < n; i++) newConstraints.add(ConstraintTypeFormula.create(p[i], pPrime[i - offset], COMPATIBLE));
TypeBinding r = functionType.returnType;
if (r != TypeBinding.VOID) {
TypeBinding rAppl = potentiallyApplicable.isConstructor() && !reference.isArrayConstructorReference() ? potentiallyApplicable.declaringClass : potentiallyApplicable.returnType;
if (rAppl == TypeBinding.VOID)
return FALSE;
TypeBinding rPrime = rAppl.capture(inferenceContext.scope, reference.sourceStart, reference.sourceEnd);
newConstraints.add(ConstraintTypeFormula.create(rPrime, r, COMPATIBLE));
}
return newConstraints.toArray(new ConstraintFormula[newConstraints.size()]);
} else {
// inexact
int n = functionType.parameters.length;
for (int i = 0; i < n; i++) if (!functionType.parameters[i].isProperType(true))
return FALSE;
// Otherwise, a search for a compile-time declaration is performed, as defined in 15.13.1....
// Note: we currently don't distinguish search for a potentially-applicable method from searching the compiler-time declaration,
// hence reusing the method binding from above
MethodBinding compileTimeDecl = potentiallyApplicable;
if (!compileTimeDecl.isValidBinding())
return FALSE;
TypeBinding r = functionType.isConstructor() ? functionType.declaringClass : functionType.returnType;
if (r.id == TypeIds.T_void)
return TRUE;
// ignore parameterization of resolve result and do a fresh start:
MethodBinding original = compileTimeDecl.shallowOriginal();
if (needsInference(reference, original)) {
TypeBinding[] argumentTypes;
if (t.isParameterizedType()) {
MethodBinding capturedFunctionType = ((ParameterizedTypeBinding) t).getSingleAbstractMethod(inferenceContext.scope, true, reference.sourceStart, reference.sourceEnd);
argumentTypes = capturedFunctionType.parameters;
} else {
argumentTypes = functionType.parameters;
}
SuspendedInferenceRecord prevInvocation = inferenceContext.enterPolyInvocation(reference, reference.createPseudoExpressions(argumentTypes));
// Invocation Applicability Inference: 18.5.1 & Invocation Type Inference: 18.5.2
InferenceContext18 innerContext = null;
try {
innerContext = reference.getInferenceContext((ParameterizedMethodBinding) compileTimeDecl);
if (innerContext != null)
innerContext.pushBoundsTo(inferenceContext);
int innerInferenceKind = determineInferenceKind(compileTimeDecl, argumentTypes, innerContext);
inferInvocationApplicability(inferenceContext, original, argumentTypes, original.isConstructor(), /*mimic a diamond?*/
innerInferenceKind);
if (!inferenceContext.computeB3(reference, r, original))
return FALSE;
// already incorporated
return null;
} catch (InferenceFailureException e) {
return FALSE;
} finally {
inferenceContext.resumeSuspendedInference(prevInvocation, innerContext);
}
}
TypeBinding rPrime = compileTimeDecl.isConstructor() ? compileTimeDecl.declaringClass : compileTimeDecl.returnType.capture(inferenceContext.scope, reference.sourceStart(), reference.sourceEnd());
if (rPrime.id == TypeIds.T_void)
return FALSE;
return ConstraintTypeFormula.create(rPrime, r, COMPATIBLE, this.isSoft);
}
}
Aggregations