JVM, JVM IR: erase generic SAM supertypes
Also, do not try to use invokedynamic on SAM calls with intersection
types, because intersection type is not allowed as an immediate type
projection of a supertype, and constructing a fake override in
LambdaMetafactoryArgumentsBuilder led to an exception. This fixes the
problem which was worked around earlier in e6c089ef, effectively
reverting that commit.
The main motivation for this change is that LambdaMetafactory also
doesn't generate generic signature for SAM wrapper classes at runtime.
Since these classes are synthetic, nobody should rely on the fact that
they have generic supertypes, which was observable only via Java
reflection.
#KT-46149 Fixed
#KT-46238 Fixed
This commit is contained in:
@@ -18,6 +18,6 @@ class JavaClass {
|
||||
|
||||
fun box(): String {
|
||||
val supertypes = JavaClass.foo { a, b -> a.compareTo(b) }
|
||||
if (supertypes != "[java.util.Comparator<java.lang.String>]") return "Fail: $supertypes"
|
||||
if (supertypes != "[interface java.util.Comparator]") return "Fail: $supertypes"
|
||||
return "OK"
|
||||
}
|
||||
|
||||
Vendored
-4
@@ -14,10 +14,6 @@ interface A : Top, Unrelated
|
||||
interface B : Top, Unrelated
|
||||
|
||||
fun box(): String {
|
||||
// TODO: https://youtrack.jetbrains.com/issue/KT-46238
|
||||
val version = System.getProperty("java.specification.version")
|
||||
if (version != "1.6" && version != "1.8") return "OK"
|
||||
|
||||
val g = when ("".length) {
|
||||
0 -> G<A>()
|
||||
else -> G<B>()
|
||||
|
||||
+5
-3
@@ -6,8 +6,9 @@
|
||||
// FILE: Custom.java
|
||||
|
||||
class Custom<K, V> {
|
||||
private K k;
|
||||
static Class<?> lambdaClass;
|
||||
|
||||
private K k;
|
||||
private V v;
|
||||
|
||||
public Custom(K k, V v) {
|
||||
@@ -21,6 +22,7 @@ class Custom<K, V> {
|
||||
|
||||
public void forEach(MBiConsumer<? super K, ? super V> action) {
|
||||
action.accept(k, v);
|
||||
lambdaClass = action.getClass();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +38,8 @@ fun box(): String {
|
||||
result = a + b
|
||||
}
|
||||
|
||||
val superInterfaces = Arrays.toString((Class.forName("_1Kt\$box$1")).genericInterfaces)
|
||||
if (superInterfaces != "[Custom\$MBiConsumer<java.lang.String, java.lang.String>]") {
|
||||
val superInterfaces = Arrays.toString(Custom.lambdaClass.genericInterfaces)
|
||||
if (superInterfaces != "[interface Custom\$MBiConsumer]") {
|
||||
return "fail: $superInterfaces"
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ fun box(): String {
|
||||
})
|
||||
|
||||
val superInterfaces = Arrays.toString((Class.forName("_1Kt\$box$1")).genericInterfaces)
|
||||
if (superInterfaces != "[Custom\$MBiConsumer<java.lang.String, java.lang.String>]") {
|
||||
if (superInterfaces != "[interface Custom\$MBiConsumer]") {
|
||||
return "fail: $superInterfaces"
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// SAM_CONVERSIONS: CLASS
|
||||
@@ -36,7 +35,7 @@ fun box(): String {
|
||||
}
|
||||
)
|
||||
|
||||
if (result != "Consumer<java.lang.Object>") return "fail: $result"
|
||||
if (result != "interface Consumer") return "fail: $result"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
+2
-2
@@ -26,7 +26,7 @@ private fun getFirstArgumentType(types: Array<Type>, klass: KClass<*>): String {
|
||||
.filterIsInstance<ParameterizedType>()
|
||||
.firstOrNull { it.rawType == klass.java }
|
||||
?.let { it.actualTypeArguments[0] }
|
||||
?.toString() ?: "fail, inferred type is null"
|
||||
?.toString() ?: "none"
|
||||
}
|
||||
|
||||
class KtProvider : Provider() {
|
||||
@@ -89,5 +89,5 @@ fun box(): String {
|
||||
assertEquals(inferredTypeInSamLambda1, inferredTypeInSamLambda2)
|
||||
assertEquals(inferredTypeInSamLambda2, inferredTypeInSamLambda3)
|
||||
|
||||
return if (inferredTypeInSamLambda1 == "class java.lang.String") "OK" else "fail: $inferredTypeInSamLambda1"
|
||||
return if (inferredTypeInSamLambda1 == "none") "OK" else "fail: $inferredTypeInSamLambda1"
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@ import java.util.Arrays
|
||||
fun box(): String {
|
||||
val r: JavaClass.Computable<String> = JavaClass.Computable { "OK" }
|
||||
val supertypes = Arrays.toString(r.javaClass.getGenericInterfaces())
|
||||
if (supertypes != "[JavaClass\$Computable<java.lang.String>]") return "Fail: $supertypes"
|
||||
if (supertypes != "[interface JavaClass\$Computable]") return "Fail: $supertypes"
|
||||
return JavaClass.compute(r)!!
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// SAM_CONVERSIONS: CLASS
|
||||
// ^ test checks reflection for synthetic classes
|
||||
// FILE: J.java
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
interface S<A extends Number, B extends A, C extends A, D extends Comparable<B>, E extends C> {
|
||||
void accept(A a, B b, C c, D d, E e);
|
||||
}
|
||||
|
||||
class J {
|
||||
public static String foo(S<Number, Long, Integer, Comparable<Long>, Integer> s) {
|
||||
return Arrays.toString(s.getClass().getGenericInterfaces());
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: 1.kt
|
||||
|
||||
fun box(): String {
|
||||
val supertypes = J.foo { a, b, c, d, e -> }
|
||||
return if (supertypes == "[interface S]") "OK" else "Fail: $supertypes"
|
||||
}
|
||||
+1
-1
@@ -5,7 +5,7 @@ public interface<<T:Ljava/lang/Object;>Ljava/lang/Object;> Sam {
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
synthetic final class<Ljava/lang/Object;LSam<TT;>;Lkotlin/jvm/internal/FunctionAdapter;> TKt$genericSam$1 {
|
||||
synthetic final class<null> TKt$genericSam$1 {
|
||||
// source: 't.kt'
|
||||
public final @org.jetbrains.annotations.NotNull <()Lkotlin/Function<*>;> method getFunctionDelegate(): kotlin.Function
|
||||
public final <()TT;> method get(): java.lang.Object
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
@kotlin.Metadata
|
||||
synthetic final class<Ljava/lang/Object;LSam<TT;>;> TKt$genericSam$1 {
|
||||
synthetic final class<null> TKt$genericSam$1 {
|
||||
// source: 't.kt'
|
||||
public final <()TT;> method get(): java.lang.Object
|
||||
static <null> method <clinit>(): void
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ public interface<<T:Ljava/lang/Object;>Ljava/lang/Object;> Sam {
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
synthetic final class<Ljava/lang/Object;LSam<Ljava/lang/String;>;Lkotlin/jvm/internal/FunctionAdapter;> TKt$specializedSam$1 {
|
||||
synthetic final class<null> TKt$specializedSam$1 {
|
||||
// source: 't.kt'
|
||||
public final @org.jetbrains.annotations.NotNull <()Lkotlin/Function<*>;> method getFunctionDelegate(): kotlin.Function
|
||||
static <null> method <clinit>(): void
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
@kotlin.Metadata
|
||||
synthetic final class<Ljava/lang/Object;LSam<Ljava/lang/String;>;> TKt$specializedSam$1 {
|
||||
synthetic final class<null> TKt$specializedSam$1 {
|
||||
// source: 't.kt'
|
||||
static <null> method <clinit>(): void
|
||||
<null> method <init>(): void
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@kotlin.Metadata
|
||||
final class<<IN:Ljava/lang/Object;KEY:Ljava/lang/Object;>Ljava/lang/Object;LKeySelector<Ljava/lang/Integer;Ljava/lang/Long;>;> TKt$main$1 {
|
||||
final class<<IN:Ljava/lang/Object;KEY:Ljava/lang/Object;>Ljava/lang/Object;LKeySelector;> TKt$main$1 {
|
||||
// source: 't.kt'
|
||||
static <null> method <clinit>(): void
|
||||
<null> method <init>(): void
|
||||
@@ -11,7 +11,7 @@ final class<<IN:Ljava/lang/Object;KEY:Ljava/lang/Object;>Ljava/lang/Object;LKeyS
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
final class<<IN:Ljava/lang/Object;KEY:Ljava/lang/Object;>Ljava/lang/Object;LKeySelector<Ljava/lang/Integer;Ljava/lang/Long;>;> TKt$main$2 {
|
||||
final class<<IN:Ljava/lang/Object;KEY:Ljava/lang/Object;>Ljava/lang/Object;LKeySelector;> TKt$main$2 {
|
||||
// source: 't.kt'
|
||||
static <null> method <clinit>(): void
|
||||
<null> method <init>(): void
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@kotlin.Metadata
|
||||
final class<<IN:Ljava/lang/Object;KEY:Ljava/lang/Object;>Ljava/lang/Object;LKeySelector<Ljava/lang/Integer;Ljava/lang/Long;>;> TKt$main$1 {
|
||||
final class<<IN:Ljava/lang/Object;KEY:Ljava/lang/Object;>Ljava/lang/Object;LKeySelector;> TKt$main$1 {
|
||||
// source: 't.kt'
|
||||
static <null> method <clinit>(): void
|
||||
<null> method <init>(): void
|
||||
@@ -11,7 +11,7 @@ final class<<IN:Ljava/lang/Object;KEY:Ljava/lang/Object;>Ljava/lang/Object;LKeyS
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
final class<<IN:Ljava/lang/Object;KEY:Ljava/lang/Object;>Ljava/lang/Object;LKeySelector<Ljava/lang/Integer;Ljava/lang/Long;>;> TKt$main$2 {
|
||||
final class<<IN:Ljava/lang/Object;KEY:Ljava/lang/Object;>Ljava/lang/Object;LKeySelector;> TKt$main$2 {
|
||||
// source: 't.kt'
|
||||
static <null> method <clinit>(): void
|
||||
<null> method <init>(): void
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ public interface<<T:Ljava/lang/Object;>Ljava/lang/Object;> Sam {
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam<TT;>;> TKt$genericSamGet$1 {
|
||||
final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam;> TKt$genericSamGet$1 {
|
||||
// source: 't.kt'
|
||||
public final <()TT;> method get(): java.lang.Object
|
||||
<null> method <init>(p0: kotlin.jvm.functions.Function0): void
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ public interface<<T:Ljava/lang/Object;>Ljava/lang/Object;> Sam {
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam<TT;>;> TKt$genericSamGet$1 {
|
||||
final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam;> TKt$genericSamGet$1 {
|
||||
// source: 't.kt'
|
||||
public final <()TT;> method get(): java.lang.Object
|
||||
<(Lkotlin/jvm/functions/Function0<+TT;>;)V> method <init>(p0: kotlin.jvm.functions.Function0): void
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
@kotlin.Metadata
|
||||
final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam<TT;>;> TKt$genericSam$1 {
|
||||
final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam;> TKt$genericSam$1 {
|
||||
// source: 't.kt'
|
||||
public final <()TT;> method get(): java.lang.Object
|
||||
<null> method <init>(p0: kotlin.jvm.functions.Function0): void
|
||||
@@ -9,7 +9,7 @@ final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam<TT;>;> TKt$genericSam$
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam<TT;>;> TKt$genericSamGet$1 {
|
||||
final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam;> TKt$genericSamGet$1 {
|
||||
// source: 't.kt'
|
||||
public final <()TT;> method get(): java.lang.Object
|
||||
<null> method <init>(p0: kotlin.jvm.functions.Function0): void
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
@kotlin.Metadata
|
||||
final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam<TT;>;> TKt$genericSam$1 {
|
||||
final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam;> TKt$genericSam$1 {
|
||||
// source: 't.kt'
|
||||
public final <()TT;> method get(): java.lang.Object
|
||||
<(Lkotlin/jvm/functions/Function0<+TT;>;)V> method <init>(p0: kotlin.jvm.functions.Function0): void
|
||||
@@ -9,7 +9,7 @@ final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam<TT;>;> TKt$genericSam$
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam<TT;>;> TKt$genericSamGet$1 {
|
||||
final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam;> TKt$genericSamGet$1 {
|
||||
// source: 't.kt'
|
||||
public final <()TT;> method get(): java.lang.Object
|
||||
<(Lkotlin/jvm/functions/Function0<+TT;>;)V> method <init>(p0: kotlin.jvm.functions.Function0): void
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ public interface<<T:Ljava/lang/Object;>Ljava/lang/Object;> Sam {
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam<Ljava/lang/String;>;> TKt$specializedSam$1 {
|
||||
final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam;> TKt$specializedSam$1 {
|
||||
// source: 't.kt'
|
||||
<null> method <init>(p0: kotlin.jvm.functions.Function0): void
|
||||
public synthetic bridge <null> method get(): java.lang.Object
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ public interface<<T:Ljava/lang/Object;>Ljava/lang/Object;> Sam {
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam<Ljava/lang/String;>;> TKt$specializedSam$1 {
|
||||
final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam;> TKt$specializedSam$1 {
|
||||
// source: 't.kt'
|
||||
<(Lkotlin/jvm/functions/Function0<Ljava/lang/String;>;)V> method <init>(p0: kotlin.jvm.functions.Function0): void
|
||||
public synthetic bridge <null> method get(): java.lang.Object
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
@kotlin.Metadata
|
||||
final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam<Ljava/lang/String;>;> TKt$specializedSam$1 {
|
||||
final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam;> TKt$specializedSam$1 {
|
||||
// source: 't.kt'
|
||||
<null> method <init>(p0: kotlin.jvm.functions.Function0): void
|
||||
public synthetic bridge <null> method get(): java.lang.Object
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
@kotlin.Metadata
|
||||
final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam<Ljava/lang/String;>;> TKt$specializedSam$1 {
|
||||
final class<<T:Ljava/lang/Object;>Ljava/lang/Object;LSam;> TKt$specializedSam$1 {
|
||||
// source: 't.kt'
|
||||
<(Lkotlin/jvm/functions/Function0<Ljava/lang/String;>;)V> method <init>(p0: kotlin.jvm.functions.Function0): void
|
||||
public synthetic bridge <null> method get(): java.lang.Object
|
||||
|
||||
Reference in New Issue
Block a user