private TypeSubstitution inferTypeSubstitutionInArrayType(MethodJavaSymbol method, TypeSubstitution substitution, ArrayJavaType formalType, JavaType argType, boolean variableArity, List<JavaType> remainingArgTypes) { JavaType newArgType = null; if (argType.isArray()) { newArgType = ((ArrayJavaType) argType).elementType; } else if (variableArity) { newArgType = (JavaType) leastUpperBound.leastUpperBound(mapToBoxedSet(remainingArgTypes)); } if (newArgType != null) { TypeSubstitution newSubstitution = inferTypeSubstitution(method, substitution, formalType.elementType, newArgType, variableArity, remainingArgTypes); return mergeTypeSubstitutions(substitution, newSubstitution); } return substitution; }
TypeSubstitution inferTypeSubstitution(MethodJavaSymbol method, List<JavaType> formals, List<JavaType> argTypes) { handledFormals.clear(); return inferTypeSubstitutionRec(method, formals, argTypes); } private TypeSubstitution inferTypeSubstitutionRec(MethodJavaSymbol method, List<JavaType> formals, List<JavaType> argTypes) {
private TypeSubstitution inferTypeSubstitutionInWildcardType(MethodJavaSymbol method, TypeSubstitution substitution, WildCardType formalType, JavaType argType, boolean variableArity, List<JavaType> remainingArgTypes) { JavaType newArgType = argType; if (argType.isTagged(JavaType.WILDCARD)) { newArgType = ((WildCardType) argType).bound; } TypeSubstitution newSubstitution = inferTypeSubstitution(method, substitution, formalType.bound, newArgType, variableArity, remainingArgTypes); return mergeTypeSubstitutions(substitution, newSubstitution); }
if (parametrizedArgType.rawType == formalType.rawType) { List<JavaType> argTypeSubstitutedTypes = parametrizedArgType.typeSubstitution.substitutedTypes(); TypeSubstitution newSubstitution = inferTypeSubstitutionRec(method, formalTypeSubstitutedTypes, argTypeSubstitutedTypes); return mergeTypeSubstitutions(substitution, newSubstitution); TypeSubstitution newSubstitution = inferTypeSubstitutionInParameterizedType(method, substitution, formalType, superclass, variableArity, remainingArgTypes); if (!newSubstitution.substitutedTypes().isEmpty()) { result = mergeTypeSubstitutions(substitution, newSubstitution); TypeSubstitution newSubstitution = inferTypeSubstitutionInParameterizedType(method, substitution, formalType, superclass, variableArity, remainingArgTypes); if (!newSubstitution.substitutedTypes().isEmpty()) { result = mergeTypeSubstitutions(result, newSubstitution); } else if (isRawTypeOfType(argType, formalType) || isNullType(argType)) { return TypeSubstitution.uncheckedTypeSubstitution(); } else if (argType.isSubtypeOf(formalType.erasure()) && argType.isClass()) { for (JavaType superType : ((ClassJavaType) argType).superTypes()) { if (sameErasure(formalType, superType)) { TypeSubstitution newSubstitution = inferTypeSubstitution(method, substitution, formalType, superType, variableArity, remainingArgTypes); result = mergeTypeSubstitutions(substitution, newSubstitution); break;
private TypeSubstitution inferTypeSubstitution(MethodJavaSymbol method, TypeSubstitution substitution, JavaType formalType, JavaType argumentType, boolean variableArity, List<JavaType> remainingArgTypes) { if(handledFormals.get(formalType).contains(argumentType)) { return substitution; } JavaType argType = argumentType; if (argType.isTagged(JavaType.DEFERRED)) { argType = ((DeferredType) argType).getUninferedType(); } handledFormals.put(formalType, argType); TypeSubstitution result = substitution; if (formalType.isTagged(JavaType.TYPEVAR)) { result = inferTypeSubstitutionInTypeVariable(method, substitution, (TypeVariableJavaType) formalType, argType, variableArity, remainingArgTypes); } else if (formalType.isArray()) { result = inferTypeSubstitutionInArrayType(method, substitution, (ArrayJavaType) formalType, argType, variableArity, remainingArgTypes); } else if (formalType.isParameterized()) { result = inferTypeSubstitutionInParameterizedType(method, substitution, (ParametrizedTypeJavaType) formalType, argType, variableArity, remainingArgTypes); } else if (formalType.isTagged(JavaType.WILDCARD)) { result = inferTypeSubstitutionInWildcardType(method, substitution, (WildCardType) formalType, argType, variableArity, remainingArgTypes); } else { // nothing to infer for simple class types or primitive types } return result; }
private TypeSubstitution inferTypeSubstitutionInTypeVariable(MethodJavaSymbol method, TypeSubstitution substitution, TypeVariableJavaType formalType, JavaType argType, boolean variableArity, List<JavaType> remainingArgTypes) { TypeSubstitution result = new TypeSubstitution(substitution); if (substitution.substitutedType(formalType) == null) { JavaType expectedType = argType; if (expectedType.isPrimitive()) { expectedType = expectedType.primitiveWrapperType; } else if (isNullType(expectedType)) { expectedType = symbols.objectType; } TypeVariableJavaType typeVar = formalType; result.add(typeVar, expectedType); } for (JavaType bound : formalType.bounds) { if (!bound.is("java.lang.Object")) { result = inferTypeSubstitution(method, result, bound, argType, variableArity, remainingArgTypes); } } return result; } }
private TypeSubstitution inferTypeSubstitutionRec(MethodJavaSymbol method, List<JavaType> formals, List<JavaType> argTypes) { boolean isVarArgs = method.isVarArgs(); int numberFormals = formals.size(); int numberArgs = argTypes.size(); int numberParamToCheck = Math.min(numberFormals, numberArgs); List<JavaType> newArgTypes = new ArrayList<>(argTypes); TypeSubstitution substitution = new TypeSubstitution(); // method is varargs but parameter is not provided if (isVarArgs && numberFormals == numberArgs + 1) { numberParamToCheck += 1; newArgTypes.add(symbols.objectType); } for (int i = 0; i < numberParamToCheck; i++) { JavaType formalType = formals.get(i); JavaType argType = newArgTypes.get(i); boolean variableArity = isVarArgs && i == (numberFormals - 1); List<JavaType> remainingArgTypes = new ArrayList<>(newArgTypes.subList(i, newArgTypes.size())); substitution = inferTypeSubstitution(method, substitution, formalType, argType, variableArity, remainingArgTypes); if (substitution.isUnchecked() || (!method.isConstructor() && substitution.typeVariables().containsAll(method.typeVariableTypes))) { // we found all the substitution break; } } return substitution; }
public TypeSubstitutionSolver(ParametrizedTypeCache parametrizedTypeCache, Symbols symbols) { this.parametrizedTypeCache = parametrizedTypeCache; this.symbols = symbols; this.leastUpperBound = new LeastUpperBound(this, parametrizedTypeCache, symbols); this.typeInferenceSolver = new TypeInferenceSolver(leastUpperBound, symbols, this); parametrizedTypeCache.setTypeSubstitutionSolver(this); }
if (parametrizedArgType.rawType == formalType.rawType) { List<JavaType> argTypeSubstitutedTypes = parametrizedArgType.typeSubstitution.substitutedTypes(); TypeSubstitution newSubstitution = inferTypeSubstitutionRec(method, formalTypeSubstitutedTypes, argTypeSubstitutedTypes); return mergeTypeSubstitutions(substitution, newSubstitution); TypeSubstitution newSubstitution = inferTypeSubstitutionInParameterizedType(method, substitution, formalType, superclass, variableArity, remainingArgTypes); if (!newSubstitution.substitutedTypes().isEmpty()) { result = mergeTypeSubstitutions(substitution, newSubstitution); TypeSubstitution newSubstitution = inferTypeSubstitutionInParameterizedType(method, substitution, formalType, superclass, variableArity, remainingArgTypes); if (!newSubstitution.substitutedTypes().isEmpty()) { result = mergeTypeSubstitutions(result, newSubstitution); } else if (isRawTypeOfType(argType, formalType) || isNullType(argType)) { return TypeSubstitution.uncheckedTypeSubstitution(); } else if (argType.isSubtypeOf(formalType.erasure()) && argType.isClass()) { for (JavaType superType : ((ClassJavaType) argType).superTypes()) { if (sameErasure(formalType, superType)) { TypeSubstitution newSubstitution = inferTypeSubstitution(method, substitution, formalType, superType, variableArity, remainingArgTypes); result = mergeTypeSubstitutions(substitution, newSubstitution); break;
private TypeSubstitution inferTypeSubstitution(MethodJavaSymbol method, TypeSubstitution substitution, JavaType formalType, JavaType argumentType, boolean variableArity, List<JavaType> remainingArgTypes) { if(handledFormals.get(formalType).contains(argumentType)) { return substitution; } JavaType argType = argumentType; if (argType.isTagged(JavaType.DEFERRED)) { argType = ((DeferredType) argType).getUninferedType(); } handledFormals.put(formalType, argType); TypeSubstitution result = substitution; if (formalType.isTagged(JavaType.TYPEVAR)) { result = inferTypeSubstitutionInTypeVariable(method, substitution, (TypeVariableJavaType) formalType, argType, variableArity, remainingArgTypes); } else if (formalType.isArray()) { result = inferTypeSubstitutionInArrayType(method, substitution, (ArrayJavaType) formalType, argType, variableArity, remainingArgTypes); } else if (formalType.isParameterized()) { result = inferTypeSubstitutionInParameterizedType(method, substitution, (ParametrizedTypeJavaType) formalType, argType, variableArity, remainingArgTypes); } else if (formalType.isTagged(JavaType.WILDCARD)) { result = inferTypeSubstitutionInWildcardType(method, substitution, (WildCardType) formalType, argType, variableArity, remainingArgTypes); } else { // nothing to infer for simple class types or primitive types } return result; }
private TypeSubstitution inferTypeSubstitutionInWildcardType(MethodJavaSymbol method, TypeSubstitution substitution, WildCardType formalType, JavaType argType, boolean variableArity, List<JavaType> remainingArgTypes) { JavaType newArgType = argType; if (argType.isTagged(JavaType.WILDCARD)) { newArgType = ((WildCardType) argType).bound; } TypeSubstitution newSubstitution = inferTypeSubstitution(method, substitution, formalType.bound, newArgType, variableArity, remainingArgTypes); return mergeTypeSubstitutions(substitution, newSubstitution); }
private TypeSubstitution inferTypeSubstitutionInTypeVariable(MethodJavaSymbol method, TypeSubstitution substitution, TypeVariableJavaType formalType, JavaType argType, boolean variableArity, List<JavaType> remainingArgTypes) { TypeSubstitution result = new TypeSubstitution(substitution); if (substitution.substitutedType(formalType) == null) { JavaType expectedType = argType; if (expectedType.isPrimitive()) { expectedType = expectedType.primitiveWrapperType; } else if (isNullType(expectedType)) { expectedType = symbols.objectType; } TypeVariableJavaType typeVar = formalType; result.add(typeVar, expectedType); } for (JavaType bound : formalType.bounds) { if (!bound.is("java.lang.Object")) { result = inferTypeSubstitution(method, result, bound, argType, variableArity, remainingArgTypes); } } return result; } }
private TypeSubstitution inferTypeSubstitutionRec(MethodJavaSymbol method, List<JavaType> formals, List<JavaType> argTypes) { boolean isVarArgs = method.isVarArgs(); int numberFormals = formals.size(); int numberArgs = argTypes.size(); int numberParamToCheck = Math.min(numberFormals, numberArgs); List<JavaType> newArgTypes = new ArrayList<>(argTypes); TypeSubstitution substitution = new TypeSubstitution(); // method is varargs but parameter is not provided if (isVarArgs && numberFormals == numberArgs + 1) { numberParamToCheck += 1; newArgTypes.add(symbols.objectType); } for (int i = 0; i < numberParamToCheck; i++) { JavaType formalType = formals.get(i); JavaType argType = newArgTypes.get(i); boolean variableArity = isVarArgs && i == (numberFormals - 1); List<JavaType> remainingArgTypes = new ArrayList<>(newArgTypes.subList(i, newArgTypes.size())); substitution = inferTypeSubstitution(method, substitution, formalType, argType, variableArity, remainingArgTypes); if (substitution.isUnchecked() || (!method.isConstructor() && substitution.typeVariables().containsAll(method.typeVariableTypes))) { // we found all the substitution break; } } return substitution; }
public TypeSubstitutionSolver(ParametrizedTypeCache parametrizedTypeCache, Symbols symbols) { this.parametrizedTypeCache = parametrizedTypeCache; this.symbols = symbols; this.leastUpperBound = new LeastUpperBound(this, parametrizedTypeCache, symbols); this.typeInferenceSolver = new TypeInferenceSolver(leastUpperBound, symbols, this); parametrizedTypeCache.setTypeSubstitutionSolver(this); }
private TypeSubstitution inferTypeSubstitutionInArrayType(MethodJavaSymbol method, TypeSubstitution substitution, ArrayJavaType formalType, JavaType argType, boolean variableArity, List<JavaType> remainingArgTypes) { JavaType newArgType = null; if (argType.isArray()) { newArgType = ((ArrayJavaType) argType).elementType; } else if (variableArity) { newArgType = (JavaType) leastUpperBound.leastUpperBound(mapToBoxedSet(remainingArgTypes)); } if (newArgType != null) { TypeSubstitution newSubstitution = inferTypeSubstitution(method, substitution, formalType.elementType, newArgType, variableArity, remainingArgTypes); return mergeTypeSubstitutions(substitution, newSubstitution); } return substitution; }
@CheckForNull TypeSubstitution getTypeSubstitution(JavaSymbol.MethodJavaSymbol method, JavaType site, List<JavaType> typeParams, List<JavaType> argTypes) { List<JavaType> formals = ((MethodJavaType) method.type).argTypes; TypeSubstitution substitution = new TypeSubstitution(); if (method.isParametrized() || constructParametrizedTypeWithoutSubstitution(method, site)) { if (!typeParams.isEmpty()) { substitution = getSubstitutionFromTypeParams(method.typeVariableTypes, typeParams); } else if (formals.isEmpty()) { // substitution can not be inferred, as it is not based on arguments, method call is still valid return substitution; } else { formals = applySiteSubstitutionToFormalParameters(formals, site); substitution = typeInferenceSolver.inferTypeSubstitution(method, formals, argTypes); } if (!isValidSubstitution(substitution, site)) { // check for valid substitution in supertypes, null if no valid substitution is found return getTypeSubstitutionFromSuperTypes(method, site, typeParams, argTypes); } } return substitution; }
TypeSubstitution inferTypeSubstitution(MethodJavaSymbol method, List<JavaType> formals, List<JavaType> argTypes) { handledFormals.clear(); return inferTypeSubstitutionRec(method, formals, argTypes); } private TypeSubstitution inferTypeSubstitutionRec(MethodJavaSymbol method, List<JavaType> formals, List<JavaType> argTypes) {
@CheckForNull TypeSubstitution getTypeSubstitution(JavaSymbol.MethodJavaSymbol method, JavaType site, List<JavaType> typeParams, List<JavaType> argTypes) { List<JavaType> formals = ((MethodJavaType) method.type).argTypes; TypeSubstitution substitution = new TypeSubstitution(); if (method.isParametrized() || constructParametrizedTypeWithoutSubstitution(method, site)) { if (!typeParams.isEmpty()) { substitution = getSubstitutionFromTypeParams(method.typeVariableTypes, typeParams); } else if (formals.isEmpty()) { // substitution can not be inferred, as it is not based on arguments, method call is still valid return substitution; } else { formals = applySiteSubstitutionToFormalParameters(formals, site); substitution = typeInferenceSolver.inferTypeSubstitution(method, formals, argTypes); } if (!isValidSubstitution(substitution, site)) { // check for valid substitution in supertypes, null if no valid substitution is found return getTypeSubstitutionFromSuperTypes(method, site, typeParams, argTypes); } } return substitution; }