Support flexible types internally in typeOf

#KT-45066 Fixed
This commit is contained in:
Alexander Udalov
2021-05-21 19:27:59 +02:00
parent 26cdb2f928
commit 6e975b3498
21 changed files with 358 additions and 42 deletions
@@ -1,26 +0,0 @@
// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
// TARGET_BACKEND: JVM
// WITH_REFLECT
// FILE: box.kt
package test
import kotlin.reflect.*
fun box(): String {
val v = returnTypeOf { J.get() }.toString()
if (v != "J") return "Fail: $v"
return "OK"
}
inline fun <reified T: Any> returnTypeOf(block: () -> T) =
typeOf<T>()
// FILE: J.java
public class J {
public static J get() {
return null;
}
}
@@ -0,0 +1,48 @@
// !API_VERSION: LATEST
// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
// TARGET_BACKEND: JVM
// WITH_REFLECT
// FILE: box.kt
package test
import kotlin.reflect.KType
import kotlin.reflect.typeOf
fun box(): String {
val v1 = returnTypeOf { J.nullabilityFlexible() }.toString()
if (v1 != "kotlin.String!") return "Fail 1: $v1"
val v2 = returnTypeOf { J.mutabilityFlexible() }.toString()
// TODO: should be (Mutable)List after KT-35877.
if (v2 != "kotlin.collections.List<kotlin.String!>") return "Fail 2: $v2"
val v3 = returnTypeOf { J.bothFlexible() }.toString()
// TODO: should be (Mutable)List after KT-35877.
if (v3 != "kotlin.collections.List<kotlin.String!>!") return "Fail 3: $v3"
return "OK"
}
inline fun <reified T : Any> returnTypeOf(block: () -> T) =
typeOf<T>()
// FILE: J.java
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class J {
public static String nullabilityFlexible() {
return null;
}
@NotNull
public static List<String> mutabilityFlexible() {
return null;
}
public static List<String> bothFlexible() {
return null;
}
}
@@ -0,0 +1,46 @@
// !API_VERSION: 1.5
// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
// TARGET_BACKEND: JVM
// WITH_REFLECT
// FILE: box.kt
package test
import kotlin.reflect.KType
import kotlin.reflect.typeOf
fun box(): String {
val v1 = returnTypeOf { J.nullabilityFlexible() }.toString()
if (v1 != "kotlin.String") return "Fail 1: $v1"
val v2 = returnTypeOf { J.mutabilityFlexible() }.toString()
if (v2 != "kotlin.collections.List<kotlin.String>") return "Fail 2: $v2"
val v3 = returnTypeOf { J.bothFlexible() }.toString()
if (v3 != "kotlin.collections.List<kotlin.String>") return "Fail 3: $v3"
return "OK"
}
inline fun <reified T : Any> returnTypeOf(block: () -> T) =
typeOf<T>()
// FILE: J.java
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class J {
public static String nullabilityFlexible() {
return null;
}
@NotNull
public static List<String> mutabilityFlexible() {
return null;
}
public static List<String> bothFlexible() {
return null;
}
}
@@ -0,0 +1,53 @@
// !API_VERSION: LATEST
// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// FILE: box.kt
package test
import kotlin.reflect.KType
import kotlin.reflect.typeOf
import kotlin.test.assertEquals
fun check(expected: String, actual: KType) {
assertEquals(expected + " (Kotlin reflection is not available)", actual.toString())
}
fun box(): String {
// String representation of platform types does not differ from non-nullable types in the stdlib implementation (without reflect).
check("java.lang.String", returnTypeOf { J.nullabilityFlexible() })
check("java.util.List<java.lang.String>", returnTypeOf { J.mutabilityFlexible() })
check("java.util.List<java.lang.String>", returnTypeOf { J.bothFlexible() })
// However, type flexibility affects equality! Platform type is neither nullable nor non-nullable.
val platform = returnTypeOf { J.nullabilityFlexible() }
if (platform == returnTypeOf { J.nullable() }) return "Fail: platform type should not be equal to nullable type"
if (platform == returnTypeOf { J.notNull() }) return "Fail: platform type should not be equal to non-nullable type"
return "OK"
}
inline fun <reified T> returnTypeOf(block: () -> T) =
typeOf<T>()
// FILE: J.java
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class J {
public static String nullabilityFlexible() { return null; }
@NotNull
public static List<String> mutabilityFlexible() { return null; }
public static List<String> bothFlexible() { return null; }
@Nullable
public static String nullable() { return null; }
@NotNull
public static String notNull() { return null; }
}
@@ -0,0 +1,52 @@
// !API_VERSION: 1.5
// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// FILE: box.kt
package test
import kotlin.reflect.KType
import kotlin.reflect.typeOf
import kotlin.test.assertEquals
fun check(expected: String, actual: KType) {
assertEquals(expected + " (Kotlin reflection is not available)", actual.toString())
}
fun box(): String {
check("java.lang.String", returnTypeOf { J.nullabilityFlexible() })
check("java.util.List<java.lang.String>", returnTypeOf { J.mutabilityFlexible() })
check("java.util.List<java.lang.String>", returnTypeOf { J.bothFlexible() })
// Before 1.6, typeOf of a flexible type was represented as non-nullable type in stdlib implementation (without reflect).
val platform = returnTypeOf { J.nullabilityFlexible() }
if (platform == returnTypeOf { J.nullable() }) return "Fail: platform type should not be equal to nullable type"
if (platform != returnTypeOf { J.notNull() }) return "Fail: platform type should be equal to non-nullable type"
return "OK"
}
inline fun <reified T> returnTypeOf(block: () -> T) =
typeOf<T>()
// FILE: J.java
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class J {
public static String nullabilityFlexible() { return null; }
@NotNull
public static List<String> mutabilityFlexible() { return null; }
public static List<String> bothFlexible() { return null; }
@Nullable
public static String nullable() { return null; }
@NotNull
public static String notNull() { return null; }
}