[java] Properly handle 0-arg calls

- We no longer take all methods as applicable for a 0-arg method call
during type resolution.
This commit is contained in:
Juan Martín Sotuyo Dodero
2017-10-26 12:18:00 -03:00
parent 2d15c6dba6
commit ae2898e238

View File

@ -115,11 +115,10 @@ public final class MethodTypeResolution {
for (int methodIndex = 0; methodIndex < methodsToSearch.size(); ++methodIndex) {
MethodType methodType = methodsToSearch.get(methodIndex);
if (argList == null) {
selectedMethods.add(methodType);
final int argCount = argList == null ? 0 : argList.jjtGetNumChildren();
// vararg methods are considered fixed arity here - varargs are dealt with in the 3rd phase
} else if (getArity(methodType.getMethod()) == argList.jjtGetNumChildren()) {
// vararg methods are considered fixed arity here, see 3rd phase
if (getArity(methodType.getMethod()) == argCount) {
if (!methodType.isParameterized()) {
// https://docs.oracle.com/javase/specs/jls/se8/html/jls-18.html#jls-18.5.1
// ...
@ -129,7 +128,7 @@ public final class MethodTypeResolution {
// reference type, or ii) Fi is a primitive type but ei is not a standalone expression of a
// primitive type; then the method is not applicable and there is no need to proceed with inference.
Class<?>[] methodParameterTypes = methodType.getMethod().getParameterTypes();
for (int argIndex = 0; argIndex < argList.jjtGetNumChildren(); ++argIndex) {
for (int argIndex = 0; argIndex < argCount; ++argIndex) {
if (((ASTExpression) argList.jjtGetChild(argIndex)).isStandAlonePrimitive()) {
if (!methodParameterTypes[argIndex].isPrimitive()) {
continue outter; // this method is not applicable
@ -146,7 +145,7 @@ public final class MethodTypeResolution {
boolean methodIsApplicable = true;
// try each arguments if it's subtypeable
for (int argIndex = 0; argIndex < argList.jjtGetNumChildren(); ++argIndex) {
for (int argIndex = 0; argIndex < argCount; ++argIndex) {
if (!isSubtypeable(methodType.getParameterTypes().get(argIndex),
(ASTExpression) argList.jjtGetChild(argIndex))) {
methodIsApplicable = false;
@ -193,7 +192,7 @@ public final class MethodTypeResolution {
int typeParamIndex = -1;
if (methodParameters[i] instanceof TypeVariable) {
typeParamIndex = JavaTypeDefinition
.getGenericTypeIndex(methodTypeParameters, ((TypeVariable) methodParameters[i]).getName());
.getGenericTypeIndex(methodTypeParameters, ((TypeVariable<?>) methodParameters[i]).getName());
}
if (typeParamIndex != -1) {
@ -233,7 +232,7 @@ public final class MethodTypeResolution {
int boundVarIndex = -1;
if (bound instanceof TypeVariable) {
boundVarIndex =
JavaTypeDefinition.getGenericTypeIndex(typeVariables, ((TypeVariable) bound).getName());
JavaTypeDefinition.getGenericTypeIndex(typeVariables, ((TypeVariable<?>) bound).getName());
}
if (boundVarIndex != -1) {
@ -268,16 +267,15 @@ public final class MethodTypeResolution {
throw new ResolutionFailedException();
}
if (argList == null) {
selectedMethods.add(methodType);
final int argCount = argList == null ? 0 : argList.jjtGetNumChildren();
// vararg methods are considered fixed arity here, see 3rd phase
} else if (getArity(methodType.getMethod()) == argList.jjtGetNumChildren()) {
// vararg methods are considered fixed arity here, see 3rd phase
if (getArity(methodType.getMethod()) == argCount) {
// check method convertability of each argument to the corresponding parameter
boolean methodIsApplicable = true;
// try each arguments if it's method convertible
for (int argIndex = 0; argIndex < argList.jjtGetNumChildren(); ++argIndex) {
for (int argIndex = 0; argIndex < argCount; ++argIndex) {
if (!isMethodConvertible(methodType.getParameterTypes().get(argIndex),
(ASTExpression) argList.jjtGetChild(argIndex))) {
methodIsApplicable = false;
@ -311,37 +309,39 @@ public final class MethodTypeResolution {
throw new ResolutionFailedException();
}
if (argList == null) {
selectedMethods.add(methodType);
// now we consider varargs as not fixed arity
// if we reach here and the method is not a vararg, then we didn't find a resolution in earlier phases
} else if (methodType.isVararg()) { // check subtypeability of each argument to the corresponding parameter
// now we consider varargs as not fixed arity
// if we reach here and the method is not a vararg, then we didn't find a resolution in earlier phases
if (methodType.isVararg()) { // check subtypeability of each argument to the corresponding parameter
boolean methodIsApplicable = true;
List<JavaTypeDefinition> methodParameters = methodType.getParameterTypes();
JavaTypeDefinition varargComponentType = methodType.getVarargComponentType();
// try each arguments if it's method convertible
for (int argIndex = 0; argIndex < argList.jjtGetNumChildren(); ++argIndex) {
JavaTypeDefinition parameterType = argIndex < methodParameters.size() - 1
? methodParameters.get(argIndex) : varargComponentType;
if (!isMethodConvertible(parameterType, (ASTExpression) argList.jjtGetChild(argIndex))) {
methodIsApplicable = false;
break;
if (argList == null) {
// There are no arguments, make sure the method has only a vararg
methodIsApplicable = getArity(methodType.getMethod()) == 1;
} else {
// try each arguments if it's method convertible
for (int argIndex = 0; argIndex < argList.jjtGetNumChildren(); ++argIndex) {
JavaTypeDefinition parameterType = argIndex < methodParameters.size() - 1
? methodParameters.get(argIndex) : varargComponentType;
if (!isMethodConvertible(parameterType, (ASTExpression) argList.jjtGetChild(argIndex))) {
methodIsApplicable = false;
break;
}
// TODO: If k != n, or if k = n and An cannot be converted by method invocation conversion to
// Sn[], then the type which is the erasure (§4.6) of Sn is accessible at the point of invocation.
// TODO: add unchecked conversion in an else if branch
}
// TODO: If k != n, or if k = n and An cannot be converted by method invocation conversion to
// Sn[], then the type which is the erasure (§4.6) of Sn is accessible at the point of invocation.
// TODO: add unchecked conversion in an else if branch
}
if (methodIsApplicable) {
selectedMethods.add(methodType);
}
} else if (!methodType.isVararg()) {
} else {
// TODO: Remove check for vararg here, once we can detect and use return types of method calls
LOG.log(Level.FINE, "Method {0} couldn't be resolved", String.valueOf(methodType));
}