Skip to content

Commit 7b64688

Browse files
authored
Add a case in our inference for generic method calls (uber#1240)
Fixes uber#1238 Before we were missing a fallback case; now we just use the type of the expression computed by `javac` (to be improved in the future). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved handling of nullable type variables in generic methods to ensure correct type inference in assignment contexts. * **Tests** * Added a new test to verify correct behavior when assigning non-nullable arrays to nullable array parameters in generic methods. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 92c9304 commit 7b64688

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

nullaway/src/main/java/com/uber/nullaway/generics/GenericsChecks.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,10 @@ private Type inferGenericMethodCallType(
514514
// TODO we should just strip out the top-level @Nullable annotation;
515515
// stripMetadata() also removes nested @Nullable annotations
516516
substitution.put(typeVar, typeFromAssignmentContext.stripMetadata());
517+
} else {
518+
// Just stick with the original javac type of the expression. As we improve inference
519+
// we will do better.
520+
substitution.put(typeVar, exprType);
517521
}
518522
}
519523

nullaway/src/test/java/com/uber/nullaway/jspecify/GenericMethodTests.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,43 @@ public void typeVarReturnNonNullUpperBound() {
738738
.doTest();
739739
}
740740

741+
@Test
742+
public void issue1238() {
743+
makeHelper()
744+
.addSourceLines(
745+
"CreatorMediator.java",
746+
"import org.jspecify.annotations.NullMarked;",
747+
"import org.jspecify.annotations.Nullable;",
748+
"@NullMarked",
749+
"public class CreatorMediator {",
750+
" private final PropertyModel mCreatorModel = new PropertyModel();",
751+
" private void followClickHandler() {",
752+
" // this is fine: byte[] is assignable to byte @Nullable []",
753+
" WebFeedBridge.followFromId(",
754+
" mCreatorModel.get(CreatorProperties.WEB_FEED_ID_KEY));",
755+
" }",
756+
" private static class PropertyModel {",
757+
" <T extends @Nullable Object> T get(Key<T> key) {",
758+
" throw new RuntimeException();",
759+
" }",
760+
" }",
761+
" private static class CreatorProperties {",
762+
" static final Key<byte[]> WEB_FEED_ID_KEY = makeKey();",
763+
" private static Key<byte[]> makeKey() {",
764+
" throw new RuntimeException();",
765+
" }",
766+
" }",
767+
" private static class WebFeedBridge {",
768+
" static void followFromId(",
769+
" byte @Nullable [] webFeedId) {",
770+
" }",
771+
" }",
772+
" interface Key<T> {",
773+
" }",
774+
"}")
775+
.doTest();
776+
}
777+
741778
private CompilationTestHelper makeHelper() {
742779
return makeTestHelperWithArgs(
743780
Arrays.asList(

0 commit comments

Comments
 (0)