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:
Denis Zharkov
2016-01-25 14:39:26 +03:00
parent 08dd675fcd
commit 11a96ee8c8
26 changed files with 451 additions and 45 deletions
@@ -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("")
}
@@ -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!>!
}
@@ -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("")
}
@@ -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!>!
}
@@ -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())
}
@@ -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!
}
@@ -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
}
@@ -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!>!
}
@@ -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("")
}
@@ -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!>!
}
@@ -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<!>)
}
@@ -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
}
@@ -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)
}
@@ -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);
}
@@ -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
}