in nullaway/src/main/java/com/uber/nullaway/generics/GenericsChecks.java [752:795]
public void checkTypeParameterNullnessForAssignability(Tree tree, VisitorState state) {
Config config = analysis.getConfig();
if (!config.isJSpecifyMode()) {
return;
}
Type lhsType = getTreeType(tree, state);
if (lhsType == null) {
return;
}
ExpressionTree rhsTree;
boolean assignedToLocal;
if (tree instanceof VariableTree varTree) {
rhsTree = varTree.getInitializer();
assignedToLocal = isAssignmentToLocalVariable(varTree);
} else if (tree instanceof AssignmentTree assignmentTree) {
rhsTree = assignmentTree.getExpression();
assignedToLocal = isAssignmentToLocalVariable(assignmentTree);
} else {
throw new RuntimeException("Unexpected tree type: " + tree.getKind());
}
// 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;
}
if (!assignedToLocal
&& (rhsTree instanceof LambdaExpressionTree || rhsTree instanceof MemberReferenceTree)
&& isAssignmentToField(tree)) {
maybeStorePolyExpressionTypeFromTarget(rhsTree, lhsType);
}
TreePath pathToRhs = new TreePath(state.getPath(), rhsTree);
Type rhsType = getTreeType(rhsTree, state.withPath(pathToRhs));
if (rhsType != null) {
if (isGenericCallNeedingInference(rhsTree)) {
rhsType =
inferGenericMethodCallType(
state, (MethodInvocationTree) rhsTree, null, lhsType, assignedToLocal, false);
}
boolean isAssignmentValid = subtypeParameterNullability(lhsType, rhsType, state);
if (!isAssignmentValid) {
reportInvalidAssignmentInstantiationError(tree, lhsType, rhsType, state);
}
}
}