diff --git a/nullaway/src/main/java/com/uber/nullaway/generics/GenericsChecks.java b/nullaway/src/main/java/com/uber/nullaway/generics/GenericsChecks.java index d95ebec3ee..85ca6861bb 100644 --- a/nullaway/src/main/java/com/uber/nullaway/generics/GenericsChecks.java +++ b/nullaway/src/main/java/com/uber/nullaway/generics/GenericsChecks.java @@ -613,6 +613,7 @@ public static void compareGenericTypeParameterNullabilityForCall( return; } Type invokedMethodType = methodSymbol.type; + // substitute class-level type arguments for instance methods if (!methodSymbol.isStatic() && tree instanceof MethodInvocationTree) { ExpressionTree methodSelect = ((MethodInvocationTree) tree).getMethodSelect(); Type enclosingType; @@ -626,10 +627,10 @@ public static void compareGenericTypeParameterNullabilityForCall( invokedMethodType = state.getTypes().memberType(enclosingType, methodSymbol); } } - // Handle generic methods + // substitute type arguments for generic methods if (tree instanceof MethodInvocationTree && methodSymbol.type instanceof Type.ForAll) { invokedMethodType = - substituteGenericTypeArgsToExplicit((MethodInvocationTree) tree, methodSymbol, state); + substituteTypeArgsInGenericMethodType((MethodInvocationTree) tree, methodSymbol, state); } List formalParamTypes = invokedMethodType.getParameterTypes(); int n = formalParamTypes.size(); @@ -820,7 +821,7 @@ public static Nullness getGenericReturnNullnessAtInvocation( if (!invokedMethodSymbol.getTypeParameters().isEmpty()) { // Substitute type arguments inside the return type Type substitutedReturnType = - substituteGenericTypeArgsToExplicit(tree, invokedMethodSymbol, state).getReturnType(); + substituteTypeArgsInGenericMethodType(tree, invokedMethodSymbol, state).getReturnType(); // If this condition evaluates to false, we fall through to the subsequent logic, to handle // type variables declared on the enclosing class if (substitutedReturnType != null @@ -854,11 +855,18 @@ private static com.sun.tools.javac.util.List convertTreesToTypes( return com.sun.tools.javac.util.List.from(types); } - private static Type substituteGenericTypeArgsToExplicit( - MethodInvocationTree methodInvocationTreetree, + /** + * Substitutes the type arguments from a generic method invocation into the method's type. + * + * @param methodInvocationTree the method invocation tree + * @param methodSymbol symbol for the invoked generic method + * @param state the visitor state + * @return the substituted method type for the generic method + */ + private static Type substituteTypeArgsInGenericMethodType( + MethodInvocationTree methodInvocationTree, Symbol.MethodSymbol methodSymbol, VisitorState state) { - MethodInvocationTree methodInvocationTree = (MethodInvocationTree) methodInvocationTreetree; List typeArgumentTrees = methodInvocationTree.getTypeArguments(); com.sun.tools.javac.util.List explicitTypeArgs = convertTreesToTypes(typeArgumentTrees); @@ -913,7 +921,8 @@ public static Nullness getGenericParameterNullnessAtInvocation( // Substitute the argument types within the MethodType // NOTE: if explicitTypeArgs is empty, this is a noop List substitutedParamTypes = - substituteGenericTypeArgsToExplicit(tree, invokedMethodSymbol, state).getParameterTypes(); + substituteTypeArgsInGenericMethodType(tree, invokedMethodSymbol, state) + .getParameterTypes(); // If this condition evaluates to false, we fall through to the subsequent logic, to handle // type variables declared on the enclosing class if (substitutedParamTypes != null