in nullaway/src/main/java/com/uber/nullaway/generics/GenericsChecks.java [1898:1945]
private Type substituteTypeArgsInGenericMethodType(
Tree tree,
Type.ForAll forAllType,
@Nullable TreePath path,
VisitorState state,
boolean calledFromDataflow) {
Type.MethodType methodType = forAllType.asMethodType();
List<? extends Tree> typeArgumentTrees =
(tree instanceof MethodInvocationTree methodInvocationTree)
? methodInvocationTree.getTypeArguments()
: ((NewClassTree) tree).getTypeArguments();
com.sun.tools.javac.util.List<Type> explicitTypeArgs = convertTreesToTypes(typeArgumentTrees);
// There are no explicit type arguments, so use the inferred types
if (explicitTypeArgs.isEmpty() && tree instanceof MethodInvocationTree invocationTree) {
MethodInferenceResult result = inferredTypeVarNullabilityForGenericCalls.get(tree);
if (result == null) {
// have not yet attempted inference for this call
InvocationAndContext invocationAndType =
path == null
? new InvocationAndContext(invocationTree, null, false)
: getInvocationAndContextForInference(path, state, calledFromDataflow);
result =
runInferenceForCall(
state,
path,
invocationAndType.invocation,
invocationAndType.typeFromAssignmentContext,
invocationAndType.assignedToLocal,
calledFromDataflow);
}
Type.MethodType methodTypeAtCallSite =
castToNonNull(ASTHelpers.getType(invocationTree.getMethodSelect())).asMethodType();
if (result instanceof InferenceSuccess successResult) {
methodTypeAtCallSite =
restoreNestedNullabilityForTypeVarArguments(
invocationTree, methodType, methodTypeAtCallSite, state);
return TypeSubstitutionUtils.updateMethodTypeWithInferredNullability(
methodTypeAtCallSite, methodType, successResult.typeVarNullability, state, config);
} else {
// inference failed; just return the method type at the call site with no substitutions
return methodTypeAtCallSite;
}
}
return TypeSubstitutionUtils.subst(
state.getTypes(), methodType, forAllType.tvars, explicitTypeArgs, config);
}