[FIR] Implement warnings for java nullability type mismatch
#KT-56989
This commit is contained in:
committed by
Space Team
parent
1ecbc094ec
commit
a6fdeeb7df
-80
@@ -1,80 +0,0 @@
|
||||
// JSPECIFY_STATE: warn
|
||||
// MUTE_FOR_PSI_CLASS_FILES_READING
|
||||
|
||||
// FILE: AnnotatedBoundsOfWildcard.java
|
||||
import org.jspecify.annotations.*;
|
||||
|
||||
@NullMarked
|
||||
public class AnnotatedBoundsOfWildcard {
|
||||
public void superAsIs(Test<? super Base, ? super @Nullable Base, ? super @NullnessUnspecified Base> a) {}
|
||||
public void superNotNull(Test<? super Base, ? super Base, ? super Base> a) {}
|
||||
public void superNullable(Test<? super @Nullable Base, ? super @Nullable Base, ? super @Nullable Base> a) {}
|
||||
|
||||
public void extendsAsIs(Test<? extends Base, ? extends @Nullable Base, ? extends @NullnessUnspecified Base> a) {}
|
||||
public void extendsNotNull(Test<? extends Base, ? extends Base, ? extends Base> a) {}
|
||||
public void extendsNullable(Test<? extends @Nullable Base, ? extends @Nullable Base, ? extends @Nullable Base> a) {}
|
||||
|
||||
public void noBounds(Test<? extends @NullnessUnspecified Object, ? extends @NullnessUnspecified Object, ? extends @NullnessUnspecified Object> a) {}
|
||||
}
|
||||
|
||||
// FILE: Base.java
|
||||
public class Base {}
|
||||
|
||||
// FILE: Derived.java
|
||||
public class Derived extends Base {}
|
||||
|
||||
// FILE: Test.java
|
||||
import org.jspecify.annotations.*;
|
||||
|
||||
@NullMarked
|
||||
public class Test<T extends Object, E extends @Nullable Object, F extends @NullnessUnspecified Object> { }
|
||||
|
||||
// FILE: main.kt
|
||||
fun main(
|
||||
aNotNullNotNullNotNull: Test<Derived, Derived, Derived>,
|
||||
aNotNullNotNullNull: Test<Derived, Derived, Derived?>,
|
||||
aNotNullNullNotNull: Test<Derived, Derived?, Derived>,
|
||||
aNotNullNullNull: Test<Derived, Derived?, Derived?>,
|
||||
|
||||
aAnyNotNullNotNullNotNull: Test<Any, Any, Any>,
|
||||
aAnyNotNullNotNullNull: Test<Any, Any, Any?>,
|
||||
aAnyNotNullNullNotNull: Test<Any, Any?, Any>,
|
||||
aAnyNotNullNullNull: Test<Any, Any?, Any?>,
|
||||
|
||||
b: AnnotatedBoundsOfWildcard
|
||||
): Unit {
|
||||
b.superAsIs(aAnyNotNullNotNullNotNull)
|
||||
b.superAsIs(aAnyNotNullNotNullNull)
|
||||
b.superAsIs(aAnyNotNullNullNotNull)
|
||||
b.superAsIs(aAnyNotNullNullNull)
|
||||
|
||||
b.superNotNull(aAnyNotNullNotNullNotNull)
|
||||
b.superNotNull(aAnyNotNullNotNullNull)
|
||||
b.superNotNull(aAnyNotNullNullNotNull)
|
||||
b.superNotNull(aAnyNotNullNullNull)
|
||||
|
||||
b.superNullable(aAnyNotNullNotNullNotNull)
|
||||
b.superNullable(aAnyNotNullNotNullNull)
|
||||
b.superNullable(aAnyNotNullNullNotNull)
|
||||
b.superNullable(aAnyNotNullNullNull)
|
||||
|
||||
b.extendsAsIs(aNotNullNotNullNotNull)
|
||||
b.extendsAsIs(aNotNullNotNullNull)
|
||||
b.extendsAsIs(aNotNullNullNotNull)
|
||||
b.extendsAsIs(aNotNullNullNull)
|
||||
|
||||
b.extendsNotNull(aNotNullNotNullNotNull)
|
||||
b.extendsNotNull(aNotNullNotNullNull)
|
||||
b.extendsNotNull(aNotNullNullNotNull)
|
||||
b.extendsNotNull(aNotNullNullNull)
|
||||
|
||||
b.extendsNullable(aNotNullNotNullNotNull)
|
||||
b.extendsNullable(aNotNullNotNullNull)
|
||||
b.extendsNullable(aNotNullNullNotNull)
|
||||
b.extendsNullable(aNotNullNullNull)
|
||||
|
||||
b.noBounds(aNotNullNotNullNotNull)
|
||||
b.noBounds(aNotNullNotNullNull)
|
||||
b.noBounds(aNotNullNullNotNull)
|
||||
b.noBounds(aNotNullNullNull)
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// JSPECIFY_STATE: warn
|
||||
// MUTE_FOR_PSI_CLASS_FILES_READING
|
||||
|
||||
|
||||
Vendored
-45
@@ -1,45 +0,0 @@
|
||||
// JSPECIFY_STATE: warn
|
||||
|
||||
// FILE: Defaults.java
|
||||
import org.jspecify.annotations.*;
|
||||
|
||||
@NullMarked
|
||||
public class Defaults {
|
||||
public Foo defaultField = null;
|
||||
@Nullable public Foo field = null;
|
||||
|
||||
public Foo everythingNotNullable(Foo x) { return null; }
|
||||
|
||||
public @Nullable Foo everythingNullable(@Nullable Foo x) { return null; }
|
||||
|
||||
public @NullnessUnspecified Foo everythingUnknown(@NullnessUnspecified Foo x) { return null; }
|
||||
|
||||
public @Nullable Foo mixed(Foo x) { return null; }
|
||||
|
||||
public Foo explicitlyNullnessUnspecified(@NullnessUnspecified Foo x) { return null; }
|
||||
}
|
||||
|
||||
// FILE: Foo.java
|
||||
public class Foo {
|
||||
public Object foo() { return null; }
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun main(a: Defaults, x: Foo): Unit {
|
||||
a.everythingNotNullable(null).foo()
|
||||
a.everythingNotNullable(x).foo()
|
||||
|
||||
a.everythingNullable(null).foo()
|
||||
|
||||
a.everythingUnknown(null).foo()
|
||||
|
||||
a.mixed(null).foo()
|
||||
a.mixed(x).foo()
|
||||
|
||||
a.explicitlyNullnessUnspecified(x).foo()
|
||||
a.explicitlyNullnessUnspecified(null).foo()
|
||||
|
||||
a.defaultField.foo()
|
||||
|
||||
a.field.foo()
|
||||
}
|
||||
Vendored
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// JSPECIFY_STATE: warn
|
||||
|
||||
// FILE: Defaults.java
|
||||
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
// JSPECIFY_STATE: warn
|
||||
|
||||
// FILE: IgnoreAnnotations.java
|
||||
import org.jspecify.annotations.*;
|
||||
|
||||
@NullMarked
|
||||
public class IgnoreAnnotations {
|
||||
@Nullable public Derived field = null;
|
||||
|
||||
@Nullable
|
||||
public Derived foo(Derived x, @NullnessUnspecified Base y) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Derived everythingNotNullable(Derived x) { return null; }
|
||||
|
||||
public @Nullable Derived everythingNullable(@Nullable Derived x) { return null; }
|
||||
|
||||
public @NullnessUnspecified Derived everythingUnknown(@NullnessUnspecified Derived x) { return null; }
|
||||
}
|
||||
|
||||
// FILE: Base.java
|
||||
public class Base {
|
||||
void foo() {}
|
||||
}
|
||||
|
||||
// FILE: Derived.java
|
||||
public class Derived extends Base { }
|
||||
|
||||
// FILE: main.kt
|
||||
fun main(a: IgnoreAnnotations, x: Derived): Unit {
|
||||
a.foo(x, null).foo()
|
||||
a.foo(null, x).foo()
|
||||
|
||||
a.field.foo()
|
||||
|
||||
a.everythingNotNullable(null).foo()
|
||||
a.everythingNotNullable(x).foo()
|
||||
|
||||
a.everythingNullable(null).foo()
|
||||
|
||||
a.everythingUnknown(null).foo()
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// JSPECIFY_STATE: warn
|
||||
|
||||
// FILE: IgnoreAnnotations.java
|
||||
|
||||
+8
-4
@@ -14,17 +14,21 @@ public class Test {}
|
||||
|
||||
// FILE: main.kt
|
||||
fun main(a1: NullnessUnspecifiedTypeParameter<Any>, a2: NullnessUnspecifiedTypeParameter<Any?>, x: Test): Unit {
|
||||
a1.foo(null)
|
||||
// jspecify_nullness_mismatch
|
||||
a1.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
a1.foo(1)
|
||||
|
||||
a2.foo(null)
|
||||
a2.foo(1)
|
||||
|
||||
a1.bar(null, null)
|
||||
a1.bar(x, null)
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
a1.bar(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, <!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
// jspecify_nullness_mismatch
|
||||
a1.bar(x, <!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
a1.bar(x, 1)
|
||||
|
||||
a2.bar(null, null)
|
||||
// jspecify_nullness_mismatch
|
||||
a2.bar(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, null)
|
||||
a2.bar(x, null)
|
||||
a2.bar(x, 1)
|
||||
}
|
||||
|
||||
Vendored
-36
@@ -1,36 +0,0 @@
|
||||
// JSPECIFY_STATE: warn
|
||||
|
||||
// FILE: Simple.java
|
||||
import org.jspecify.annotations.*;
|
||||
|
||||
@NullMarked
|
||||
public class Simple {
|
||||
@Nullable public Derived field = null;
|
||||
|
||||
@Nullable
|
||||
public Derived foo(Derived x, @NullnessUnspecified Base y) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Derived bar() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: Base.java
|
||||
public class Base {}
|
||||
|
||||
// FILE: Derived.java
|
||||
public class Derived extends Base {
|
||||
void foo() {}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun main(a: Simple, x: Derived): Unit {
|
||||
a.foo(x, null).foo()
|
||||
a.foo(null, x).foo()
|
||||
|
||||
a.bar().foo()
|
||||
|
||||
a.field.foo()
|
||||
}
|
||||
Vendored
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// JSPECIFY_STATE: warn
|
||||
|
||||
// FILE: Simple.java
|
||||
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
// JSPECIFY_STATE: warn
|
||||
// MUTE_FOR_PSI_CLASS_FILES_READING
|
||||
|
||||
// FILE: TypeArgumentsFromParameterBounds.java
|
||||
import org.jspecify.annotations.*;
|
||||
|
||||
@NullMarked
|
||||
public class TypeArgumentsFromParameterBounds<T extends Object, E extends @Nullable Object, F extends @NullnessUnspecified Object> {}
|
||||
|
||||
// FILE: A.java
|
||||
import org.jspecify.annotations.*;
|
||||
|
||||
@NullMarked
|
||||
public class A {
|
||||
public void bar(TypeArgumentsFromParameterBounds<Test, Test, Test> a) {}
|
||||
}
|
||||
|
||||
// FILE: B.java
|
||||
import org.jspecify.annotations.*;
|
||||
|
||||
public class B {
|
||||
public void bar(TypeArgumentsFromParameterBounds<Test, Test, Test> a) {}
|
||||
}
|
||||
|
||||
// FILE: Test.java
|
||||
public class Test {}
|
||||
|
||||
// FILE: main.kt
|
||||
fun main(
|
||||
aNotNullNotNullNotNull: TypeArgumentsFromParameterBounds<Test, Test, Test>,
|
||||
aNotNullNotNullNull: TypeArgumentsFromParameterBounds<Test, Test, Test?>,
|
||||
aNotNullNullNotNull: TypeArgumentsFromParameterBounds<Test, Test?, Test>,
|
||||
aNotNullNullNull: TypeArgumentsFromParameterBounds<Test, Test?, Test?>,
|
||||
a: A, b: B
|
||||
): Unit {
|
||||
a.bar(aNotNullNotNullNotNull)
|
||||
a.bar(aNotNullNotNullNull)
|
||||
a.bar(aNotNullNullNotNull)
|
||||
a.bar(aNotNullNullNull)
|
||||
|
||||
b.bar(aNotNullNotNullNotNull)
|
||||
b.bar(aNotNullNotNullNull)
|
||||
b.bar(aNotNullNullNotNull)
|
||||
b.bar(aNotNullNullNull)
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// JSPECIFY_STATE: warn
|
||||
// MUTE_FOR_PSI_CLASS_FILES_READING
|
||||
|
||||
|
||||
+2
-1
@@ -33,7 +33,8 @@ fun <T : Test> main(a1: A<Any?>, a2: A<Test>, b1: B<Any?>, b2: B<Test>, x: T): U
|
||||
b1.bar<T?>(null)
|
||||
b1.bar<T>(x)
|
||||
|
||||
b2.foo(null)
|
||||
// jspecify_nullness_mismatch
|
||||
b2.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
b2.bar<T?>(null)
|
||||
b2.bar<T>(x)
|
||||
}
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// JSPECIFY_STATE: warn
|
||||
// FILE: J1.java
|
||||
import org.jspecify.annotations.*;
|
||||
|
||||
@NullMarked
|
||||
public interface J1<T extends @Nullable Object> {
|
||||
T foo();
|
||||
}
|
||||
|
||||
// FILE: J2.java
|
||||
public interface J2 {
|
||||
J1<?> bar();
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
// jspecify_nullness_mismatch
|
||||
fun baz(j2: J2): Any = <!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>j2.bar().foo()<!> // Any..Any?
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// FIR_IDENTICAL
|
||||
// JSPECIFY_STATE: warn
|
||||
// FILE: J1.java
|
||||
import org.jspecify.annotations.*;
|
||||
|
||||
Vendored
-15
@@ -1,15 +0,0 @@
|
||||
// JSPECIFY_STATE: warn
|
||||
|
||||
// FILE: Foo.java
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public static <T> void gauge(@Nullable T stateObject) {}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun <T> test(metric: T) {
|
||||
if (metric is String) {
|
||||
Foo.gauge(metric)
|
||||
}
|
||||
}
|
||||
Vendored
+3
-1
@@ -1,3 +1,5 @@
|
||||
// FIR_IDENTICAL
|
||||
// DIAGNOSTICS: -DEBUG_INFO_SMARTCAST
|
||||
// JSPECIFY_STATE: warn
|
||||
|
||||
// FILE: Foo.java
|
||||
@@ -10,6 +12,6 @@ public class Foo {
|
||||
// FILE: main.kt
|
||||
fun <T> test(metric: T) {
|
||||
if (metric is String) {
|
||||
Foo.gauge(<!DEBUG_INFO_SMARTCAST!>metric<!>)
|
||||
Foo.gauge(metric)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user