use of org.eclipse.jdt.internal.compiler.ast.SwitchExpression 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;
}
use of org.eclipse.jdt.internal.compiler.ast.SwitchExpression 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.ast.SwitchExpression in project bazel-jdt-java-toolchain by salesforce.
the class InferenceContext18 method addConstraintsToC_OneExpr.
private boolean addConstraintsToC_OneExpr(Expression expri, Set<ConstraintFormula> c, TypeBinding fsi, TypeBinding substF, MethodBinding method) throws InferenceFailureException {
boolean substFIsProperType = substF.isProperType(true);
// -- not per JLS, emulate javac behavior:
substF = Scope.substitute(getResultSubstitution(this.b3), substF);
// For all i (1 ≤ i ≤ k), if ei is not pertinent to applicability, the set contains ⟨ei → θ Fi⟩.
if (!expri.isPertinentToApplicability(fsi, method)) {
c.add(new ConstraintExpressionFormula(expri, substF, ReductionResult.COMPATIBLE, ARGUMENT_CONSTRAINTS_ARE_SOFT));
}
if (expri instanceof FunctionalExpression) {
c.add(new ConstraintExceptionFormula((FunctionalExpression) expri, substF));
if (expri instanceof LambdaExpression) {
// https://bugs.openjdk.java.net/browse/JDK-8038747
LambdaExpression lambda = (LambdaExpression) expri;
BlockScope skope = lambda.enclosingScope;
if (substF.isFunctionalInterface(skope)) {
// could be an inference variable.
ReferenceBinding t = (ReferenceBinding) substF;
ParameterizedTypeBinding withWildCards = InferenceContext18.parameterizedWithWildcard(t);
if (withWildCards != null) {
t = ConstraintExpressionFormula.findGroundTargetType(this, skope, lambda, withWildCards);
}
MethodBinding functionType;
if (t != null && (functionType = t.getSingleAbstractMethod(skope, true)) != null && (lambda = lambda.resolveExpressionExpecting(t, this.scope, this)) != null) {
TypeBinding r = functionType.returnType;
Expression[] resultExpressions = lambda.resultExpressions();
for (int i = 0, length = resultExpressions == null ? 0 : resultExpressions.length; i < length; i++) {
Expression resultExpression = resultExpressions[i];
if (!addConstraintsToC_OneExpr(resultExpression, c, r.original(), r, method))
return false;
}
}
}
}
} else if (expri instanceof Invocation && expri.isPolyExpression()) {
if (// https://bugs.openjdk.java.net/browse/JDK-8052325
substFIsProperType)
return true;
Invocation invocation = (Invocation) expri;
MethodBinding innerMethod = invocation.binding();
if (innerMethod == null)
// -> proceed with no new C set elements.
return true;
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;
InferenceContext18 innerContext = null;
if (innerMethod instanceof ParameterizedGenericMethodBinding)
innerContext = invocation.getInferenceContext((ParameterizedGenericMethodBinding) innerMethod);
if (innerContext != null) {
MethodBinding shallowMethod = innerMethod.shallowOriginal();
innerContext.outerContext = this;
if (// shouldn't happen, but let's play safe
innerContext.stepCompleted < InferenceContext18.APPLICABILITY_INFERRED)
innerContext.inferInvocationApplicability(shallowMethod, argumentTypes, shallowMethod.isConstructor());
if (!innerContext.computeB3(invocation, substF, shallowMethod))
return false;
if (innerContext.addConstraintsToC(arguments, c, innerMethod.genericMethod(), innerContext.inferenceKind, invocation)) {
this.currentBounds.addBounds(innerContext.currentBounds, this.environment);
return true;
}
return false;
} else {
int applicabilityKind = getInferenceKind(innerMethod, argumentTypes);
return this.addConstraintsToC(arguments, c, innerMethod.genericMethod(), applicabilityKind, invocation);
}
} else if (expri instanceof ConditionalExpression) {
ConditionalExpression ce = (ConditionalExpression) expri;
return addConstraintsToC_OneExpr(ce.valueIfTrue, c, fsi, substF, method) && addConstraintsToC_OneExpr(ce.valueIfFalse, c, fsi, substF, method);
} else if (expri instanceof SwitchExpression) {
SwitchExpression se = (SwitchExpression) expri;
for (Expression re : se.resultExpressions) {
if (!addConstraintsToC_OneExpr(re, c, fsi, substF, method))
return false;
}
return true;
}
return true;
}
use of org.eclipse.jdt.internal.compiler.ast.SwitchExpression in project bazel-jdt-java-toolchain by salesforce.
the class InferenceContext18 method checkExpression.
private boolean checkExpression(Expression expri, TypeBinding[] u, TypeBinding r1, TypeBinding[] v, TypeBinding r2) throws InferenceFailureException {
if (expri instanceof LambdaExpression && !((LambdaExpression) expri).argumentsTypeElided()) {
for (int i = 0; i < u.length; i++) {
if (!reduceAndIncorporate(ConstraintTypeFormula.create(u[i], v[i], ReductionResult.SAME)))
return false;
}
if (r2.id == TypeIds.T_void)
return true;
LambdaExpression lambda = (LambdaExpression) expri;
Expression[] results = lambda.resultExpressions();
if (results != Expression.NO_EXPRESSIONS) {
if (r1.isFunctionalInterface(this.scope) && r2.isFunctionalInterface(this.scope) && !(r1.isCompatibleWith(r2) || r2.isCompatibleWith(r1))) {
// (what does "applied .. to R1 and R2" mean? Why mention R1/R2 and not U/V?)
for (int i = 0; i < results.length; i++) {
if (!checkExpression(results[i], u, r1, v, r2))
return false;
}
return true;
}
checkPrimitive1: if (r1.isPrimitiveType() && !r2.isPrimitiveType()) {
// check: each result expression is a standalone expression of a primitive type
for (int i = 0; i < results.length; i++) {
if (results[i].isPolyExpression() || (results[i].resolvedType != null && !results[i].resolvedType.isPrimitiveType()))
break checkPrimitive1;
}
return true;
}
checkPrimitive2: if (r2.isPrimitiveType() && !r1.isPrimitiveType()) {
for (int i = 0; i < results.length; i++) {
// for all expressions (not for any expression not)
if (!(// standalone of a referencetype
(!results[i].isPolyExpression() && (results[i].resolvedType != null && !results[i].resolvedType.isPrimitiveType())) || // or a poly
results[i].isPolyExpression()))
break checkPrimitive2;
}
return true;
}
}
return reduceAndIncorporate(ConstraintTypeFormula.create(r1, r2, ReductionResult.SUBTYPE));
} else if (expri instanceof ReferenceExpression && ((ReferenceExpression) expri).isExactMethodReference()) {
ReferenceExpression reference = (ReferenceExpression) expri;
for (int i = 0; i < u.length; i++) {
if (!reduceAndIncorporate(ConstraintTypeFormula.create(u[i], v[i], ReductionResult.SAME)))
return false;
}
if (r2.id == TypeIds.T_void)
return true;
MethodBinding method = reference.getExactMethod();
TypeBinding returnType = method.isConstructor() ? method.declaringClass : method.returnType;
if (r1.isPrimitiveType() && !r2.isPrimitiveType() && returnType.isPrimitiveType())
return true;
if (r2.isPrimitiveType() && !r1.isPrimitiveType() && !returnType.isPrimitiveType())
return true;
return reduceAndIncorporate(ConstraintTypeFormula.create(r1, r2, ReductionResult.SUBTYPE));
} else if (expri instanceof ConditionalExpression) {
ConditionalExpression cond = (ConditionalExpression) expri;
return checkExpression(cond.valueIfTrue, u, r1, v, r2) && checkExpression(cond.valueIfFalse, u, r1, v, r2);
} else if (expri instanceof SwitchExpression) {
SwitchExpression se = (SwitchExpression) expri;
for (Expression re : se.resultExpressions) {
if (!checkExpression(re, u, r1, v, r2))
return false;
}
return true;
} else {
return false;
}
}
use of org.eclipse.jdt.internal.compiler.ast.SwitchExpression in project bazel-jdt-java-toolchain by salesforce.
the class ProblemReporter method expressionNonNullComparison.
/**
* @param expr expression being compared for null or nonnull
* @param checkForNull true if checking for null, false if checking for nonnull
*/
public boolean expressionNonNullComparison(Expression expr, boolean checkForNull) {
int problemId = 0;
Binding binding = null;
String[] arguments = null;
int start = 0, end = 0;
Expression location = expr;
if (expr.resolvedType != null) {
long tagBits = expr.resolvedType.tagBits & TagBits.AnnotationNullMASK;
if (tagBits == TagBits.AnnotationNonNull) {
problemId = IProblem.RedundantNullCheckAgainstNonNullType;
arguments = new String[] { String.valueOf(expr.resolvedType.nullAnnotatedReadableName(this.options, true)) };
start = nodeSourceStart(location);
end = nodeSourceEnd(location);
handle(problemId, arguments, arguments, start, end);
return true;
}
}
// unwrap uninteresting nodes:
while (true) {
if (expr instanceof Assignment)
// don't report against the assignment, but the variable
return false;
else if (expr instanceof CastExpression)
expr = ((CastExpression) expr).expression;
else
break;
}
// check all those kinds of expressions that can possible answer NON_NULL from nullStatus():
if (expr instanceof MessageSend) {
problemId = checkForNull ? IProblem.NonNullMessageSendComparisonYieldsFalse : IProblem.RedundantNullCheckOnNonNullMessageSend;
MethodBinding method = ((MessageSend) expr).binding;
binding = method;
arguments = new String[] { new String(method.shortReadableName()) };
start = location.sourceStart;
end = location.sourceEnd;
} else if (expr instanceof Reference && !(expr instanceof ThisReference) && !(expr instanceof ArrayReference)) {
FieldBinding field = ((Reference) expr).lastFieldBinding();
if (field == null) {
return false;
}
if (field.isNonNull()) {
problemId = checkForNull ? IProblem.NonNullSpecdFieldComparisonYieldsFalse : IProblem.RedundantNullCheckOnNonNullSpecdField;
char[][] nonNullName = this.options.nonNullAnnotationName;
arguments = new String[] { new String(field.name), new String(nonNullName[nonNullName.length - 1]) };
} else if (field.constant() != Constant.NotAConstant) {
problemId = checkForNull ? IProblem.ConstNonNullFieldComparisonYieldsFalse : IProblem.RedundantNullCheckOnConstNonNullField;
char[][] nonNullName = this.options.nonNullAnnotationName;
arguments = new String[] { new String(field.name), new String(nonNullName[nonNullName.length - 1]) };
} else {
// signaling redundancy based on syntactic analysis:
problemId = checkForNull ? IProblem.FieldComparisonYieldsFalse : IProblem.RedundantNullCheckOnField;
arguments = new String[] { String.valueOf(field.name) };
}
binding = field;
start = nodeSourceStart(binding, location);
end = nodeSourceEnd(binding, location);
} else if (expr instanceof AllocationExpression || expr instanceof ArrayAllocationExpression || expr instanceof ArrayInitializer || expr instanceof ClassLiteralAccess || expr instanceof ThisReference) {
// fall through to bottom
} else if (expr instanceof Literal || expr instanceof ConditionalExpression || expr instanceof SwitchExpression) {
if (expr instanceof NullLiteral) {
// reported as nonnull??
needImplementation(location);
return false;
}
if (expr.resolvedType != null && expr.resolvedType.isBaseType()) {
// false alarm, auto(un)boxing is involved
return false;
}
// fall through to bottom
} else if (expr instanceof BinaryExpression) {
if ((expr.bits & ASTNode.ReturnTypeIDMASK) != TypeIds.T_JavaLangString) {
// false alarm, primitive types involved, must be auto(un)boxing?
return false;
}
// fall through to bottom
} else {
// want to see if we get here
needImplementation(expr);
return false;
}
if (problemId == 0) {
// standard case, fill in details now
problemId = checkForNull ? IProblem.NonNullExpressionComparisonYieldsFalse : IProblem.RedundantNullCheckOnNonNullExpression;
start = location.sourceStart;
end = location.sourceEnd;
arguments = NoArgument;
}
this.handle(problemId, arguments, arguments, start, end);
return true;
}
Aggregations