JVM_IR wrap function into a proxy if indy SAM-conversion becomes valid
This commit is contained in:
committed by
teamcityserver
parent
9ad62eb1fd
commit
40fe67880b
+36
@@ -22233,6 +22233,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/genericLambdaSignature.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineFunWithPrivateMethod.kt")
|
||||
public void testInlineFunWithPrivateMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineFunWithPrivateMethod.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineOnly.kt")
|
||||
public void testInlineOnly() throws Exception {
|
||||
@@ -22281,6 +22287,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/primitiveVsWrapperInSam.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("reifiedTypeParameter.kt")
|
||||
public void testReifiedTypeParameter() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/reifiedTypeParameter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("samConversionInsideSamConvertedLambda.kt")
|
||||
public void testSamConversionInsideSamConvertedLambda() throws Exception {
|
||||
@@ -22480,6 +22492,18 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/enhancedNullability.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericBoundInnerConstructorRef.kt")
|
||||
public void testGenericBoundInnerConstructorRef() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericBoundInnerConstructorRef.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericInnerConstructorRef.kt")
|
||||
public void testGenericInnerConstructorRef() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericInnerConstructorRef.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("innerConstructorRef.kt")
|
||||
public void testInnerConstructorRef() throws Exception {
|
||||
@@ -22534,6 +22558,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multifileClassMemberFromStdlib.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleProxyWrappersForSameFunction.kt")
|
||||
public void testMultipleProxyWrappersForSameFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multipleProxyWrappersForSameFunction.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonTrivialReceiver.kt")
|
||||
public void testNonTrivialReceiver() throws Exception {
|
||||
@@ -22621,6 +22651,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/enumValues.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("intArrayOf.kt")
|
||||
public void testIntArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/intArrayOf.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("intPlus.kt")
|
||||
public void testIntPlus() throws Exception {
|
||||
|
||||
@@ -341,11 +341,13 @@ private val jvmFilePhases = listOf(
|
||||
propertyReferencePhase,
|
||||
arrayConstructorPhase,
|
||||
constPhase1,
|
||||
|
||||
// TODO: merge the next three phases together, as visitors behave incorrectly between them
|
||||
// (backing fields moved out of companion objects are reachable by two paths):
|
||||
moveOrCopyCompanionObjectFieldsPhase,
|
||||
propertiesPhase,
|
||||
remapObjectFieldAccesses,
|
||||
|
||||
anonymousObjectSuperConstructorPhase,
|
||||
jvmStandardLibraryBuiltInsPhase,
|
||||
|
||||
|
||||
+184
-17
@@ -16,10 +16,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredStatementOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmSymbols
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.*
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.indy.LambdaMetafactoryArguments
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.indy.LambdaMetafactoryArgumentsBuilder
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.indy.SamDelegatingLambdaBlock
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.indy.SamDelegatingLambdaBuilder
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.indy.*
|
||||
import org.jetbrains.kotlin.config.JvmClosureGenerationScheme
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
@@ -28,9 +25,11 @@ import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
@@ -88,10 +87,11 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
if (shouldGenerateIndyLambdas) {
|
||||
val lambdaMetafactoryArguments =
|
||||
LambdaMetafactoryArgumentsBuilder(context, crossinlineLambdas)
|
||||
.getLambdaMetafactoryArgumentsOrNull(reference, reference.type, true)
|
||||
if (lambdaMetafactoryArguments != null) {
|
||||
.getLambdaMetafactoryArguments(reference, reference.type, true)
|
||||
if (lambdaMetafactoryArguments is LambdaMetafactoryArguments) {
|
||||
return wrapLambdaReferenceWithIndySamConversion(expression, reference, lambdaMetafactoryArguments)
|
||||
}
|
||||
// TODO MetafactoryArgumentsResult.Failure.FunctionHazard?
|
||||
}
|
||||
|
||||
return FunctionReferenceBuilder(reference).build()
|
||||
@@ -254,8 +254,13 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
val lambdaBlock = SamDelegatingLambdaBuilder(context)
|
||||
.build(invokable, samSuperType, currentScope!!.scope.scopeOwnerSymbol, getDeclarationParentForDelegatingLambda())
|
||||
val lambdaMetafactoryArguments = LambdaMetafactoryArgumentsBuilder(context, crossinlineLambdas)
|
||||
.getLambdaMetafactoryArgumentsOrNull(lambdaBlock.ref, samSuperType, false)
|
||||
?: return super.visitTypeOperator(expression)
|
||||
.getLambdaMetafactoryArguments(lambdaBlock.ref, samSuperType, false)
|
||||
|
||||
if (lambdaMetafactoryArguments !is LambdaMetafactoryArguments) {
|
||||
// TODO MetafactoryArgumentsResult.Failure.FunctionHazard?
|
||||
return super.visitTypeOperator(expression)
|
||||
}
|
||||
|
||||
invokable.transformChildrenVoid()
|
||||
return wrapSamDelegatingLambdaWithIndySamConversion(samSuperType, lambdaBlock, lambdaMetafactoryArguments)
|
||||
} else {
|
||||
@@ -267,9 +272,25 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
if (shouldGenerateIndySamConversions) {
|
||||
val lambdaMetafactoryArguments =
|
||||
LambdaMetafactoryArgumentsBuilder(context, crossinlineLambdas)
|
||||
.getLambdaMetafactoryArgumentsOrNull(reference, samSuperType, false)
|
||||
if (lambdaMetafactoryArguments != null) {
|
||||
return wrapSamConversionArgumentWithIndySamConversion(expression, lambdaMetafactoryArguments)
|
||||
.getLambdaMetafactoryArguments(reference, samSuperType, false)
|
||||
if (lambdaMetafactoryArguments is LambdaMetafactoryArguments) {
|
||||
return wrapSamConversionArgumentWithIndySamConversion(expression) { samType ->
|
||||
wrapWithIndySamConversion(samType, lambdaMetafactoryArguments)
|
||||
}
|
||||
} else if (lambdaMetafactoryArguments is MetafactoryArgumentsResult.Failure.FunctionHazard) {
|
||||
// Try wrapping function with a proxy local function and see if that helps.
|
||||
val proxyLocalFunBlock = createProxyLocalFunctionForIndySamConversion(reference)
|
||||
val proxyLocalFunRef = proxyLocalFunBlock.statements[proxyLocalFunBlock.statements.size - 1] as IrFunctionReference
|
||||
val proxyLambdaMetafactoryArguments = LambdaMetafactoryArgumentsBuilder(context, crossinlineLambdas)
|
||||
.getLambdaMetafactoryArguments(proxyLocalFunRef, samSuperType, false)
|
||||
if (proxyLambdaMetafactoryArguments is LambdaMetafactoryArguments) {
|
||||
return wrapSamConversionArgumentWithIndySamConversion(expression) { samType ->
|
||||
proxyLocalFunBlock.statements[proxyLocalFunBlock.statements.size - 1] =
|
||||
wrapWithIndySamConversion(samType, proxyLambdaMetafactoryArguments)
|
||||
proxyLocalFunBlock.type = samType
|
||||
proxyLocalFunBlock
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,6 +301,152 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
return FunctionReferenceBuilder(reference, erasedSamSuperType).build()
|
||||
}
|
||||
|
||||
private fun createProxyLocalFunctionForIndySamConversion(reference: IrFunctionReference): IrBlock {
|
||||
val startOffset = reference.startOffset
|
||||
val endOffset = reference.endOffset
|
||||
val targetFun = reference.symbol.owner
|
||||
|
||||
// For a function reference with possibly bound value parameters
|
||||
// [ dispatchReceiver = ..., extensionReceiver = ..., ... ]::foo
|
||||
// create a proxy wrapper:
|
||||
// {
|
||||
// val tmp_proxy_0 = <bound_argument_value_0>
|
||||
// ...
|
||||
// val tmp_proxy_N = <bound_argument_value_N>
|
||||
// fun `$proxy`(p_0: TP_0, ..., p_M: TP_M): TR =
|
||||
// foo(... arg_J ...)
|
||||
// // here for each J arg_J is either 'tmp_proxy_K' or 'p_K' for some K
|
||||
// ::`$proxy`
|
||||
// }
|
||||
|
||||
val temporaryVals = ArrayList<IrVariable>()
|
||||
|
||||
val targetCall: IrFunctionAccessExpression =
|
||||
when (targetFun) {
|
||||
is IrSimpleFunction ->
|
||||
IrCallImpl.fromSymbolOwner(startOffset, endOffset, targetFun.symbol)
|
||||
is IrConstructor ->
|
||||
IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, targetFun.returnType, targetFun.symbol)
|
||||
else ->
|
||||
throw AssertionError("Unexpected callable reference target: ${targetFun.render()}")
|
||||
}
|
||||
|
||||
val proxyFun = context.irFactory.buildFun {
|
||||
name = Name.identifier("\$proxy")
|
||||
returnType = targetFun.returnType
|
||||
visibility = DescriptorVisibilities.LOCAL
|
||||
modality = Modality.FINAL
|
||||
isSuspend = false
|
||||
isInline = false
|
||||
origin = JvmLoweredDeclarationOrigin.PROXY_FUN_FOR_INDY_SAM_CONVESION
|
||||
}.also { proxyFun ->
|
||||
proxyFun.parent = currentDeclarationParent
|
||||
?: throw AssertionError("No declaration parent when processing $reference")
|
||||
|
||||
var temporaryValIndex = 0
|
||||
var proxyParameterIndex = 0
|
||||
|
||||
fun addAndGetTemporaryVal(initializer: IrExpression): IrGetValue {
|
||||
val tmpVal = IrVariableImpl(
|
||||
startOffset, endOffset,
|
||||
IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
|
||||
IrVariableSymbolImpl(),
|
||||
Name.identifier("tmp_proxy_${temporaryValIndex++}"),
|
||||
initializer.type,
|
||||
isVar = false, isConst = false, isLateinit = false
|
||||
)
|
||||
tmpVal.initializer = initializer
|
||||
temporaryVals.add(tmpVal)
|
||||
return IrGetValueImpl(startOffset, endOffset, tmpVal.symbol)
|
||||
}
|
||||
|
||||
fun addAndGetProxyValueParameter(originalParameter: IrValueParameter): IrGetValue {
|
||||
val proxyParameter = buildValueParameter(proxyFun) {
|
||||
updateFrom(originalParameter)
|
||||
name = Name.identifier("p$proxyParameterIndex\$${originalParameter.name.asString()}")
|
||||
index = proxyParameterIndex
|
||||
proxyParameterIndex++
|
||||
}.apply {
|
||||
parent = proxyFun
|
||||
}
|
||||
proxyFun.valueParameters += proxyParameter
|
||||
return IrGetValueImpl(startOffset, endOffset, proxyParameter.symbol)
|
||||
}
|
||||
|
||||
fun getTargetCallArgument(boundValue: IrExpression?, originalParameter: IrValueParameter?): IrExpression? =
|
||||
when {
|
||||
boundValue != null ->
|
||||
addAndGetTemporaryVal(boundValue)
|
||||
originalParameter != null ->
|
||||
addAndGetProxyValueParameter(originalParameter)
|
||||
else ->
|
||||
null
|
||||
}
|
||||
|
||||
targetCall.dispatchReceiver = getTargetCallArgument(reference.dispatchReceiver, targetFun.dispatchReceiverParameter)
|
||||
targetCall.extensionReceiver = getTargetCallArgument(reference.extensionReceiver, targetFun.extensionReceiverParameter)
|
||||
for ((valueParameterIndex, valueParameter) in targetFun.valueParameters.withIndex()) {
|
||||
targetCall.putValueArgument(
|
||||
valueParameterIndex,
|
||||
getTargetCallArgument(
|
||||
reference.getValueArgument(valueParameterIndex),
|
||||
valueParameter
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val proxyFunBody = IrBlockBodyImpl(startOffset, endOffset).also { proxyFun.body = it }
|
||||
when {
|
||||
targetFun.isArrayOf() -> {
|
||||
// Lower arrayOf-like function in place.
|
||||
// TODO it seems that VarargLowering does a little bit too much.
|
||||
// Maybe worth decomposing it into varargs part and arrayOf intrinsics part.
|
||||
val varargParameter = proxyFun.valueParameters.singleOrNull { it.isVararg }
|
||||
?: throw AssertionError(
|
||||
"Proxy for *arrayOf should have single vararg parameter:\n" +
|
||||
proxyFun.valueParameters.joinToString(separator = "\n") { it.dump() }
|
||||
)
|
||||
proxyFunBody.statements.add(
|
||||
IrReturnImpl(
|
||||
startOffset, endOffset,
|
||||
context.irBuiltIns.nothingType,
|
||||
proxyFun.symbol,
|
||||
IrGetValueImpl(startOffset, endOffset, varargParameter.symbol, null)
|
||||
)
|
||||
)
|
||||
}
|
||||
targetFun.returnType.isUnit() -> {
|
||||
proxyFunBody.statements.add(targetCall)
|
||||
}
|
||||
else -> {
|
||||
proxyFunBody.statements.add(
|
||||
IrReturnImpl(
|
||||
startOffset, endOffset,
|
||||
context.irBuiltIns.nothingType,
|
||||
proxyFun.symbol,
|
||||
targetCall
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val proxyFunRef = IrFunctionReferenceImpl(
|
||||
startOffset, endOffset,
|
||||
reference.type,
|
||||
proxyFun.symbol,
|
||||
0, // TODO generic function reference?
|
||||
proxyFun.valueParameters.size
|
||||
)
|
||||
|
||||
return IrBlockImpl(
|
||||
startOffset, endOffset,
|
||||
reference.type,
|
||||
origin = null,
|
||||
temporaryVals + proxyFun + proxyFunRef
|
||||
)
|
||||
}
|
||||
|
||||
private fun canGenerateIndySamConversionOnFunctionalExpression(samSuperType: IrType, expression: IrExpression): Boolean {
|
||||
val samClass = samSuperType.classOrNull
|
||||
?: throw AssertionError("Class type expected: ${samSuperType.render()}")
|
||||
@@ -302,24 +469,24 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
|
||||
private fun wrapSamConversionArgumentWithIndySamConversion(
|
||||
expression: IrTypeOperatorCall,
|
||||
lambdaMetafactoryArguments: LambdaMetafactoryArguments
|
||||
produceSamConversion: (IrType) -> IrExpression
|
||||
): IrExpression {
|
||||
val samType = expression.typeOperand
|
||||
return when (val argument = expression.argument) {
|
||||
is IrFunctionReference ->
|
||||
wrapWithIndySamConversion(samType, lambdaMetafactoryArguments)
|
||||
produceSamConversion(samType)
|
||||
is IrBlock ->
|
||||
wrapFunctionReferenceInsideBlockWithIndySamConversion(samType, lambdaMetafactoryArguments, argument)
|
||||
wrapFunctionReferenceInsideBlockWithIndySamConversion(samType, argument, produceSamConversion)
|
||||
else -> throw AssertionError("Block or function reference expected: ${expression.render()}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun wrapFunctionReferenceInsideBlockWithIndySamConversion(
|
||||
samType: IrType,
|
||||
lambdaMetafactoryArguments: LambdaMetafactoryArguments,
|
||||
block: IrBlock
|
||||
block: IrBlock,
|
||||
produceSamConversion: (IrType) -> IrExpression
|
||||
): IrExpression {
|
||||
val indySamConversion = wrapWithIndySamConversion(samType, lambdaMetafactoryArguments)
|
||||
val indySamConversion = produceSamConversion(samType)
|
||||
block.statements[block.statements.size - 1] = indySamConversion
|
||||
block.type = indySamConversion.type
|
||||
return block
|
||||
|
||||
+101
-30
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.ir.allOverridden
|
||||
import org.jetbrains.kotlin.backend.common.lower.VariableRemapper
|
||||
import org.jetbrains.kotlin.backend.common.lower.parents
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.findSuperDeclaration
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.getSingleAbstractMethod
|
||||
@@ -34,12 +35,49 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
|
||||
internal sealed class MetafactoryArgumentsResult {
|
||||
abstract val isSuccess: Boolean
|
||||
|
||||
abstract class Success : MetafactoryArgumentsResult() {
|
||||
override val isSuccess: Boolean
|
||||
get() = true
|
||||
}
|
||||
|
||||
abstract class Failure : MetafactoryArgumentsResult() {
|
||||
override val isSuccess: Boolean
|
||||
get() = false
|
||||
|
||||
// Objects produced by j.l.invoke.LambdaMetafactory have different semantics (e.g., different 'equals' method)
|
||||
// that prevents using them in place of objects of corresponding Kotlin classes.
|
||||
// TODO might use Kotlin-specific metafactory if there would be one.
|
||||
object LambdaMetafactorySemanticsHazard : Failure()
|
||||
|
||||
// There's an ABI incompatibility between classes generated by j.l.invoke.LambdaMetafactory and classes generatede by Kotlin.
|
||||
// TODO might use Kotlin-specific metafactory if there would be one.
|
||||
object LambdaMetafactoryAbiHazard : Failure()
|
||||
|
||||
// An object would be created inside an inline function, which currently doesn't work well with 'invokedynamic'.
|
||||
// TODO make sure indy and Kotlin bytecode inliner work well together
|
||||
object InliningHazard : Failure()
|
||||
|
||||
// Resulting object should be Serializable.
|
||||
// TODO implement serialization support required by j.l.invoke.LambdaMetafactory
|
||||
object SerializationHazard : Failure()
|
||||
|
||||
// There's something special about a function we are referencing.
|
||||
// Wrapping it into a proxy local function might help.
|
||||
object FunctionHazard : Failure()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal class LambdaMetafactoryArguments(
|
||||
val samMethod: IrSimpleFunction,
|
||||
val fakeInstanceMethod: IrSimpleFunction,
|
||||
val implMethodReference: IrFunctionReference,
|
||||
val extraOverriddenMethods: List<IrSimpleFunction>
|
||||
)
|
||||
) : MetafactoryArgumentsResult.Success()
|
||||
|
||||
|
||||
internal class LambdaMetafactoryArgumentsBuilder(
|
||||
private val context: JvmBackendContext,
|
||||
@@ -48,34 +86,44 @@ internal class LambdaMetafactoryArgumentsBuilder(
|
||||
/**
|
||||
* @see java.lang.invoke.LambdaMetafactory
|
||||
*/
|
||||
fun getLambdaMetafactoryArgumentsOrNull(
|
||||
fun getLambdaMetafactoryArguments(
|
||||
reference: IrFunctionReference,
|
||||
samType: IrType,
|
||||
plainLambda: Boolean
|
||||
): LambdaMetafactoryArguments? {
|
||||
): MetafactoryArgumentsResult {
|
||||
val samClass = samType.getClass()
|
||||
?: throw AssertionError("SAM type is not a class: ${samType.render()}")
|
||||
|
||||
var semanticsHazard = false
|
||||
var abiHazard = false
|
||||
var inliningHazard = false
|
||||
var shouldBeSerializable = false
|
||||
var functionHazard = false
|
||||
|
||||
// Can't use JDK LambdaMetafactory for function references by default (because of 'equals').
|
||||
// TODO special mode that would generate indy everywhere?
|
||||
if (!reference.origin.isLambda && !samClass.isFromJava())
|
||||
return null
|
||||
if (!reference.origin.isLambda && !samClass.isFromJava()) {
|
||||
semanticsHazard = true
|
||||
}
|
||||
|
||||
// Don't use JDK LambdaMetafactory for serializable lambdas
|
||||
// TODO implement support for serializable lambdas with LambdaMetafactory (requires additional code for deserialization)
|
||||
if (samClass.isInheritedFromSerializable())
|
||||
return null
|
||||
if (samClass.isInheritedFromSerializable()) {
|
||||
shouldBeSerializable = true
|
||||
}
|
||||
|
||||
val samMethod = samClass.getSingleAbstractMethod()
|
||||
?: throw AssertionError("SAM class has no single abstract method: ${samClass.render()}")
|
||||
|
||||
// Can't use JDK LambdaMetafactory for fun interface with suspend fun.
|
||||
if (samMethod.isSuspend)
|
||||
return null
|
||||
if (samMethod.isSuspend) {
|
||||
abiHazard = true
|
||||
}
|
||||
|
||||
// Can't use JDK LambdaMetafactory for fun interfaces that require delegation to $DefaultImpls.
|
||||
if (samClass.requiresDelegationToDefaultImpls())
|
||||
return null
|
||||
if (samClass.requiresDelegationToDefaultImpls()) {
|
||||
abiHazard = true
|
||||
}
|
||||
|
||||
// TODO in cases where LambdaMetafactory is unusable directly due to problems with the implementation function,
|
||||
// we can still avoid generating an entire class by converting the function reference into a lambda first;
|
||||
@@ -83,32 +131,38 @@ internal class LambdaMetafactoryArgumentsBuilder(
|
||||
|
||||
val implFun = reference.symbol.owner
|
||||
|
||||
if (implFun.typeParameters.any { it.isReified }) {
|
||||
// TODO support reified type parameters in proxy wrappers somehow?
|
||||
abiHazard = true
|
||||
}
|
||||
|
||||
// Don't generate references to intrinsic functions as invokedynamic (no such method exists at run-time).
|
||||
if (context.irIntrinsics.getIntrinsic(implFun.symbol) != null)
|
||||
return null
|
||||
if (context.irIntrinsics.getIntrinsic(implFun.symbol) != null) {
|
||||
functionHazard = true
|
||||
}
|
||||
|
||||
// Can't use invokedynamic if the referenced function has to be inlined for correct semantics
|
||||
// Also in some cases like `private inline fun` we'd need accessors, which `SyntheticAccessorLowering`
|
||||
// won't generate under the assumption that the inline function will be inlined. Plus if the function
|
||||
// is in a different module we should probably copy it anyway (and regenerate all objects in it).
|
||||
if (implFun.isInline)
|
||||
return null
|
||||
if (implFun.isInline) {
|
||||
functionHazard = true
|
||||
}
|
||||
|
||||
if (implFun is IrConstructor && DescriptorVisibilities.isPrivate(implFun.visibility)) {
|
||||
// Kotlin generates constructor accessors differently from Java.
|
||||
// TODO more precise accessibility check (see SyntheticAccessorLowering::isAccessible)
|
||||
return null
|
||||
// We don't do exact accessibility check here, just
|
||||
functionHazard = true
|
||||
}
|
||||
|
||||
// It's possible to reference through a child class a method declared in a package-private base Java class.
|
||||
// In this case the corresponding method might be inaccessible in the context where it's referenced (see KT-48954).
|
||||
// For now, just prohibit referencing methods from package-private Java classes through indy (without precise accessibility check).
|
||||
// TODO wrap into lambda?
|
||||
if (implFun is IrSimpleFunction) {
|
||||
val baseFun = findSuperDeclaration(implFun, false, context.state.jvmDefaultMode)
|
||||
val baseFunClass = baseFun.parent as? IrClass
|
||||
if (baseFunClass != null && baseFunClass.visibility == JavaDescriptorVisibilities.PACKAGE_VISIBILITY) {
|
||||
return null
|
||||
functionHazard = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,40 +171,52 @@ internal class LambdaMetafactoryArgumentsBuilder(
|
||||
// LambdaMetafactory treats multifile class part members as non-accessible,
|
||||
// even if the member is referenced via facade,
|
||||
// because corresponding part class is non-accessible
|
||||
return null
|
||||
functionHazard = true
|
||||
}
|
||||
|
||||
// Can't use JDK LambdaMetafactory for annotated lambdas.
|
||||
// JDK LambdaMetafactory doesn't copy annotations from implementation method to an instance method in a
|
||||
// corresponding synthetic class, which doesn't look like a binary compatible change.
|
||||
// TODO relaxed mode?
|
||||
if (reference.origin.isLambda && implFun.annotations.isNotEmpty())
|
||||
return null
|
||||
if (reference.origin.isLambda && implFun.annotations.isNotEmpty()) {
|
||||
abiHazard = true
|
||||
}
|
||||
|
||||
// Don't use JDK LambdaMetafactory for big arity lambdas.
|
||||
if (plainLambda) {
|
||||
var parametersCount = implFun.valueParameters.size
|
||||
if (implFun.extensionReceiverParameter != null) ++parametersCount
|
||||
if (parametersCount >= BuiltInFunctionArity.BIG_ARITY)
|
||||
return null
|
||||
abiHazard = true
|
||||
}
|
||||
|
||||
// Can't use indy-based SAM conversion inside inline fun (Ok in inline lambda).
|
||||
if (implFun.parents.any { it.isInlineFunction() || it.isCrossinlineLambda() })
|
||||
return null
|
||||
if (implFun.parents.any { it.isInlineFunction() || it.isCrossinlineLambda() }) {
|
||||
inliningHazard = true
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if (samType.arguments.any { it is IrStarProjection || it is IrTypeProjection && it.variance != Variance.INVARIANT })
|
||||
return null
|
||||
if (samType.arguments.any { it is IrStarProjection || it is IrTypeProjection && it.variance != Variance.INVARIANT }) {
|
||||
abiHazard = true
|
||||
}
|
||||
}
|
||||
|
||||
when {
|
||||
semanticsHazard -> return MetafactoryArgumentsResult.Failure.LambdaMetafactorySemanticsHazard
|
||||
abiHazard -> return MetafactoryArgumentsResult.Failure.LambdaMetafactoryAbiHazard
|
||||
inliningHazard -> return MetafactoryArgumentsResult.Failure.InliningHazard
|
||||
shouldBeSerializable -> return MetafactoryArgumentsResult.Failure.SerializationHazard
|
||||
functionHazard -> return MetafactoryArgumentsResult.Failure.FunctionHazard
|
||||
}
|
||||
|
||||
// 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.
|
||||
// If this results in conflicting requirements, we can't use INVOKEDYNAMIC with LambdaMetafactory for creating a closure.
|
||||
return getLambdaMetafactoryArgsOrNullInner(reference, samMethod, samType, implFun)
|
||||
?: MetafactoryArgumentsResult.Failure.FunctionHazard
|
||||
}
|
||||
|
||||
private val javaIoSerializableFqn =
|
||||
@@ -258,7 +324,7 @@ internal class LambdaMetafactoryArgumentsBuilder(
|
||||
return null
|
||||
|
||||
adaptFakeInstanceMethodSignature(fakeInstanceMethod, signatureAdaptationConstraints)
|
||||
if (implFun.origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA) {
|
||||
if (implFun.origin in adaptableFunctionOrigins) {
|
||||
adaptLambdaSignature(implFun as IrSimpleFunction, fakeInstanceMethod, signatureAdaptationConstraints)
|
||||
} else if (
|
||||
!checkMethodSignatureCompliance(implFun, fakeInstanceMethod, signatureAdaptationConstraints, reference)
|
||||
@@ -319,13 +385,18 @@ internal class LambdaMetafactoryArgumentsBuilder(
|
||||
TypeAdaptationConstraint.CONFLICT -> false
|
||||
}
|
||||
|
||||
private val adaptableFunctionOrigins = setOf(
|
||||
IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA,
|
||||
JvmLoweredDeclarationOrigin.PROXY_FUN_FOR_INDY_SAM_CONVESION
|
||||
)
|
||||
|
||||
private fun adaptLambdaSignature(
|
||||
implFun: IrSimpleFunction,
|
||||
fakeInstanceMethod: IrSimpleFunction,
|
||||
constraints: SignatureAdaptationConstraints
|
||||
) {
|
||||
if (implFun.origin != IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA) {
|
||||
throw AssertionError("Can't adapt non-lambda function signature: ${implFun.render()}")
|
||||
if (implFun.origin !in adaptableFunctionOrigins) {
|
||||
throw AssertionError("Function origin should be one of ${adaptableFunctionOrigins}: ${implFun.dump()}")
|
||||
}
|
||||
|
||||
val implParameters = collectValueParameters(implFun)
|
||||
|
||||
+2
-1
@@ -37,7 +37,7 @@ interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin {
|
||||
object INTERFACE_COMPANION_PRIVATE_INSTANCE : IrDeclarationOriginImpl("INTERFACE_COMPANION_PRIVATE_INSTANCE", isSynthetic = true)
|
||||
object POLYMORPHIC_SIGNATURE_INSTANTIATION : IrDeclarationOriginImpl("POLYMORPHIC_SIGNATURE_INSTANTIATION", isSynthetic = true)
|
||||
object ENUM_CONSTRUCTOR_SYNTHETIC_PARAMETER : IrDeclarationOriginImpl("ENUM_CONSTRUCTOR_SYNTHETIC_PARAMETER", isSynthetic = true)
|
||||
object OBJECT_SUPER_CONSTRUCTOR_PARAMETER : IrDeclarationOriginImpl("OBJECT_SUPER_CONSTURCTOR_PARAMETER", isSynthetic = true)
|
||||
object OBJECT_SUPER_CONSTRUCTOR_PARAMETER : IrDeclarationOriginImpl("OBJECT_SUPER_CONSTRUCTOR_PARAMETER", isSynthetic = true)
|
||||
object CONTINUATION_CLASS : IrDeclarationOriginImpl("CONTINUATION_CLASS")
|
||||
object SUSPEND_LAMBDA : IrDeclarationOriginImpl("SUSPEND_LAMBDA")
|
||||
object FOR_INLINE_STATE_MACHINE_TEMPLATE : IrDeclarationOriginImpl("FOR_INLINE_TEMPLATE")
|
||||
@@ -48,4 +48,5 @@ interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin {
|
||||
object ABSTRACT_BRIDGE_STUB : IrDeclarationOriginImpl("ABSTRACT_BRIDGE_STUB")
|
||||
object INVOVEDYNAMIC_CALL_TARGET : IrDeclarationOriginImpl("INVOVEDYNAMIC_CALL_TARGET")
|
||||
object INLINE_LAMBDA : IrDeclarationOriginImpl("INLINE_LAMBDA")
|
||||
object PROXY_FUN_FOR_INDY_SAM_CONVESION : IrDeclarationOriginImpl("PROXY_FUN_FOR_INDY_SAM_CONVESION")
|
||||
}
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// SAM_CONVERSIONS: INDY
|
||||
|
||||
// CHECK_BYTECODE_TEXT
|
||||
// JVM_IR_TEMPLATES
|
||||
// 1 java/lang/invoke/LambdaMetafactory
|
||||
|
||||
// FILE: genericBoundInnerConstructorRef.kt
|
||||
class Outer<TO>(val s1: TO) {
|
||||
inner class Inner<TI>(val s2: TI) {
|
||||
fun t() = s1.toString() + s2.toString()
|
||||
}
|
||||
}
|
||||
|
||||
fun box() = Sam(Outer("O")::Inner).get("K").t()
|
||||
|
||||
// FILE: Sam.java
|
||||
public interface Sam<TO, TI> {
|
||||
Outer<TO>.Inner<TI> get(String s);
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// SAM_CONVERSIONS: INDY
|
||||
|
||||
// CHECK_BYTECODE_TEXT
|
||||
// JVM_IR_TEMPLATES
|
||||
// 1 java/lang/invoke/LambdaMetafactory
|
||||
|
||||
// FILE: genericInnerConstructorRef.kt
|
||||
|
||||
// Can't resolve generic type argument for unbound constructor reference,
|
||||
// so 'Outer' has no type parameters.
|
||||
class Outer(val s1: String) {
|
||||
inner class Inner<TI>(val s2: TI) {
|
||||
fun t() = s1 + s2.toString()
|
||||
}
|
||||
}
|
||||
|
||||
fun box() = Sam(Outer::Inner).get(Outer("O"), "K").t()
|
||||
|
||||
// FILE: Sam.java
|
||||
public interface Sam<TI> {
|
||||
Outer.Inner<TI> get(Outer outer, String s);
|
||||
}
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
|
||||
// CHECK_BYTECODE_TEXT
|
||||
// JVM_IR_TEMPLATES
|
||||
// 0 java/lang/invoke/LambdaMetafactory
|
||||
// 1 java/lang/invoke/LambdaMetafactory
|
||||
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// ^ OVERLOAD_RESOLUTION_AMBIGUITY: Overload resolution ambiguity between candidates: [kotlin/collections/plus, kotlin/collections/plus]
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// SAM_CONVERSIONS: INDY
|
||||
|
||||
// CHECK_BYTECODE_TEXT
|
||||
// JVM_IR_TEMPLATES
|
||||
// 4 java/lang/invoke/LambdaMetafactory
|
||||
|
||||
// FILE: voidReturnTypeAsObject.kt
|
||||
|
||||
var t = "Failed"
|
||||
|
||||
fun ok(s: String) { t = s }
|
||||
|
||||
fun box(): String {
|
||||
Sam(::ok).get("1")
|
||||
Sam(::ok).get("2")
|
||||
Sam(::ok).get("3")
|
||||
|
||||
val r = Sam(::ok).get("OK")
|
||||
if (r != Unit) {
|
||||
return "Failed: $r"
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// FILE: Sam.java
|
||||
public interface Sam {
|
||||
Object get(String s);
|
||||
}
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
// CHECK_BYTECODE_TEXT
|
||||
// JVM_IR_TEMPLATES
|
||||
// 0 java/lang/invoke/LambdaMetafactory
|
||||
// 1 java/lang/invoke/LambdaMetafactory
|
||||
|
||||
// FILE: anyNToString.kt
|
||||
fun box() =
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
// CHECK_BYTECODE_TEXT
|
||||
// JVM_IR_TEMPLATES
|
||||
// 0 java/lang/invoke/LambdaMetafactory
|
||||
// 1 java/lang/invoke/LambdaMetafactory
|
||||
|
||||
// FILE: arrayConstructor.kt
|
||||
fun box(): String {
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
// CHECK_BYTECODE_TEXT
|
||||
// JVM_IR_TEMPLATES
|
||||
// 0 java/lang/invoke/LambdaMetafactory
|
||||
// 1 java/lang/invoke/LambdaMetafactory
|
||||
|
||||
// FILE: charArrayOf.kt
|
||||
fun box(): String {
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// SAM_CONVERSIONS: INDY
|
||||
|
||||
// CHECK_BYTECODE_TEXT
|
||||
// JVM_IR_TEMPLATES
|
||||
// 1 java/lang/invoke/LambdaMetafactory
|
||||
|
||||
// FILE: intArrayOf.kt
|
||||
fun box(): String {
|
||||
val sam = Sam(::intArrayOf)
|
||||
val arr = sam.get(intArrayOf('O'.toInt(), 'K'.toInt()))
|
||||
return "${arr[0].toChar()}${arr[1].toChar()}"
|
||||
}
|
||||
|
||||
// FILE: Sam.java
|
||||
public interface Sam {
|
||||
int[] get(int[] s);
|
||||
}
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
// CHECK_BYTECODE_TEXT
|
||||
// JVM_IR_TEMPLATES
|
||||
// 0 java/lang/invoke/LambdaMetafactory
|
||||
// 1 java/lang/invoke/LambdaMetafactory
|
||||
|
||||
// FILE: stringNPlus.kt
|
||||
fun test(x: String?, y: Any?) =
|
||||
|
||||
compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/voidReturnTypeAsObject.kt
Vendored
+1
-2
@@ -4,8 +4,7 @@
|
||||
|
||||
// CHECK_BYTECODE_TEXT
|
||||
// JVM_IR_TEMPLATES
|
||||
// 0 java/lang/invoke/LambdaMetafactory
|
||||
// 1 final synthetic class VoidReturnTypeAsObjectKt\$box\$r\$[0-9]+
|
||||
// 1 java/lang/invoke/LambdaMetafactory
|
||||
|
||||
// FILE: voidReturnTypeAsObject.kt
|
||||
var t = "Failed"
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// SAM_CONVERSIONS: INDY
|
||||
// WITH_RUNTIME
|
||||
// FULL_JDK
|
||||
|
||||
// CHECK_BYTECODE_TEXT
|
||||
// JVM_IR_TEMPLATES
|
||||
// 1 java/lang/invoke/LambdaMetafactory
|
||||
|
||||
// FILE: inlineFunWithPrivateMethod.kt
|
||||
|
||||
private inline fun g(x: String) = println(x)
|
||||
|
||||
fun call(c: Consumer<String>) = c.accept("")
|
||||
|
||||
fun box(): String {
|
||||
val obj = { call(::g) } // `g` is inaccessible in this scope
|
||||
obj()
|
||||
return "OK"
|
||||
}
|
||||
|
||||
// FILE: Consumer.java
|
||||
|
||||
public interface Consumer<T> {
|
||||
void accept(T t);
|
||||
}
|
||||
@@ -6,22 +6,13 @@
|
||||
|
||||
// CHECK_BYTECODE_TEXT
|
||||
// JVM_IR_TEMPLATES
|
||||
// 0 java/lang/invoke/LambdaMetafactory
|
||||
// 1 java/lang/invoke/LambdaMetafactory
|
||||
|
||||
// FILE: inlineOnly.kt
|
||||
|
||||
inline fun <reified T> f(x: T) =
|
||||
println("${T::class.simpleName}($x)")
|
||||
|
||||
private inline fun g(x: String) = println(x)
|
||||
|
||||
fun call(c: Consumer<String>) = c.accept("")
|
||||
|
||||
fun box(): String {
|
||||
call(::println) // `println` is `@InlineOnly`
|
||||
call(::f) // `f` has a reified type parameter and thus isn't callable directly
|
||||
val obj = { call(::g) } // `g` is inaccessible in this scope
|
||||
obj()
|
||||
call(::println) // 'println' is @InlineOnly
|
||||
return "OK"
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// SAM_CONVERSIONS: INDY
|
||||
// WITH_RUNTIME
|
||||
// FULL_JDK
|
||||
|
||||
// CHECK_BYTECODE_TEXT
|
||||
// JVM_IR_TEMPLATES
|
||||
// 0 java/lang/invoke/LambdaMetafactory
|
||||
|
||||
// FILE: reifiedTypeParameter.kt
|
||||
|
||||
inline fun <reified T> f(x: T) =
|
||||
println("${T::class.simpleName}($x)")
|
||||
|
||||
fun call(c: Consumer<String>) = c.accept("")
|
||||
|
||||
fun box(): String {
|
||||
call(::f) // `f` has a reified type parameter and thus isn't callable directly
|
||||
return "OK"
|
||||
}
|
||||
|
||||
// FILE: Consumer.java
|
||||
|
||||
public interface Consumer<T> {
|
||||
void accept(T t);
|
||||
}
|
||||
+36
@@ -22095,6 +22095,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/genericLambdaSignature.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineFunWithPrivateMethod.kt")
|
||||
public void testInlineFunWithPrivateMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineFunWithPrivateMethod.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineOnly.kt")
|
||||
public void testInlineOnly() throws Exception {
|
||||
@@ -22143,6 +22149,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/primitiveVsWrapperInSam.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("reifiedTypeParameter.kt")
|
||||
public void testReifiedTypeParameter() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/reifiedTypeParameter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("samConversionInsideSamConvertedLambda.kt")
|
||||
public void testSamConversionInsideSamConvertedLambda() throws Exception {
|
||||
@@ -22342,6 +22354,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/enhancedNullability.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericBoundInnerConstructorRef.kt")
|
||||
public void testGenericBoundInnerConstructorRef() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericBoundInnerConstructorRef.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericInnerConstructorRef.kt")
|
||||
public void testGenericInnerConstructorRef() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericInnerConstructorRef.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("innerConstructorRef.kt")
|
||||
public void testInnerConstructorRef() throws Exception {
|
||||
@@ -22396,6 +22420,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multifileClassMemberFromStdlib.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleProxyWrappersForSameFunction.kt")
|
||||
public void testMultipleProxyWrappersForSameFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multipleProxyWrappersForSameFunction.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonTrivialReceiver.kt")
|
||||
public void testNonTrivialReceiver() throws Exception {
|
||||
@@ -22483,6 +22513,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/enumValues.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("intArrayOf.kt")
|
||||
public void testIntArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/intArrayOf.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("intPlus.kt")
|
||||
public void testIntPlus() throws Exception {
|
||||
|
||||
+36
@@ -22233,6 +22233,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/genericLambdaSignature.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineFunWithPrivateMethod.kt")
|
||||
public void testInlineFunWithPrivateMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineFunWithPrivateMethod.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineOnly.kt")
|
||||
public void testInlineOnly() throws Exception {
|
||||
@@ -22281,6 +22287,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/primitiveVsWrapperInSam.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("reifiedTypeParameter.kt")
|
||||
public void testReifiedTypeParameter() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/reifiedTypeParameter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("samConversionInsideSamConvertedLambda.kt")
|
||||
public void testSamConversionInsideSamConvertedLambda() throws Exception {
|
||||
@@ -22480,6 +22492,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/enhancedNullability.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericBoundInnerConstructorRef.kt")
|
||||
public void testGenericBoundInnerConstructorRef() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericBoundInnerConstructorRef.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericInnerConstructorRef.kt")
|
||||
public void testGenericInnerConstructorRef() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericInnerConstructorRef.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("innerConstructorRef.kt")
|
||||
public void testInnerConstructorRef() throws Exception {
|
||||
@@ -22534,6 +22558,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multifileClassMemberFromStdlib.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleProxyWrappersForSameFunction.kt")
|
||||
public void testMultipleProxyWrappersForSameFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multipleProxyWrappersForSameFunction.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonTrivialReceiver.kt")
|
||||
public void testNonTrivialReceiver() throws Exception {
|
||||
@@ -22621,6 +22651,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/enumValues.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("intArrayOf.kt")
|
||||
public void testIntArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/intArrayOf.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("intPlus.kt")
|
||||
public void testIntPlus() throws Exception {
|
||||
|
||||
+30
@@ -18495,6 +18495,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/genericFunInterfaceWithPrimitive.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineFunWithPrivateMethod.kt")
|
||||
public void testInlineFunWithPrivateMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineFunWithPrivateMethod.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOnly.kt")
|
||||
public void testInlineOnly() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineOnly.kt");
|
||||
@@ -18535,6 +18540,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/primitiveVsWrapperInSam.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("reifiedTypeParameter.kt")
|
||||
public void testReifiedTypeParameter() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/reifiedTypeParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("samConversionInsideSamConvertedLambda.kt")
|
||||
public void testSamConversionInsideSamConvertedLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/samConversionInsideSamConvertedLambda.kt");
|
||||
@@ -18705,6 +18715,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/enhancedNullability.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("genericBoundInnerConstructorRef.kt")
|
||||
public void testGenericBoundInnerConstructorRef() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericBoundInnerConstructorRef.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("genericInnerConstructorRef.kt")
|
||||
public void testGenericInnerConstructorRef() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericInnerConstructorRef.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("innerConstructorRef.kt")
|
||||
public void testInnerConstructorRef() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/innerConstructorRef.kt");
|
||||
@@ -18750,6 +18770,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multifileClassMemberFromStdlib.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("multipleProxyWrappersForSameFunction.kt")
|
||||
public void testMultipleProxyWrappersForSameFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multipleProxyWrappersForSameFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonTrivialReceiver.kt")
|
||||
public void testNonTrivialReceiver() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/nonTrivialReceiver.kt");
|
||||
@@ -18827,6 +18852,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/enumValues.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("intArrayOf.kt")
|
||||
public void testIntArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/intArrayOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("intPlus.kt")
|
||||
public void testIntPlus() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/intPlus.kt");
|
||||
|
||||
Reference in New Issue
Block a user