Introduce not null type parameter capability
Java nullability annotations may generate types that currently are not denotable in Kotlin:
class Java {
void <F> foo(@NotNull F f) {}
}
Type of given value parameter should be not nullable under any substitution:
String/String?/String! because of annotation contract.
NB: Currently there is no full analogues for such types in pure kotlin
This commit is contained in:
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
// FILE: A.java
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
public interface A<T> {
|
||||
void foo(@NotNull T x);
|
||||
}
|
||||
|
||||
// FILE: B.java
|
||||
public class B<E> {
|
||||
public void foo(E x) {}
|
||||
}
|
||||
|
||||
// FILE: C.java
|
||||
public class C<F> extends B<F> implements A<F> {
|
||||
public static C<String> create() { return null; }
|
||||
public void foo(F x) {}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun test() {
|
||||
C.create().foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
C.create().foo("")
|
||||
|
||||
C<String>().foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
C<String?>().foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
C<String?>().foo("")
|
||||
}
|
||||
compiler/testData/diagnostics/tests/platformTypes/notNullTypeParameter/enhancementFromAnnotation.txt
Vendored
+30
@@ -0,0 +1,30 @@
|
||||
package
|
||||
|
||||
public /*synthesized*/ fun </*0*/ T : kotlin.Any!> A(/*0*/ function: (T!) -> kotlin.Unit): A<T>
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public interface A</*0*/ T : kotlin.Any!> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract fun foo(/*0*/ @org.jetbrains.annotations.NotNull() x: T): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public open class B</*0*/ E : kotlin.Any!> {
|
||||
public constructor B</*0*/ E : kotlin.Any!>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo(/*0*/ x: E!): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public open class C</*0*/ F : kotlin.Any!> : B<F!>, A<F!> {
|
||||
public constructor C</*0*/ F : kotlin.Any!>()
|
||||
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*2*/ fun foo(/*0*/ x: F): kotlin.Unit
|
||||
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public open fun create(): C<kotlin.String!>!
|
||||
}
|
||||
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
// FILE: A.kt
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
public interface A<T> {
|
||||
fun foo(x: T)
|
||||
}
|
||||
|
||||
// FILE: B.java
|
||||
public class B<E> {
|
||||
public void foo(E x) {}
|
||||
}
|
||||
|
||||
// FILE: C.java
|
||||
public class C<F> extends B<F> implements A<F> {
|
||||
public static C<String> create() { return null; }
|
||||
public void foo(F x) {}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun test() {
|
||||
C.create().foo(null)
|
||||
C.create().foo("")
|
||||
|
||||
C<String>().foo(null)
|
||||
C<String?>().foo(null)
|
||||
C<String?>().foo("")
|
||||
}
|
||||
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
package
|
||||
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public interface A</*0*/ T> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract fun foo(/*0*/ x: T): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public open class B</*0*/ E : kotlin.Any!> {
|
||||
public constructor B</*0*/ E : kotlin.Any!>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo(/*0*/ x: E!): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public open class C</*0*/ F : kotlin.Any!> : B<F!>, A<F!> {
|
||||
public constructor C</*0*/ F : kotlin.Any!>()
|
||||
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*2*/ fun foo(/*0*/ x: F!): kotlin.Unit
|
||||
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public open fun create(): C<kotlin.String!>!
|
||||
}
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
// FILE: A.java
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class A {
|
||||
public static <T> void bar(@NotNull T x, T y) { }
|
||||
public static String platformString() { return null; }
|
||||
}
|
||||
|
||||
// FILE: k.kt
|
||||
|
||||
fun test() {
|
||||
A.<!TYPE_INFERENCE_INCORPORATION_ERROR!>bar<!>(<!NULL_FOR_NONNULL_TYPE!>null<!>, "")
|
||||
|
||||
A.bar<String>(<!NULL_FOR_NONNULL_TYPE!>null<!>, "")
|
||||
A.bar<String?>(<!NULL_FOR_NONNULL_TYPE!>null<!>, "")
|
||||
A.<!TYPE_INFERENCE_INCORPORATION_ERROR!>bar<!>(<!NULL_FOR_NONNULL_TYPE!>null<!>, A.platformString())
|
||||
}
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
package
|
||||
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public open class A {
|
||||
public constructor A()
|
||||
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*/ T : kotlin.Any!> bar(/*0*/ @org.jetbrains.annotations.NotNull() x: T, /*1*/ y: T!): kotlin.Unit
|
||||
public open fun platformString(): kotlin.String!
|
||||
}
|
||||
Vendored
+23
@@ -0,0 +1,23 @@
|
||||
// FILE: A.java
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class A<T> {
|
||||
public static A<String> create() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public T bar() {
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: k.kt
|
||||
|
||||
fun test() {
|
||||
A.create().bar()<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||
A<String?>().bar()<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||
}
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
package
|
||||
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public open class A</*0*/ T : kotlin.Any!> {
|
||||
public constructor A</*0*/ T : kotlin.Any!>()
|
||||
@org.jetbrains.annotations.NotNull() public open fun bar(): 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 open fun create(): A<kotlin.String!>!
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// FILE: A.java
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class A<T> {
|
||||
public static A<String> create() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void bar(@NotNull T x) {
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: k.kt
|
||||
|
||||
fun test() {
|
||||
A.create().bar(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
A.create().bar("")
|
||||
|
||||
A<String>().bar(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
A<String?>().bar(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
A<String?>().bar("")
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package
|
||||
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public open class A</*0*/ T : kotlin.Any!> {
|
||||
public constructor A</*0*/ T : kotlin.Any!>()
|
||||
public open fun bar(/*0*/ @org.jetbrains.annotations.NotNull() x: T): 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
|
||||
|
||||
// Static members
|
||||
public open fun create(): A<kotlin.String!>!
|
||||
}
|
||||
Vendored
+41
@@ -0,0 +1,41 @@
|
||||
// FILE: A.java
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class A<T> {
|
||||
public void bar(@NotNull T x) {
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: B1.java
|
||||
public class B1 extends A<String> {
|
||||
// real override
|
||||
public void bar(String x) {
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: B2.java
|
||||
public class B2 extends A<String> {
|
||||
// fake override bar
|
||||
}
|
||||
|
||||
// FILE: k.kt
|
||||
|
||||
class C1 : A<String?>() {
|
||||
override fun bar(x: String) {}
|
||||
}
|
||||
|
||||
class C2 : A<String?>() {
|
||||
<!NOTHING_TO_OVERRIDE!>override<!> fun bar(x: String?) {}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
B1().bar(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
B2().bar(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
|
||||
C1().bar(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
}
|
||||
|
||||
Vendored
+44
@@ -0,0 +1,44 @@
|
||||
package
|
||||
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public open class A</*0*/ T : kotlin.Any!> {
|
||||
public constructor A</*0*/ T : kotlin.Any!>()
|
||||
public open fun bar(/*0*/ @org.jetbrains.annotations.NotNull() x: T): 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
|
||||
}
|
||||
|
||||
public open class B1 : A<kotlin.String!> {
|
||||
public constructor B1()
|
||||
public open override /*1*/ fun bar(/*0*/ x: kotlin.String): 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
|
||||
}
|
||||
|
||||
public open class B2 : A<kotlin.String!> {
|
||||
public constructor B2()
|
||||
public open override /*1*/ /*fake_override*/ fun bar(/*0*/ @org.jetbrains.annotations.NotNull() x: kotlin.String): 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
|
||||
}
|
||||
|
||||
public final class C1 : A<kotlin.String?> {
|
||||
public constructor C1()
|
||||
public open override /*1*/ fun bar(/*0*/ x: kotlin.String): 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
|
||||
}
|
||||
|
||||
public final class C2 : A<kotlin.String?> {
|
||||
public constructor C2()
|
||||
public open override /*1*/ /*fake_override*/ fun bar(/*0*/ @org.jetbrains.annotations.NotNull() x: kotlin.String): kotlin.Unit
|
||||
public open fun bar(/*0*/ x: kotlin.String?): 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
|
||||
}
|
||||
+1
-1
@@ -22,6 +22,6 @@ val doubleList: List<Double?> = null!!
|
||||
|
||||
fun main() {
|
||||
Test.rawField.foo("", doubleList)
|
||||
Test.rawField.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, doubleList)
|
||||
Test.rawField.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, doubleList)
|
||||
Test.DerivedRawA().foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, doubleList)
|
||||
}
|
||||
|
||||
compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/saveAnnotationAfterSubstitution.kt
Vendored
+2
-6
@@ -24,12 +24,8 @@ public interface B2 extends A<String> {
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
public interface B3 extends A<String> {
|
||||
// inconsistent override, second parameter type is platform
|
||||
// TODO: first one should be platform too, but it's not because when substituting T -> String!,
|
||||
// value parameter type becomes platform and it can be overridden with @NotNull String.
|
||||
// Conceptual problem: we can use type parameter as T?, but there is no way to specify same semantics as in Java `@NotNull T`.
|
||||
|
||||
// override /*1*/ fun foo(/*0*/ org.jetbrains.annotations.Nullable() x: kotlin.String?, /*1*/ org.jetbrains.annotations.NotNull() y: kotlin.String!): kotlin.Unit
|
||||
// inconsistent override, both parameters are platform
|
||||
// override /*1*/ fun foo(/*0*/ org.jetbrains.annotations.Nullable() x: kotlin.String!, /*1*/ org.jetbrains.annotations.NotNull() y: kotlin.String!): kotlin.Unit
|
||||
void foo(@Nullable String x, @NotNull String y);
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package
|
||||
|
||||
public /*synthesized*/ fun </*0*/ T : kotlin.Any!> A(/*0*/ function: (T!, T!) -> kotlin.Unit): A<T>
|
||||
public /*synthesized*/ fun B1(/*0*/ function: (kotlin.String!, kotlin.String?) -> kotlin.Unit): B1
|
||||
public /*synthesized*/ fun B1(/*0*/ function: (kotlin.String, kotlin.String?) -> kotlin.Unit): B1
|
||||
public /*synthesized*/ fun B2(/*0*/ function: (kotlin.String!, kotlin.String!) -> kotlin.Unit): B2
|
||||
public /*synthesized*/ fun B3(/*0*/ function: (kotlin.String!, kotlin.String!) -> kotlin.Unit): B3
|
||||
|
||||
@@ -28,7 +28,7 @@ public interface B2 : A<kotlin.String!> {
|
||||
|
||||
public interface B3 : A<kotlin.String!> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract override /*1*/ fun foo(/*0*/ @org.jetbrains.annotations.Nullable() x: kotlin.String?, /*1*/ @org.jetbrains.annotations.NotNull() y: kotlin.String!): kotlin.Unit
|
||||
public abstract override /*1*/ fun foo(/*0*/ @org.jetbrains.annotations.Nullable() x: kotlin.String!, /*1*/ @org.jetbrains.annotations.NotNull() y: kotlin.String!): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -42,7 +42,7 @@ public interface C1 : A<kotlin.String> {
|
||||
|
||||
public interface C2 : A<kotlin.String?> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ @org.jetbrains.annotations.NotNull() x: kotlin.String?, /*1*/ @org.jetbrains.annotations.Nullable() y: kotlin.String?): kotlin.Unit
|
||||
public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ @org.jetbrains.annotations.NotNull() x: kotlin.String, /*1*/ @org.jetbrains.annotations.Nullable() y: kotlin.String?): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user