Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSpecify: handle Nullability for lambda expression parameters for Generic Types #852

Merged
merged 9 commits into from
Oct 25, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
import static com.uber.nullaway.Nullness.NONNULL;
import static com.uber.nullaway.Nullness.NULLABLE;

import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.LambdaExpressionTree;
import com.sun.source.tree.VariableTree;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.util.Context;
import com.uber.nullaway.CodeAnnotationInfo;
Expand Down Expand Up @@ -92,13 +94,25 @@ private static NullnessStore lambdaInitialStore(
Symbol.MethodSymbol fiMethodSymbol = NullabilityUtil.getFunctionalInterfaceMethod(code, types);
com.sun.tools.javac.util.List<Symbol.VarSymbol> fiMethodParameters =
fiMethodSymbol.getParameters();
// This obtains the Types of the functional interface method with preserved annotations in case
// of generic types
List<Type> overridenMethodParamTypeList =
types.memberType(ASTHelpers.getType(code), fiMethodSymbol).getParameterTypes();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was expecting that somewhere we would have to check the config to see if we were in JSpecify mode. I think that coded this way, this will change NullAway's behavior outside of JSpecify mode, which could turn into a compatibility issue for existing code. Could we change this PR so that the changes only apply in JSpecify mode? Also maybe we should write a test to check that the NullAway behavior when JSpecify mode is off is unchanged.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! Let me know if this works

// If fiArgumentPositionNullness[i] == null, parameter position i is unannotated
Nullness[] fiArgumentPositionNullness = new Nullness[fiMethodParameters.size()];
final boolean isFIAnnotated = !codeAnnotationInfo.isSymbolUnannotated(fiMethodSymbol, config);
if (isFIAnnotated) {
for (int i = 0; i < fiMethodParameters.size(); i++) {
fiArgumentPositionNullness[i] =
Nullness.hasNullableAnnotation(fiMethodParameters.get(i), config) ? NULLABLE : NONNULL;
if (Nullness.hasNullableAnnotation(fiMethodParameters.get(i), config)) {
// Get the Nullness if the Annotation is directly written with the parameter
fiArgumentPositionNullness[i] = NULLABLE;
} else if (Nullness.hasNullableAnnotation(
overridenMethodParamTypeList.get(i).getAnnotationMirrors().stream(), config)) {
// Get the Nullness if the Annotation is indirectly applied through a generic type
fiArgumentPositionNullness[i] = NULLABLE;
} else {
fiArgumentPositionNullness[i] = NONNULL;
}
}
}
fiArgumentPositionNullness =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -596,8 +596,7 @@ public void testForLambdasInAnAssignment() {
" String function(T1 o);",
" }",
" static void testPositive() {",
" // TODO: we should report an error here, since the lambda cannot take",
" // a @Nullable parameter. we don't catch this yet",
" // BUG: Diagnostic contains: dereferenced expression o is @Nullable",
" A<@Nullable Object> p = o -> o.toString();",
" }",
" static void testNegative() {",
Expand Down