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:
Alexander Udalov
2021-04-21 18:41:18 +02:00
parent 1093bffc62
commit b2005302dc
30 changed files with 97 additions and 45 deletions
@@ -9,8 +9,6 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator
import org.jetbrains.kotlin.resolve.calls.commonSuperType
import org.jetbrains.kotlin.resolve.sam.getAbstractMembers import org.jetbrains.kotlin.resolve.sam.getAbstractMembers
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithNothing import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithNothing
@@ -82,15 +80,7 @@ open class SamTypeFactory {
} }
private fun KotlinType.removeExternalProjections(): KotlinType { private fun KotlinType.removeExternalProjections(): KotlinType {
val newArguments = arguments.map { val newArguments = arguments.map { TypeProjectionImpl(Variance.INVARIANT, it.type) }
val type = it.type
TypeProjectionImpl(
Variance.INVARIANT,
if (type.constructor is IntersectionTypeConstructor)
NewCommonSuperTypeCalculator.commonSuperType(type.constructor.supertypes.map(KotlinType::unwrap))
else type
)
}
return replace(newArguments) return replace(newArguments)
} }
@@ -158,7 +158,14 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
for (int i = 0; i < superInterfaceTypes.size(); i++) { for (int i = 0; i < superInterfaceTypes.size(); i++) {
KotlinType superInterfaceType = superInterfaceTypes.get(i); KotlinType superInterfaceType = superInterfaceTypes.get(i);
sw.writeInterface(); sw.writeInterface();
superInterfaceAsmTypes[i] = typeMapper.mapSupertype(superInterfaceType, sw).getInternalName(); Type superInterfaceAsmType;
if (samType != null && superInterfaceType.getConstructor() == samType.getType().getConstructor()) {
superInterfaceAsmType = typeMapper.mapSupertype(superInterfaceType, null);
sw.writeAsmType(superInterfaceAsmType);
} else {
superInterfaceAsmType = typeMapper.mapSupertype(superInterfaceType, sw);
}
superInterfaceAsmTypes[i] = superInterfaceAsmType.getInternalName();
sw.writeInterfaceEnd(); sw.writeInterfaceEnd();
} }
@@ -38084,6 +38084,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/sam/samConversionToJavaWildcard.kt"); runTest("compiler/testData/codegen/box/sam/samConversionToJavaWildcard.kt");
} }
@Test
@TestMetadata("samInterfaceTypeParameterErasure.kt")
public void testSamInterfaceTypeParameterErasure() throws Exception {
runTest("compiler/testData/codegen/box/sam/samInterfaceTypeParameterErasure.kt");
}
@Test @Test
@TestMetadata("smartCastSamConversion.kt") @TestMetadata("smartCastSamConversion.kt")
public void testSmartCastSamConversion() throws Exception { public void testSmartCastSamConversion() throws Exception {
@@ -187,7 +187,11 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
} }
} }
return FunctionReferenceBuilder(reference, samSuperType).build() // Erase generic arguments in the SAM type, because they are not easy to approximate correctly otherwise,
// and LambdaMetafactory also uses erased type.
val erasedSamSuperType = samSuperType.erasedUpperBound.rawType(context)
return FunctionReferenceBuilder(reference, erasedSamSuperType).build()
} }
private fun canGenerateIndySamConversionOnFunctionalExpression(samSuperType: IrType, expression: IrExpression): Boolean { private fun canGenerateIndySamConversionOnFunctionalExpression(samSuperType: IrType, expression: IrExpression): Boolean {
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
internal class LambdaMetafactoryArguments( internal class LambdaMetafactoryArguments(
@@ -105,6 +106,12 @@ internal class LambdaMetafactoryArgumentsBuilder(
if (implFun.parents.any { it.isInlineFunction() || it.isCrossinlineLambda() }) if (implFun.parents.any { it.isInlineFunction() || it.isCrossinlineLambda() })
return null return null
// Don't try to use indy on SAM types with non-invariant projections because buildFakeOverrideMember doesn't support such supertypes
// (and rightly so: supertypes in Kotlin can't have projections in immediate type arguments). This can happen for example in case
// the SAM type is instantiated with an intersection type in arguments, which is approximated to an out-projection in psi2ir.
if (samType is IrSimpleType && samType.arguments.any { it is IrTypeProjection && it.variance != Variance.INVARIANT })
return null
// Do the hard work of matching Kotlin functional interface hierarchy against LambdaMetafactory constraints. // Do the hard work of matching Kotlin functional interface hierarchy against LambdaMetafactory constraints.
// Briefly: sometimes we have to force boxing on the primitive and inline class values, sometimes we have to keep them unboxed. // Briefly: sometimes we have to force boxing on the primitive and inline class values, sometimes we have to keep them unboxed.
// If this results in conflicting requirements, we can't use INVOKEDYNAMIC with LambdaMetafactory for creating a closure. // If this results in conflicting requirements, we can't use INVOKEDYNAMIC with LambdaMetafactory for creating a closure.
@@ -18,6 +18,6 @@ class JavaClass {
fun box(): String { fun box(): String {
val supertypes = JavaClass.foo { a, b -> a.compareTo(b) } 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" return "OK"
} }
@@ -14,10 +14,6 @@ interface A : Top, Unrelated
interface B : Top, Unrelated interface B : Top, Unrelated
fun box(): String { 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) { val g = when ("".length) {
0 -> G<A>() 0 -> G<A>()
else -> G<B>() else -> G<B>()
+5 -3
View File
@@ -6,8 +6,9 @@
// FILE: Custom.java // FILE: Custom.java
class Custom<K, V> { class Custom<K, V> {
private K k; static Class<?> lambdaClass;
private K k;
private V v; private V v;
public Custom(K k, 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) { public void forEach(MBiConsumer<? super K, ? super V> action) {
action.accept(k, v); action.accept(k, v);
lambdaClass = action.getClass();
} }
} }
@@ -36,8 +38,8 @@ fun box(): String {
result = a + b result = a + b
} }
val superInterfaces = Arrays.toString((Class.forName("_1Kt\$box$1")).genericInterfaces) val superInterfaces = Arrays.toString(Custom.lambdaClass.genericInterfaces)
if (superInterfaces != "[Custom\$MBiConsumer<java.lang.String, java.lang.String>]") { if (superInterfaces != "[interface Custom\$MBiConsumer]") {
return "fail: $superInterfaces" return "fail: $superInterfaces"
} }
+1 -1
View File
@@ -37,7 +37,7 @@ fun box(): String {
}) })
val superInterfaces = Arrays.toString((Class.forName("_1Kt\$box$1")).genericInterfaces) 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" return "fail: $superInterfaces"
} }
+1 -2
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// WITH_RUNTIME // WITH_RUNTIME
// SAM_CONVERSIONS: CLASS // 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" return "OK"
} }
@@ -26,7 +26,7 @@ private fun getFirstArgumentType(types: Array<Type>, klass: KClass<*>): String {
.filterIsInstance<ParameterizedType>() .filterIsInstance<ParameterizedType>()
.firstOrNull { it.rawType == klass.java } .firstOrNull { it.rawType == klass.java }
?.let { it.actualTypeArguments[0] } ?.let { it.actualTypeArguments[0] }
?.toString() ?: "fail, inferred type is null" ?.toString() ?: "none"
} }
class KtProvider : Provider() { class KtProvider : Provider() {
@@ -89,5 +89,5 @@ fun box(): String {
assertEquals(inferredTypeInSamLambda1, inferredTypeInSamLambda2) assertEquals(inferredTypeInSamLambda1, inferredTypeInSamLambda2)
assertEquals(inferredTypeInSamLambda2, inferredTypeInSamLambda3) 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 { fun box(): String {
val r: JavaClass.Computable<String> = JavaClass.Computable { "OK" } val r: JavaClass.Computable<String> = JavaClass.Computable { "OK" }
val supertypes = Arrays.toString(r.javaClass.getGenericInterfaces()) 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)!! 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"
}
@@ -5,7 +5,7 @@ public interface<<T:Ljava/lang/Object;>Ljava/lang/Object;> Sam {
} }
@kotlin.Metadata @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' // source: 't.kt'
public final @org.jetbrains.annotations.NotNull <()Lkotlin/Function<*>;> method getFunctionDelegate(): kotlin.Function public final @org.jetbrains.annotations.NotNull <()Lkotlin/Function<*>;> method getFunctionDelegate(): kotlin.Function
public final <()TT;> method get(): java.lang.Object public final <()TT;> method get(): java.lang.Object
@@ -1,5 +1,5 @@
@kotlin.Metadata @kotlin.Metadata
synthetic final class<Ljava/lang/Object;LSam<TT;>;> TKt$genericSam$1 { synthetic final class<null> TKt$genericSam$1 {
// source: 't.kt' // source: 't.kt'
public final <()TT;> method get(): java.lang.Object public final <()TT;> method get(): java.lang.Object
static <null> method <clinit>(): void static <null> method <clinit>(): void
@@ -5,7 +5,7 @@ public interface<<T:Ljava/lang/Object;>Ljava/lang/Object;> Sam {
} }
@kotlin.Metadata @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' // source: 't.kt'
public final @org.jetbrains.annotations.NotNull <()Lkotlin/Function<*>;> method getFunctionDelegate(): kotlin.Function public final @org.jetbrains.annotations.NotNull <()Lkotlin/Function<*>;> method getFunctionDelegate(): kotlin.Function
static <null> method <clinit>(): void static <null> method <clinit>(): void
@@ -1,5 +1,5 @@
@kotlin.Metadata @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' // source: 't.kt'
static <null> method <clinit>(): void static <null> method <clinit>(): void
<null> method <init>(): void <null> method <init>(): void
+2 -2
View File
@@ -1,5 +1,5 @@
@kotlin.Metadata @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' // source: 't.kt'
static <null> method <clinit>(): void static <null> method <clinit>(): void
<null> method <init>(): 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 @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' // source: 't.kt'
static <null> method <clinit>(): void static <null> method <clinit>(): void
<null> method <init>(): void <null> method <init>(): void
@@ -1,5 +1,5 @@
@kotlin.Metadata @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' // source: 't.kt'
static <null> method <clinit>(): void static <null> method <clinit>(): void
<null> method <init>(): 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 @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' // source: 't.kt'
static <null> method <clinit>(): void static <null> method <clinit>(): void
<null> method <init>(): void <null> method <init>(): void
@@ -5,7 +5,7 @@ public interface<<T:Ljava/lang/Object;>Ljava/lang/Object;> Sam {
} }
@kotlin.Metadata @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' // source: 't.kt'
public final <()TT;> method get(): java.lang.Object public final <()TT;> method get(): java.lang.Object
<null> method <init>(p0: kotlin.jvm.functions.Function0): void <null> method <init>(p0: kotlin.jvm.functions.Function0): void
@@ -5,7 +5,7 @@ public interface<<T:Ljava/lang/Object;>Ljava/lang/Object;> Sam {
} }
@kotlin.Metadata @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' // source: 't.kt'
public final <()TT;> method get(): java.lang.Object public final <()TT;> method get(): java.lang.Object
<(Lkotlin/jvm/functions/Function0<+TT;>;)V> method <init>(p0: kotlin.jvm.functions.Function0): void <(Lkotlin/jvm/functions/Function0<+TT;>;)V> method <init>(p0: kotlin.jvm.functions.Function0): void
@@ -1,5 +1,5 @@
@kotlin.Metadata @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' // source: 't.kt'
public final <()TT;> method get(): java.lang.Object public final <()TT;> method get(): java.lang.Object
<null> method <init>(p0: kotlin.jvm.functions.Function0): void <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 @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' // source: 't.kt'
public final <()TT;> method get(): java.lang.Object public final <()TT;> method get(): java.lang.Object
<null> method <init>(p0: kotlin.jvm.functions.Function0): void <null> method <init>(p0: kotlin.jvm.functions.Function0): void
@@ -1,5 +1,5 @@
@kotlin.Metadata @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' // source: 't.kt'
public final <()TT;> method get(): java.lang.Object public final <()TT;> method get(): java.lang.Object
<(Lkotlin/jvm/functions/Function0<+TT;>;)V> method <init>(p0: kotlin.jvm.functions.Function0): void <(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 @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' // source: 't.kt'
public final <()TT;> method get(): java.lang.Object public final <()TT;> method get(): java.lang.Object
<(Lkotlin/jvm/functions/Function0<+TT;>;)V> method <init>(p0: kotlin.jvm.functions.Function0): void <(Lkotlin/jvm/functions/Function0<+TT;>;)V> method <init>(p0: kotlin.jvm.functions.Function0): void
@@ -5,7 +5,7 @@ public interface<<T:Ljava/lang/Object;>Ljava/lang/Object;> Sam {
} }
@kotlin.Metadata @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' // source: 't.kt'
<null> method <init>(p0: kotlin.jvm.functions.Function0): void <null> method <init>(p0: kotlin.jvm.functions.Function0): void
public synthetic bridge <null> method get(): java.lang.Object public synthetic bridge <null> method get(): java.lang.Object
@@ -5,7 +5,7 @@ public interface<<T:Ljava/lang/Object;>Ljava/lang/Object;> Sam {
} }
@kotlin.Metadata @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' // source: 't.kt'
<(Lkotlin/jvm/functions/Function0<Ljava/lang/String;>;)V> method <init>(p0: kotlin.jvm.functions.Function0): void <(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 public synthetic bridge <null> method get(): java.lang.Object
@@ -1,5 +1,5 @@
@kotlin.Metadata @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' // source: 't.kt'
<null> method <init>(p0: kotlin.jvm.functions.Function0): void <null> method <init>(p0: kotlin.jvm.functions.Function0): void
public synthetic bridge <null> method get(): java.lang.Object public synthetic bridge <null> method get(): java.lang.Object
@@ -1,5 +1,5 @@
@kotlin.Metadata @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' // source: 't.kt'
<(Lkotlin/jvm/functions/Function0<Ljava/lang/String;>;)V> method <init>(p0: kotlin.jvm.functions.Function0): void <(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 public synthetic bridge <null> method get(): java.lang.Object
@@ -38060,6 +38060,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/sam/samConversionToJavaWildcard.kt"); runTest("compiler/testData/codegen/box/sam/samConversionToJavaWildcard.kt");
} }
@Test
@TestMetadata("samInterfaceTypeParameterErasure.kt")
public void testSamInterfaceTypeParameterErasure() throws Exception {
runTest("compiler/testData/codegen/box/sam/samInterfaceTypeParameterErasure.kt");
}
@Test @Test
@TestMetadata("smartCastSamConversion.kt") @TestMetadata("smartCastSamConversion.kt")
public void testSmartCastSamConversion() throws Exception { public void testSmartCastSamConversion() throws Exception {
@@ -38084,6 +38084,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/sam/samConversionToJavaWildcard.kt"); runTest("compiler/testData/codegen/box/sam/samConversionToJavaWildcard.kt");
} }
@Test
@TestMetadata("samInterfaceTypeParameterErasure.kt")
public void testSamInterfaceTypeParameterErasure() throws Exception {
runTest("compiler/testData/codegen/box/sam/samInterfaceTypeParameterErasure.kt");
}
@Test @Test
@TestMetadata("smartCastSamConversion.kt") @TestMetadata("smartCastSamConversion.kt")
public void testSmartCastSamConversion() throws Exception { public void testSmartCastSamConversion() throws Exception {
@@ -30372,6 +30372,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/sam/samConversionToJavaWildcard.kt"); runTest("compiler/testData/codegen/box/sam/samConversionToJavaWildcard.kt");
} }
@TestMetadata("samInterfaceTypeParameterErasure.kt")
public void testSamInterfaceTypeParameterErasure() throws Exception {
runTest("compiler/testData/codegen/box/sam/samInterfaceTypeParameterErasure.kt");
}
@TestMetadata("smartCastSamConversion.kt") @TestMetadata("smartCastSamConversion.kt")
public void testSmartCastSamConversion() throws Exception { public void testSmartCastSamConversion() throws Exception {
runTest("compiler/testData/codegen/box/sam/smartCastSamConversion.kt"); runTest("compiler/testData/codegen/box/sam/smartCastSamConversion.kt");