JVM_IR indy-SAM conversions: more cases
KT-44278 KT-26060 KT-42621
This commit is contained in:
+36
@@ -18403,6 +18403,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/boundReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("builtinMemberReference.kt")
|
||||
public void testBuiltinMemberReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/builtinMemberReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("capturedDispatchReceiver.kt")
|
||||
public void testCapturedDispatchReceiver() throws Exception {
|
||||
@@ -18427,12 +18433,42 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/capturingIndySam.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("capturingVar.kt")
|
||||
public void testCapturingVar() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/capturingVar.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("constructorReference.kt")
|
||||
public void testConstructorReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/constructorReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericFunInterface.kt")
|
||||
public void testGenericFunInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/genericFunInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericFunInterfaceWithPrimitive.kt")
|
||||
public void testGenericFunInterfaceWithPrimitive() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/genericFunInterfaceWithPrimitive.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("primitiveVsWrapperInSam.kt")
|
||||
public void testPrimitiveVsWrapperInSam() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/primitiveVsWrapperInSam.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("samConversionOnFunctionReference.kt")
|
||||
public void testSamConversionOnFunctionReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/samConversionOnFunctionReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("simpleIndyFunInterface.kt")
|
||||
public void testSimpleIndyFunInterface() throws Exception {
|
||||
|
||||
@@ -604,11 +604,25 @@ class JvmSymbols(
|
||||
}.symbol
|
||||
|
||||
// Intrinsic used to represent MethodType objects in bootstrap method arguments (see jvmInvokeDynamicIntrinsic above).
|
||||
// Type argument is a possibly substituted method owner type (e.g., 'java.lang.function.Supplier<String>').
|
||||
// Value argument is a raw function reference to a corresponding method (e.g., 'java.lang.function.Supplier#get').
|
||||
val jvmMethodTypeIntrinsic: IrSimpleFunctionSymbol =
|
||||
// Resulting method type is unsubstituted.
|
||||
val jvmOriginalMethodTypeIntrinsic: IrSimpleFunctionSymbol =
|
||||
irFactory.buildFun {
|
||||
name = Name.special("<jvm-method-type>")
|
||||
name = Name.special("<jvm-original-method-type>")
|
||||
origin = IrDeclarationOrigin.IR_BUILTINS_STUB
|
||||
}.apply {
|
||||
parent = kotlinJvmInternalPackage
|
||||
addValueParameter("method", irBuiltIns.anyType)
|
||||
returnType = irBuiltIns.anyType
|
||||
}.symbol
|
||||
|
||||
// Intrinsic used to represent MethodType objects in bootstrap method arguments (see jvmInvokeDynamicIntrinsic above).
|
||||
// Type argument is a substituted method owner type (e.g., 'java.lang.function.Supplier<String>').
|
||||
// Value argument is a raw function reference to a corresponding method (e.g., 'java.lang.function.Supplier#get').
|
||||
// Resulting method type is substituted.
|
||||
val jvmSubstitutedMethodTypeIntrinsic: IrSimpleFunctionSymbol =
|
||||
irFactory.buildFun {
|
||||
name = Name.special("<jvm-substituted-method-type>")
|
||||
origin = IrDeclarationOrigin.IR_BUILTINS_STUB
|
||||
}.apply {
|
||||
parent = kotlinJvmInternalPackage
|
||||
|
||||
+59
-9
@@ -8,10 +8,17 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.inline.v
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.overrides.buildFakeOverrideMember
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.org.objectweb.asm.Handle
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
@@ -71,8 +78,10 @@ object JvmInvokeDynamic : IntrinsicMethod() {
|
||||
generateMethodHandle(element, codegen)
|
||||
is IrCall ->
|
||||
when (element.symbol) {
|
||||
codegen.context.ir.symbols.jvmMethodTypeIntrinsic ->
|
||||
generateMethodType(element, codegen)
|
||||
codegen.context.ir.symbols.jvmOriginalMethodTypeIntrinsic ->
|
||||
generateOriginalMethodType(element, codegen)
|
||||
codegen.context.ir.symbols.jvmSubstitutedMethodTypeIntrinsic ->
|
||||
generateSubstitutedMethodType(element, codegen)
|
||||
else ->
|
||||
throw AssertionError("Unexpected callee in bootstrap method argument:\n${element.dump()}")
|
||||
}
|
||||
@@ -92,12 +101,14 @@ object JvmInvokeDynamic : IntrinsicMethod() {
|
||||
throw AssertionError("Unexpected bootstrap method argument:\n${element.dump()}")
|
||||
}
|
||||
|
||||
private fun generateMethodHandle(irRawFunctionReference: IrRawFunctionReference, codegen: ExpressionCodegen): Any {
|
||||
private fun generateMethodHandle(irRawFunctionReference: IrRawFunctionReference, codegen: ExpressionCodegen): Handle {
|
||||
val irFun = irRawFunctionReference.symbol.owner
|
||||
val irParentClass = irFun.parentAsClass
|
||||
val owner = codegen.typeMapper.mapOwner(irParentClass)
|
||||
val asmMethod = codegen.methodSignatureMapper.mapAsmMethod(irFun)
|
||||
val handleTag = when {
|
||||
irFun is IrConstructor ->
|
||||
Opcodes.H_NEWINVOKESPECIAL
|
||||
irFun.dispatchReceiverParameter == null ->
|
||||
Opcodes.H_INVOKESTATIC
|
||||
else ->
|
||||
@@ -106,18 +117,57 @@ object JvmInvokeDynamic : IntrinsicMethod() {
|
||||
return Handle(handleTag, owner.internalName, asmMethod.name, asmMethod.descriptor, irParentClass.isJvmInterface)
|
||||
}
|
||||
|
||||
private fun generateMethodType(jvmMethodTypeCall: IrCall, codegen: ExpressionCodegen): Any {
|
||||
val irRawFunctionReference = jvmMethodTypeCall.getValueArgument(0) as? IrRawFunctionReference
|
||||
private fun generateOriginalMethodType(irCall: IrCall, codegen: ExpressionCodegen): Type {
|
||||
val irRawFunRef = irCall.getValueArgument(0) as? IrRawFunctionReference
|
||||
?: throw AssertionError(
|
||||
"Argument in ${jvmMethodTypeCall.symbol.owner.name} call is expected to be a raw function reference:\n" +
|
||||
jvmMethodTypeCall.dump()
|
||||
"Argument in ${irCall.symbol.owner.name} call is expected to be a raw function reference:\n" +
|
||||
irCall.dump()
|
||||
)
|
||||
val irFun = irRawFunctionReference.symbol.owner
|
||||
// TODO substitute signature
|
||||
val irFun = irRawFunRef.symbol.owner
|
||||
val asmMethod = codegen.methodSignatureMapper.mapAsmMethod(irFun)
|
||||
return Type.getMethodType(asmMethod.descriptor)
|
||||
}
|
||||
|
||||
private fun generateSubstitutedMethodType(irCall: IrCall, codegen: ExpressionCodegen): Type {
|
||||
fun fail(message: String): Nothing =
|
||||
throw AssertionError("$message; irCall:\n${irCall.dump()}")
|
||||
|
||||
val irRawFunRef = irCall.getValueArgument(0) as? IrRawFunctionReference
|
||||
?: fail("Argument in ${irCall.symbol.owner.name} call is expected to be a raw function reference")
|
||||
val irOriginalFun = irRawFunRef.symbol.owner as? IrSimpleFunction
|
||||
?: fail("IrSimpleFunction expected: ${irRawFunRef.symbol.owner.render()}")
|
||||
val substitutedType = irCall.getTypeArgument(0) as? IrSimpleType
|
||||
?: fail("Type argument expected")
|
||||
|
||||
// Force boxing on primitive types, otherwise D8 fails to accept resulting MethodType in presence of primitive types in arguments
|
||||
// (LambdaMetafactory is ok with such types, though).
|
||||
val substitutedTypeWithNullableArgs =
|
||||
substitutedType.classifier.typeWithArguments(
|
||||
substitutedType.arguments.map {
|
||||
when (it) {
|
||||
is IrStarProjection -> it
|
||||
is IrTypeProjection -> {
|
||||
val type = it.type
|
||||
if (type !is IrSimpleType || type.hasQuestionMark)
|
||||
it
|
||||
else
|
||||
makeTypeProjection(type.withHasQuestionMark(true), it.variance)
|
||||
}
|
||||
else ->
|
||||
fail("Unexpected type argument '${it}' :: ${it::class.simpleName}")
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
val fakeClass = codegen.context.irFactory.buildClass { name = Name.special("<fake>") }
|
||||
fakeClass.parent = codegen.context.ir.symbols.kotlinJvmInternalInvokeDynamicPackage
|
||||
val irFakeOverride = buildFakeOverrideMember(substitutedTypeWithNullableArgs, irOriginalFun, fakeClass) as IrSimpleFunction
|
||||
irFakeOverride.overriddenSymbols = listOf(irOriginalFun.symbol)
|
||||
|
||||
val asmMethod = codegen.methodSignatureMapper.mapAsmMethod(irFakeOverride)
|
||||
return Type.getMethodType(asmMethod.descriptor)
|
||||
}
|
||||
|
||||
private fun IrExpression.getIntConst() =
|
||||
if (this is IrConst<*> && kind == IrConstKind.Int)
|
||||
this.value as Int
|
||||
|
||||
+12
-1
@@ -103,13 +103,24 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
}
|
||||
reference.transformChildrenVoid()
|
||||
|
||||
return if (shouldUseIndySamConversions) {
|
||||
return if (shouldUseIndySamConversions && canUseIndySamConversion(reference)) {
|
||||
wrapSamConversionArgumentWithIndySamConversion(expression)
|
||||
} else {
|
||||
FunctionReferenceBuilder(reference, expression.typeOperand).build()
|
||||
}
|
||||
}
|
||||
|
||||
private fun canUseIndySamConversion(reference: IrFunctionReference): Boolean {
|
||||
// Can't use indy for regular function references by default (because of 'equals').
|
||||
// TODO special mode that would generate indy everywhere?
|
||||
if (reference.origin != IrStatementOrigin.LAMBDA)
|
||||
return false
|
||||
// TODO wrap intrinsic function in lambda?
|
||||
if (context.irIntrinsics.getIntrinsic(reference.symbol) != null)
|
||||
return false
|
||||
return true
|
||||
}
|
||||
|
||||
private fun wrapSamConversionArgumentWithIndySamConversion(expression: IrTypeOperatorCall): IrExpression {
|
||||
return when (val argument = expression.argument) {
|
||||
is IrFunctionReference ->
|
||||
|
||||
+12
-7
@@ -121,10 +121,16 @@ private class TypeOperatorLowering(private val context: JvmBackendContext) : Fil
|
||||
putValueArgument(5, irVararg(context.irBuiltIns.anyType, bootstrapMethodArguments))
|
||||
}
|
||||
|
||||
private val methodTypeIntrinsic = context.ir.symbols.jvmMethodTypeIntrinsic
|
||||
private val originalMethodTypeIntrinsic = context.ir.symbols.jvmOriginalMethodTypeIntrinsic
|
||||
private val substitutedMethodTypeIntrinsic = context.ir.symbols.jvmSubstitutedMethodTypeIntrinsic
|
||||
|
||||
private fun IrBuilderWithScope.jvmMethodType(ownerType: IrType, methodSymbol: IrFunctionSymbol) =
|
||||
irCall(methodTypeIntrinsic, context.irBuiltIns.anyType).apply {
|
||||
private fun IrBuilderWithScope.jvmOriginalMethodType(methodSymbol: IrFunctionSymbol) =
|
||||
irCall(originalMethodTypeIntrinsic, context.irBuiltIns.anyType).apply {
|
||||
putValueArgument(0, irRawFunctionReferefence(context.irBuiltIns.anyType, methodSymbol))
|
||||
}
|
||||
|
||||
private fun IrBuilderWithScope.jvmSubstitutedMethodType(ownerType: IrType, methodSymbol: IrFunctionSymbol) =
|
||||
irCall(substitutedMethodTypeIntrinsic, context.irBuiltIns.anyType).apply {
|
||||
putTypeArgument(0, ownerType)
|
||||
putValueArgument(0, irRawFunctionReferefence(context.irBuiltIns.anyType, methodSymbol))
|
||||
}
|
||||
@@ -181,16 +187,15 @@ private class TypeOperatorLowering(private val context: JvmBackendContext) : Fil
|
||||
?: fail("'method' is expected to be 'IrFunctionReference'")
|
||||
val funSymbol = irFunRef.symbol
|
||||
|
||||
val erasedSamType = samClassSymbol.defaultType as IrSimpleType
|
||||
val dynamicCall = wrapClosureInDynamicCall(erasedSamType, samMethod, irFunRef)
|
||||
val dynamicCall = wrapClosureInDynamicCall(samType, samMethod, irFunRef)
|
||||
|
||||
return context.createJvmIrBuilder(
|
||||
funSymbol, // TODO actual symbol for outer scope
|
||||
startOffset, endOffset
|
||||
).run {
|
||||
val samMethodType = jvmMethodType(erasedSamType, samMethod.symbol)
|
||||
val samMethodType = jvmOriginalMethodType(samMethod.symbol)
|
||||
val irRawFunRef = irRawFunctionReferefence(irFunRef.type, funSymbol)
|
||||
val instanceMethodType = jvmMethodType(samType, samMethod.symbol)
|
||||
val instanceMethodType = jvmSubstitutedMethodType(samType, samMethod.symbol)
|
||||
|
||||
jvmInvokeDynamic(
|
||||
dynamicCall,
|
||||
|
||||
+2
-1
@@ -38,7 +38,8 @@ abstract class IrGetEnumValue : IrGetSingletonValue() {
|
||||
/**
|
||||
* Platform-specific low-level reference to function.
|
||||
*
|
||||
* On JS platform represent a plain reference to JavaScript function.
|
||||
* On JS platform it represents a plain reference to JavaScript function.
|
||||
* On JVM platform it represents a MethodHandle constant.
|
||||
*/
|
||||
abstract class IrRawFunctionReference : IrDeclarationReference() {
|
||||
abstract override val symbol: IrFunctionSymbol
|
||||
|
||||
@@ -23,33 +23,8 @@ import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
abstract class FakeOverrideBuilderStrategy {
|
||||
open fun fakeOverrideMember(superType: IrType, member: IrOverridableMember, clazz: IrClass): IrOverridableMember{
|
||||
require(superType is IrSimpleType) { "superType is $superType, expected IrSimpleType" }
|
||||
val classifier = superType.classifier
|
||||
require(classifier is IrClassSymbol) { "superType classifier is not IrClassSymbol: $classifier" }
|
||||
|
||||
val typeParameters = extractTypeParameters(classifier.owner)
|
||||
val superArguments = superType.arguments
|
||||
assert(typeParameters.size == superArguments.size) {
|
||||
"typeParameters = $typeParameters size != typeArguments = $superArguments size "
|
||||
}
|
||||
|
||||
val substitutionMap = mutableMapOf<IrTypeParameterSymbol, IrType>()
|
||||
|
||||
for (i in typeParameters.indices) {
|
||||
val tp = typeParameters[i]
|
||||
val ta = superArguments[i]
|
||||
require(ta is IrTypeProjection) { "Unexpected super type argument: $ta @ $i" }
|
||||
assert(ta.variance == Variance.INVARIANT) { "Unexpected variance in super type argument: ${ta.variance} @$i" }
|
||||
substitutionMap[tp.symbol] = ta.type
|
||||
}
|
||||
|
||||
val copier = DeepCopyIrTreeWithSymbolsForFakeOverrides(substitutionMap)
|
||||
val deepCopyFakeOverride = copier.copy(member, clazz) as IrOverridableMember
|
||||
deepCopyFakeOverride.parent = clazz
|
||||
|
||||
return deepCopyFakeOverride
|
||||
}
|
||||
open fun fakeOverrideMember(superType: IrType, member: IrOverridableMember, clazz: IrClass): IrOverridableMember =
|
||||
buildFakeOverrideMember(superType, member, clazz)
|
||||
|
||||
fun linkFakeOverride(fakeOverride: IrOverridableMember) {
|
||||
when (fakeOverride) {
|
||||
@@ -66,6 +41,35 @@ abstract class FakeOverrideBuilderStrategy {
|
||||
val propertyOverriddenSymbols: MutableMap<IrOverridableMember, List<IrSymbol>> = mutableMapOf()
|
||||
}
|
||||
|
||||
fun buildFakeOverrideMember(superType: IrType, member: IrOverridableMember, clazz: IrClass): IrOverridableMember {
|
||||
require(superType is IrSimpleType) { "superType is $superType, expected IrSimpleType" }
|
||||
val classifier = superType.classifier
|
||||
require(classifier is IrClassSymbol) { "superType classifier is not IrClassSymbol: $classifier" }
|
||||
|
||||
val typeParameters = extractTypeParameters(classifier.owner)
|
||||
val superArguments = superType.arguments
|
||||
assert(typeParameters.size == superArguments.size) {
|
||||
"typeParameters = $typeParameters size != typeArguments = $superArguments size "
|
||||
}
|
||||
|
||||
val substitutionMap = mutableMapOf<IrTypeParameterSymbol, IrType>()
|
||||
|
||||
for (i in typeParameters.indices) {
|
||||
val tp = typeParameters[i]
|
||||
val ta = superArguments[i]
|
||||
require(ta is IrTypeProjection) { "Unexpected super type argument: $ta @ $i" }
|
||||
assert(ta.variance == Variance.INVARIANT) { "Unexpected variance in super type argument: ${ta.variance} @$i" }
|
||||
substitutionMap[tp.symbol] = ta.type
|
||||
}
|
||||
|
||||
val copier = DeepCopyIrTreeWithSymbolsForFakeOverrides(substitutionMap)
|
||||
val deepCopyFakeOverride = copier.copy(member, clazz) as IrOverridableMember
|
||||
deepCopyFakeOverride.parent = clazz
|
||||
|
||||
return deepCopyFakeOverride
|
||||
}
|
||||
|
||||
|
||||
// TODO:
|
||||
// The below pile of code is basically half of OverridingUtil.java
|
||||
// adapted to IR and converted to Kotlin.
|
||||
@@ -294,7 +298,7 @@ class IrOverridingUtil(
|
||||
}
|
||||
|
||||
val realOverrides = members
|
||||
.map{ originals[it]!! }
|
||||
.map { originals[it]!! }
|
||||
.collectAndFilterRealOverrides()
|
||||
return getMinimalModality(realOverrides, transformAbstractToClassModality, current.modality)
|
||||
}
|
||||
@@ -349,7 +353,10 @@ class IrOverridingUtil(
|
||||
return result
|
||||
}
|
||||
|
||||
private fun IrSimpleFunction.updateAccessorModalityAndVisibility(newModality: Modality, newVisibility: DescriptorVisibility): IrSimpleFunction? {
|
||||
private fun IrSimpleFunction.updateAccessorModalityAndVisibility(
|
||||
newModality: Modality,
|
||||
newVisibility: DescriptorVisibility
|
||||
): IrSimpleFunction? {
|
||||
require(this is IrFakeOverrideFunction) {
|
||||
"Unexpected fake override accessor kind: $this"
|
||||
}
|
||||
@@ -746,15 +753,15 @@ class IrOverridingUtil(
|
||||
|
||||
fun IrSimpleFunction.isOverridableFunction(): Boolean =
|
||||
this.visibility != DescriptorVisibilities.PRIVATE &&
|
||||
this.dispatchReceiverParameter != null
|
||||
this.dispatchReceiverParameter != null
|
||||
|
||||
fun IrProperty.isOverridableProperty(): Boolean =
|
||||
this.visibility != DescriptorVisibilities.PRIVATE &&
|
||||
(this.getter?.dispatchReceiverParameter != null ||
|
||||
this.setter?.dispatchReceiverParameter != null)
|
||||
(this.getter?.dispatchReceiverParameter != null ||
|
||||
this.setter?.dispatchReceiverParameter != null)
|
||||
|
||||
fun IrDeclaration.isOverridableMemberOrAccessor(): Boolean = when(this) {
|
||||
fun IrDeclaration.isOverridableMemberOrAccessor(): Boolean = when (this) {
|
||||
is IrSimpleFunction -> isOverridableFunction()
|
||||
is IrProperty -> isOverridableProperty()
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// SAM_CONVERSIONS: INDY
|
||||
|
||||
fun interface IntFun {
|
||||
fun invoke(i: Int): Int
|
||||
}
|
||||
|
||||
fun invoke1(intFun: IntFun) = intFun.invoke(1)
|
||||
|
||||
fun box(): String {
|
||||
val test = invoke1(41::plus)
|
||||
if (test != 42) return "Failed: $test"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// SAM_CONVERSIONS: INDY
|
||||
|
||||
fun interface KRunnable {
|
||||
fun run()
|
||||
}
|
||||
|
||||
fun runIt(r: KRunnable) {
|
||||
r.run()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var test = "Failed"
|
||||
runIt { test = "OK" }
|
||||
return test
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// SAM_CONVERSIONS: INDY
|
||||
|
||||
class C(val test: String)
|
||||
|
||||
fun interface MakeC {
|
||||
fun make(x: String): C
|
||||
}
|
||||
|
||||
fun make(makeC: MakeC) = makeC.make("OK")
|
||||
|
||||
fun box() = make(::C).test
|
||||
@@ -0,0 +1,11 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// SAM_CONVERSIONS: INDY
|
||||
|
||||
fun interface IFoo<T> {
|
||||
fun foo(x: T): T
|
||||
}
|
||||
|
||||
fun foo(fs: IFoo<String>) = fs.foo("O")
|
||||
|
||||
fun box() = foo { "${it}K" }
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// SAM_CONVERSIONS: INDY
|
||||
|
||||
fun interface IFoo<T> {
|
||||
fun foo(x: T): T
|
||||
}
|
||||
|
||||
fun foo1(fs: IFoo<Int>) = fs.foo(1)
|
||||
|
||||
fun box(): String {
|
||||
val t = foo1 { it + 41 }
|
||||
if (t != 42) return "Failed: t=$t"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// SAM_CONVERSIONS: INDY
|
||||
|
||||
fun interface KRunnable {
|
||||
fun run()
|
||||
}
|
||||
|
||||
fun runnable(kr: KRunnable) = kr
|
||||
|
||||
fun foo() {}
|
||||
|
||||
fun box(): String {
|
||||
val foo1 = runnable(::foo)
|
||||
val foo2 = runnable(::foo)
|
||||
|
||||
if (foo1 != foo2) {
|
||||
return "Failed: foo1 != foo2"
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+36
@@ -18403,6 +18403,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/boundReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("builtinMemberReference.kt")
|
||||
public void testBuiltinMemberReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/builtinMemberReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("capturedDispatchReceiver.kt")
|
||||
public void testCapturedDispatchReceiver() throws Exception {
|
||||
@@ -18427,12 +18433,42 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/capturingIndySam.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("capturingVar.kt")
|
||||
public void testCapturingVar() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/capturingVar.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("constructorReference.kt")
|
||||
public void testConstructorReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/constructorReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericFunInterface.kt")
|
||||
public void testGenericFunInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/genericFunInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericFunInterfaceWithPrimitive.kt")
|
||||
public void testGenericFunInterfaceWithPrimitive() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/genericFunInterfaceWithPrimitive.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("primitiveVsWrapperInSam.kt")
|
||||
public void testPrimitiveVsWrapperInSam() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/primitiveVsWrapperInSam.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("samConversionOnFunctionReference.kt")
|
||||
public void testSamConversionOnFunctionReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/samConversionOnFunctionReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("simpleIndyFunInterface.kt")
|
||||
public void testSimpleIndyFunInterface() throws Exception {
|
||||
|
||||
+36
@@ -18403,6 +18403,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/boundReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("builtinMemberReference.kt")
|
||||
public void testBuiltinMemberReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/builtinMemberReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("capturedDispatchReceiver.kt")
|
||||
public void testCapturedDispatchReceiver() throws Exception {
|
||||
@@ -18427,12 +18433,42 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/capturingIndySam.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("capturingVar.kt")
|
||||
public void testCapturingVar() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/capturingVar.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("constructorReference.kt")
|
||||
public void testConstructorReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/constructorReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericFunInterface.kt")
|
||||
public void testGenericFunInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/genericFunInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericFunInterfaceWithPrimitive.kt")
|
||||
public void testGenericFunInterfaceWithPrimitive() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/genericFunInterfaceWithPrimitive.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("primitiveVsWrapperInSam.kt")
|
||||
public void testPrimitiveVsWrapperInSam() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/primitiveVsWrapperInSam.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("samConversionOnFunctionReference.kt")
|
||||
public void testSamConversionOnFunctionReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/samConversionOnFunctionReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("simpleIndyFunInterface.kt")
|
||||
public void testSimpleIndyFunInterface() throws Exception {
|
||||
|
||||
+6
-2
@@ -46,7 +46,11 @@ class JvmBoxRunner(testServices: TestServices) : JvmBinaryArtifactHandler(testSe
|
||||
try {
|
||||
for (ktFile in ktFiles) {
|
||||
val className = ktFile.getFacadeFqName() ?: continue
|
||||
val clazz = classLoader.getGeneratedClass(className)
|
||||
val clazz = try {
|
||||
classLoader.getGeneratedClass(className)
|
||||
} catch (e: LinkageError) {
|
||||
throw AssertionError("Failed to load class '$className':\n${info.classFileFactory.createText()}", e)
|
||||
}
|
||||
val method = clazz.getBoxMethodOrNull() ?: continue
|
||||
boxMethodFound = true
|
||||
callBoxMethodAndCheckResultWithCleanup(
|
||||
@@ -128,7 +132,7 @@ class JvmBoxRunner(testServices: TestServices) : JvmBinaryArtifactHandler(testSe
|
||||
): GeneratedClassLoader {
|
||||
val classLoader = createClassLoader(module, classFileFactory)
|
||||
val verificationSucceeded = CodegenTestUtil.verifyAllFilesWithAsm(classFileFactory, classLoader, reportProblems)
|
||||
if (!verificationSucceeded ) {
|
||||
if (!verificationSucceeded) {
|
||||
assertions.fail { "Verification failed: see exceptions above" }
|
||||
}
|
||||
return classLoader
|
||||
|
||||
+30
@@ -16138,6 +16138,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/boundReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("builtinMemberReference.kt")
|
||||
public void testBuiltinMemberReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/builtinMemberReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("capturedDispatchReceiver.kt")
|
||||
public void testCapturedDispatchReceiver() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/capturedDispatchReceiver.kt");
|
||||
@@ -16158,11 +16163,36 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/capturingIndySam.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("capturingVar.kt")
|
||||
public void testCapturingVar() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/capturingVar.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("constructorReference.kt")
|
||||
public void testConstructorReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/constructorReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("genericFunInterface.kt")
|
||||
public void testGenericFunInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/genericFunInterface.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("genericFunInterfaceWithPrimitive.kt")
|
||||
public void testGenericFunInterfaceWithPrimitive() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/genericFunInterfaceWithPrimitive.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("primitiveVsWrapperInSam.kt")
|
||||
public void testPrimitiveVsWrapperInSam() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/primitiveVsWrapperInSam.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("samConversionOnFunctionReference.kt")
|
||||
public void testSamConversionOnFunctionReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/samConversionOnFunctionReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simpleIndyFunInterface.kt")
|
||||
public void testSimpleIndyFunInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/simpleIndyFunInterface.kt");
|
||||
|
||||
Reference in New Issue
Block a user