[java-analysis] Use type nullability in DFA

Fixes IDEA-372347 Java type inference should respect nullability
Fixes IDEA-368244 Unexpected warnings when using @Nullable generic type bounds in @NullMarked context
Fixes IDEA-372223 Nullability inference for generic parameters
Fixes IDEA-367232 'Argument might be null' warning on JSpecify nullable enum

GitOrigin-RevId: 12745f82e22fadb35e23ad73f330501146c86b86
This commit is contained in:
Tagir Valeev
2025-06-12 12:11:23 +00:00
committed by intellij-monorepo-bot
parent a3216712f6
commit 4466a6556b
19 changed files with 229 additions and 137 deletions
@@ -94,6 +94,12 @@ class Descriptable {
@NullMarked
class MarkedAsNull {
void test() {
Person person = new Person("user-name", null);
Assertions.assertThat(person.userType()).isNull();
Assertions.assertThat((Object)null).isNull();
}
public enum UserType { TYPE_1, TYPE_2 }
public record Person (String name, @Nullable UserType userType) {}
}
@@ -0,0 +1,45 @@
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import java.util.function.Supplier;
@NullMarked
class Main {
public static void main(String[] args) {
// (1) No warning expected: Expression 'getNullableObject()' might evaluate to null but is returned by the method declared as @NullMarked
fNullableBound(() -> getNullableObject());
// (2) No warning expected: Function may return null, but it's not allowed here
fNullableBound(Main::getNullableObject);
// No null warnings, as expected (this is the current workaround, to specify T explicitly)
Main.<@Nullable Object>fNullableBound(() -> getNullableObject());
Main.<@Nullable Object>fNullableBound(Main::getNullableObject);
// Expected warning: Expression 'getNullableObject()' might evaluate to null but is returned by the method declared as @NullMarked
fNonNullBound(() -> <warning descr="Expression 'getNullableObject()' might evaluate to null but is returned by the method declared as @NullMarked">getNullableObject()</warning>);
// Expected warning: Function may return null, but it's not allowed here
fNonNullBound(<warning descr="Function may return null, but it's not allowed here">Main::getNullableObject</warning>);
// (3) NICE-TO-HAVE, it would be nice to have a warning that a @Nullable type for T is not allowed
Main.<@Nullable Object>fNonNullBound(() -> <warning descr="Expression 'getNullableObject()' might evaluate to null but is returned by the method declared as @NullMarked">getNullableObject()</warning>);
Main.<@Nullable Object>fNonNullBound(<warning descr="Function may return null, but it's not allowed here">Main::getNullableObject</warning>);
}
static <T extends @Nullable Object> T fNullableBound(Supplier<T> supplier){
return supplier.get();
}
static <T> T fNonNullBound(Supplier<T> supplier){
return supplier.get();
}
static @Nullable Object getNullableObject() {
return null;
}
}
@@ -0,0 +1,21 @@
import org.jetbrains.annotations.NotNull;
import java.util.function.Supplier;
class TestTest {
public void test() {
@NotNull String string = reSupplier(this::supplyString);
onlyNonNull(string);
}
public void onlyNonNull(@NotNull String string) {
}
public @NotNull String supplyString() {
return "test";
}
public <T> T reSupplier(@NotNull Supplier<T> supplier) {
return supplier.get();
}
}
@@ -15,7 +15,7 @@ class Main {
Stream.of("test3")
.map(Main::testNullableStaticMethod)
.map(<warning descr="Method reference argument might be null but passed to non-annotated parameter">Main::requireNonNull</warning>);
.map(Main::requireNonNull);
}
static <T> T requireNonNull(T obj) {