From b44761dc38b90efc5abd047d16a49b21b4864ca2 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Thu, 25 Sep 2025 17:36:21 +0200 Subject: [PATCH] [java-psi] IDEA-379789 Guava. Possible NPE is not highlighted Correct nullability when inferring type variable from eq and lower bounds GitOrigin-RevId: 3c41bda2c36fd24568710ef2c9ca8b5ba0c70414 --- .../graphInference/InferenceSession.java | 3 ++ .../fixture/GuavaIterablesProblems.java | 37 +++++++++++++++++++ .../InheritNullableInstantiateUnknown.java | 17 --------- .../DataFlowInspection21Test.java | 2 +- 4 files changed, 41 insertions(+), 18 deletions(-) create mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/GuavaIterablesProblems.java delete mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/InheritNullableInstantiateUnknown.java diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java index dc6386ea9616..24e616ef6ed1 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java @@ -1192,6 +1192,9 @@ public class InferenceSession { return PsiTypes.nullType(); } else { type = eqBound; + if (!lowerBound.equals(PsiTypes.nullType())) { + type = type.withNullability(eqBound.getNullability().join(lowerBound.getNullability())); + } if (isLowerBoundNotAssignable(var, eqBound, false)) { setErased(); diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/GuavaIterablesProblems.java b/java/java-tests/testData/inspection/dataFlow/fixture/GuavaIterablesProblems.java new file mode 100644 index 000000000000..d7e4c833e8f4 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/GuavaIterablesProblems.java @@ -0,0 +1,37 @@ +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.NotNullByDefault; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +class MyTest { + @NotNullByDefault + static class Iterables { + public static native Iterable concat(Iterable a, Iterable b); + + public static native T[] toArray( + Iterable iterable, Class<@NotNull T> type); + + public static native T get( + Iterable iterable, int position); + } + + + void toArray(List<@Nullable String> l1) { + for (String s : Iterables.toArray(l1, String.class)) { + System.out.println(s.length()); + + } + } + + void get(List<@Nullable String> l1) { + System.out.println(Iterables.get(l1, 0).length()); + + } + + void foo(List l1, List l2) { + for (String s : Iterables.concat(l1, l2)) { + System.out.println(s.length()); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/InheritNullableInstantiateUnknown.java b/java/java-tests/testData/inspection/dataFlow/fixture/InheritNullableInstantiateUnknown.java deleted file mode 100644 index b561fe7b085d..000000000000 --- a/java/java-tests/testData/inspection/dataFlow/fixture/InheritNullableInstantiateUnknown.java +++ /dev/null @@ -1,17 +0,0 @@ -import org.jetbrains.annotations.NotNullByDefault; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -class MyTest { - @NotNullByDefault - static class Iterables { - public static native Iterable concat(Iterable a, Iterable b); - } - - void foo(List l1, List l2) { - for (String s : Iterables.concat(l1, l2)) { - System.out.println(s.length()); - } - } -} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection21Test.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection21Test.java index 5e96dceb6f13..e65611bfa14a 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection21Test.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection21Test.java @@ -212,7 +212,7 @@ public class DataFlowInspection21Test extends DataFlowInspectionTestCase { doTest(); } - public void testInheritNullableInstantiateUnknown() { + public void testGuavaIterablesProblems() { doTest(); }