Prefer flexible nullability by Java annotations to nullable one if the corresponding type parameter has nullable bound

^KT-47422 Fixed
This commit is contained in:
Victor Petukhov
2021-07-19 14:24:17 +03:00
committed by teamcityserver
parent 2c9857b880
commit 99491014e4
14 changed files with 306 additions and 18 deletions
@@ -42,10 +42,8 @@ fun main(
// jspecify_nullness_mismatch
a.bar(<!TYPE_MISMATCH!>aNotNullNullNull<!>)
// jspecify_nullness_mismatch
b.bar(<!TYPE_MISMATCH!>aNotNullNotNullNotNull<!>)
// jspecify_nullness_mismatch
b.bar(<!TYPE_MISMATCH!>aNotNullNotNullNull<!>)
b.bar(aNotNullNotNullNotNull)
b.bar(aNotNullNotNullNull)
b.bar(aNotNullNullNotNull)
b.bar(aNotNullNullNull)
}
@@ -12,7 +12,7 @@ public fun main(/*0*/ aNotNullNotNullNotNull: TypeArgumentsFromParameterBounds<T
public open class B {
public constructor B()
public open fun bar(/*0*/ a: TypeArgumentsFromParameterBounds<Test, Test?, Test!>!): kotlin.Unit
public open fun bar(/*0*/ a: TypeArgumentsFromParameterBounds<Test, Test!, Test!>!): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
@@ -42,10 +42,8 @@ fun main(
// jspecify_nullness_mismatch
a.bar(<!TYPE_MISMATCH!>aNotNullNullNull<!>)
// jspecify_nullness_mismatch
b.bar(<!TYPE_MISMATCH!>aNotNullNotNullNotNull<!>)
// jspecify_nullness_mismatch
b.bar(<!TYPE_MISMATCH!>aNotNullNotNullNull<!>)
b.bar(aNotNullNotNullNotNull)
b.bar(aNotNullNotNullNull)
b.bar(aNotNullNullNotNull)
b.bar(aNotNullNullNull)
}
@@ -12,7 +12,7 @@ public fun main(/*0*/ aNotNullNotNullNotNull: TypeArgumentsFromParameterBounds<T
public open class B {
public constructor B()
public open fun bar(/*0*/ a: TypeArgumentsFromParameterBounds<Test, Test?, Test!>!): kotlin.Unit
public open fun bar(/*0*/ a: TypeArgumentsFromParameterBounds<Test, Test!, Test!>!): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
@@ -0,0 +1,136 @@
// JSPECIFY_STATE: strict
// !DIAGNOSTICS: -UNUSED_PARAMETER
// !LANGUAGE: +TypeEnhancementImprovementsInStrictMode
// FILE: Foo.java
import org.jspecify.nullness.*;
public interface Foo<T extends @Nullable Object> {}
// FILE: Util.java
public class Util {
public static Foo<String> getFooOfString() {
throw new RuntimeException();
}
}
// FILE: UtilNullMarked.java
import org.jspecify.nullness.*;
@NullMarked
public class UtilNullMarked {
public static Foo<String> getFooOfString() {
throw new RuntimeException();
}
}
// FILE: UtilNullMarkedGeneric.java
import org.jspecify.nullness.*;
@NullMarked
public class UtilNullMarkedGeneric {
public static <K> Foo<K> getFooOfK() {
throw new RuntimeException();
}
}
// FILE: UtilNullMarkedGenericNullableBound.java
import org.jspecify.nullness.*;
@NullMarked
public class UtilNullMarkedGenericNullableBound {
public static <K extends @Nullable Object> Foo<K> getFooOfK() {
throw new RuntimeException();
}
}
// FILE: UtilGenericNullableBound.java
import org.jspecify.nullness.*;
public class UtilGenericNullableBound {
public static <K extends @Nullable Object> Foo<K> getFooOfK() {
throw new RuntimeException();
}
}
// FILE: UtilNullMarkedGenericNullnessUnspecifiedBound.java
import org.jspecify.nullness.*;
@NullMarked
public class UtilNullMarkedGenericNullnessUnspecifiedBound {
public static <K extends @NullnessUnspecified Object> Foo<K> getFooOfK() {
throw new RuntimeException();
}
}
// FILE: UtilGenericNullnessUnspecifiedBound.java
import org.jspecify.nullness.*;
public class UtilGenericNullnessUnspecifiedBound {
public static <K extends @NullnessUnspecified Object> Foo<K> getFooOfK() {
throw new RuntimeException();
}
}
// FILE: main.kt
// no errors on this call means String in Foo is flexible
fun isNotNullAndNullableStringInFoo(x: Foo<String>, y: Foo<String?>) {}
fun test1() {
// String in Foo is flexible
isNotNullAndNullableStringInFoo(
Util.getFooOfString(),
Util.getFooOfString()
)
}
fun test2() {
// String in Foo is not null
isNotNullAndNullableStringInFoo(
UtilNullMarked.getFooOfString(),
// jspecify_nullness_mismatch
<!TYPE_MISMATCH!>UtilNullMarked.getFooOfString()<!>
)
}
fun test3() {
// String in Foo is not null
isNotNullAndNullableStringInFoo(
UtilNullMarkedGeneric.getFooOfK(),
// jspecify_nullness_mismatch
<!TYPE_MISMATCH!>UtilNullMarkedGeneric.getFooOfK()<!>
)
}
fun test4() {
// String in Foo is flexible
isNotNullAndNullableStringInFoo(
UtilNullMarkedGenericNullableBound.getFooOfK(),
UtilNullMarkedGenericNullableBound.getFooOfK()
)
}
fun test5() {
// String in Foo is flexible
isNotNullAndNullableStringInFoo(
UtilGenericNullableBound.getFooOfK(),
UtilGenericNullableBound.getFooOfK()
)
}
fun test6() {
// String in Foo is flexible
isNotNullAndNullableStringInFoo(
UtilNullMarkedGenericNullnessUnspecifiedBound.getFooOfK(),
UtilNullMarkedGenericNullnessUnspecifiedBound.getFooOfK()
)
}
fun test7() {
// String in Foo is flexible
isNotNullAndNullableStringInFoo(
UtilGenericNullnessUnspecifiedBound.getFooOfK(),
UtilGenericNullnessUnspecifiedBound.getFooOfK()
)
}
@@ -0,0 +1,86 @@
package
public fun isNotNullAndNullableStringInFoo(/*0*/ x: Foo<kotlin.String>, /*1*/ y: Foo<kotlin.String?>): kotlin.Unit
public fun test1(): kotlin.Unit
public fun test2(): kotlin.Unit
public fun test3(): kotlin.Unit
public fun test4(): kotlin.Unit
public fun test5(): kotlin.Unit
public fun test6(): kotlin.Unit
public fun test7(): kotlin.Unit
public interface Foo</*0*/ T> {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public open class Util {
public constructor Util()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public open fun getFooOfString(): Foo<kotlin.String!>!
}
public open class UtilGenericNullableBound {
public constructor UtilGenericNullableBound()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public open fun </*0*/ K> getFooOfK(): Foo<K>!
}
public open class UtilGenericNullnessUnspecifiedBound {
public constructor UtilGenericNullnessUnspecifiedBound()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public open fun </*0*/ K : @org.jspecify.nullness.NullnessUnspecified kotlin.Any!> getFooOfK(): Foo<K!>!
}
@org.jspecify.nullness.NullMarked public open class UtilNullMarked {
public constructor UtilNullMarked()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public open fun getFooOfString(): Foo<kotlin.String>
}
@org.jspecify.nullness.NullMarked public open class UtilNullMarkedGeneric {
public constructor UtilNullMarkedGeneric()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public open fun </*0*/ K : kotlin.Any> getFooOfK(): Foo<K>
}
@org.jspecify.nullness.NullMarked public open class UtilNullMarkedGenericNullableBound {
public constructor UtilNullMarkedGenericNullableBound()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public open fun </*0*/ K> getFooOfK(): Foo<K>
}
@org.jspecify.nullness.NullMarked public open class UtilNullMarkedGenericNullnessUnspecifiedBound {
public constructor UtilNullMarkedGenericNullnessUnspecifiedBound()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public open fun </*0*/ K : @org.jspecify.nullness.NullnessUnspecified kotlin.Any!> getFooOfK(): Foo<K!>
}
@@ -0,0 +1,17 @@
// JSPECIFY_STATE: strict
// !LANGUAGE: +TypeEnhancementImprovementsInStrictMode
// FILE: Foo.java
import org.jspecify.nullness.*;
@NullMarked
public class Foo<T extends @Nullable Object> {
static <T extends Comparable> Foo<T> create() {
return new Foo<>();
}
}
// FILE: main.kt
fun test(): Foo<String> {
return <!DEBUG_INFO_EXPRESSION_TYPE("Foo<(kotlin.String..kotlin.String?)>")!>Foo.create()<!>
}
@@ -0,0 +1,13 @@
package
public fun test(): Foo<kotlin.String>
@org.jspecify.nullness.NullMarked public open class Foo</*0*/ T> {
public constructor Foo</*0*/ T>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public/*package*/ open fun </*0*/ T : (kotlin.Comparable<(raw) kotlin.Any?>..kotlin.Comparable<kotlin.Nothing>?)> create(): Foo<T!>
}