in nullaway/src/main/java/com/uber/nullaway/generics/GenericsChecks.java [424:482]
public void checkTypeParameterNullnessForAssignability(
Tree tree, NullAway analysis, VisitorState state) {
Config config = analysis.getConfig();
if (!config.isJSpecifyMode()) {
return;
}
Type lhsType = getTreeType(tree, config);
if (lhsType == null) {
return;
}
Tree rhsTree;
if (tree instanceof VariableTree) {
VariableTree varTree = (VariableTree) tree;
rhsTree = varTree.getInitializer();
} else {
AssignmentTree assignmentTree = (AssignmentTree) tree;
rhsTree = assignmentTree.getExpression();
}
// rhsTree can be null for a VariableTree. Also, we don't need to do a check
// if rhsTree is the null literal
if (rhsTree == null || rhsTree.getKind().equals(Tree.Kind.NULL_LITERAL)) {
return;
}
Type rhsType = getTreeType(rhsTree, config);
if (rhsTree instanceof MethodInvocationTree) {
MethodInvocationTree methodInvocationTree = (MethodInvocationTree) rhsTree;
Symbol.MethodSymbol methodSymbol = ASTHelpers.getSymbol(methodInvocationTree);
if (methodSymbol.type instanceof Type.ForAll
&& methodInvocationTree.getTypeArguments().isEmpty()) {
// generic method call with no explicit generic arguments
// update inferred type arguments based on the assignment context
boolean invokedMethodIsNullUnmarked =
CodeAnnotationInfo.instance(state.context)
.isSymbolUnannotated(methodSymbol, config, analysis.getHandler());
InferGenericMethodSubstitutionViaAssignmentContextVisitor inferVisitor =
new InferGenericMethodSubstitutionViaAssignmentContextVisitor(
state, config, invokedMethodIsNullUnmarked);
Type returnType = methodSymbol.getReturnType();
returnType.accept(inferVisitor, lhsType);
Map<TypeVariable, Type> substitution = inferVisitor.getInferredSubstitution();
inferredSubstitutionsForGenericMethodCalls.put(methodInvocationTree, substitution);
if (rhsType != null) {
// update rhsType with inferred substitution
rhsType =
substituteInferredTypesForTypeVariables(
state, methodSymbol.getReturnType(), substitution, config);
}
}
}
if (rhsType != null) {
boolean isAssignmentValid = subtypeParameterNullability(lhsType, rhsType, state, config);
if (!isAssignmentValid) {
reportInvalidAssignmentInstantiationError(tree, lhsType, rhsType, state, analysis);
}
}
}