diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmRuntimeTypes.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmRuntimeTypes.kt index 5e8d9872b71..d099417addf 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmRuntimeTypes.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmRuntimeTypes.kt @@ -154,8 +154,10 @@ class JvmRuntimeTypes( val suspendFunctionType = if (referencedFunction.isSuspend) suspendFunctionInterface?.defaultType else null val superClass = when { - isAdaptedCallableReference || isSuspendConversion -> adaptedFunctionReference - generateOptimizedCallableReferenceSuperClasses -> functionReferenceImpl + generateOptimizedCallableReferenceSuperClasses -> when { + isAdaptedCallableReference || isSuspendConversion -> adaptedFunctionReference + else -> functionReferenceImpl + } else -> functionReference } return listOfNotNull(superClass.defaultType, functionType, suspendFunctionType) @@ -178,4 +180,4 @@ class JvmRuntimeTypes( return classes[arity].defaultType } -} \ No newline at end of file +} diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 4902f0b4377..5ee1b42ad0e 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -2070,6 +2070,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/manyDefaultsAndVararg.kt"); } + @TestMetadata("noAdaptedReferencesIfNoOptimizedReferencesEnabled.kt") + public void testNoAdaptedReferencesIfNoOptimizedReferencesEnabled() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noAdaptedReferencesIfNoOptimizedReferencesEnabled.kt"); + } + @TestMetadata("noReflectionForAdaptedCallableReferences.kt") public void testNoReflectionForAdaptedCallableReferences() throws Exception { runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noReflectionForAdaptedCallableReferences.kt"); diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt index 86bd62b2c0c..6aeec2ec748 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt @@ -124,10 +124,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext) private val useOptimizedSuperClass = context.state.generateOptimizedCallableReferenceSuperClasses - private val adaptedReferenceOriginalTarget: IrFunction? - private val adapteeCall: IrFunctionAccessExpression? - - init { + private val adapteeCall: IrFunctionAccessExpression? = if (callee.origin == IrDeclarationOrigin.ADAPTER_FOR_CALLABLE_REFERENCE) { // The body of a callable reference adapter contains either only a call, or an IMPLICIT_COERCION_TO_UNIT type operator // applied to a call. That call's target is the original function which we need to get owner/name/signature. @@ -144,24 +141,26 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext) if (call !is IrFunctionAccessExpression) { throw UnsupportedOperationException("Unknown structure of ADAPTER_FOR_CALLABLE_REFERENCE: ${callee.render()}") } - adapteeCall = call - adaptedReferenceOriginalTarget = call.symbol.owner + call } else { - adapteeCall = null - adaptedReferenceOriginalTarget = null + null } - } + + private val adaptedReferenceOriginalTarget: IrFunction? = adapteeCall?.symbol?.owner + private val isAdaptedReference = adaptedReferenceOriginalTarget != null private val needToGenerateSamEqualsHashCodeMethods = samSuperType != null && samSuperType.getClass()?.origin != IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && - (adaptedReferenceOriginalTarget != null || !isLambda) + (isAdaptedReference || !isLambda) private val superType = samSuperType ?: when { - adaptedReferenceOriginalTarget != null -> context.ir.symbols.adaptedFunctionReference isLambda -> context.ir.symbols.lambdaClass - useOptimizedSuperClass -> context.ir.symbols.functionReferenceImpl + useOptimizedSuperClass -> when { + isAdaptedReference -> context.ir.symbols.adaptedFunctionReference + else -> context.ir.symbols.functionReferenceImpl + } else -> context.ir.symbols.functionReference }.defaultType @@ -258,7 +257,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext) SamEqualsHashCodeMethodsGenerator(backendContext, functionReferenceClass, samSuperType) { receiver -> val internalClass = when { - adaptedReferenceOriginalTarget != null -> backendContext.ir.symbols.adaptedFunctionReference + isAdaptedReference -> backendContext.ir.symbols.adaptedFunctionReference else -> backendContext.ir.symbols.functionReferenceImpl } val constructor = internalClass.owner.constructors.single { @@ -299,7 +298,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext) context.irBuiltIns.anyClass.owner.constructors.single() } else { val expectedArity = - if (isLambda && adaptedReferenceOriginalTarget == null) 1 + if (isLambda && !isAdaptedReference) 1 else 1 + (if (boundReceiver != null) 1 else 0) + (if (useOptimizedSuperClass) 4 else 0) superType.getClass()!!.constructors.single { it.valueParameters.size == expectedArity @@ -327,12 +326,8 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext) if (boundReceiver != null) { call.putValueArgument(index++, generateBoundReceiver()) } - val callableReferenceTarget = when { - adaptedReferenceOriginalTarget != null -> adaptedReferenceOriginalTarget - !isLambda && useOptimizedSuperClass -> callee - else -> null - } - if (callableReferenceTarget != null) { + if (!isLambda && useOptimizedSuperClass) { + val callableReferenceTarget = adaptedReferenceOriginalTarget ?: callee val owner = calculateOwnerKClass(callableReferenceTarget.parent, backendContext) call.putValueArgument(index++, kClassToJavaClass(owner, backendContext)) call.putValueArgument(index++, irString(callableReferenceTarget.originalName.asString())) diff --git a/compiler/testData/codegen/box/callableReference/adaptedReferences/noAdaptedReferencesIfNoOptimizedReferencesEnabled.kt b/compiler/testData/codegen/box/callableReference/adaptedReferences/noAdaptedReferencesIfNoOptimizedReferencesEnabled.kt new file mode 100644 index 00000000000..cc0dd0863a5 --- /dev/null +++ b/compiler/testData/codegen/box/callableReference/adaptedReferences/noAdaptedReferencesIfNoOptimizedReferencesEnabled.kt @@ -0,0 +1,19 @@ +// TARGET_BACKEND: JVM +// IGNORE_BACKEND_FIR: JVM_IR +// WITH_RUNTIME +// KOTLIN_CONFIGURATION_FLAGS: +JVM.NO_OPTIMIZED_CALLABLE_REFERENCES + +class A { + fun target(): Int = 42 +} + +fun foo(f: () -> Unit): Any = f + +fun box(): String { + val o = foo(A()::target) + if (o is kotlin.jvm.internal.AdaptedFunctionReference || + o !is kotlin.jvm.internal.FunctionReference) + return "Fail: we shouldn't generate reference to AdaptedFunctionReference if -Xno-optimized-callable-references is enabled" + + return "OK" +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index d1faece6135..ce9be7fd49c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -2090,6 +2090,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/manyDefaultsAndVararg.kt"); } + @TestMetadata("noAdaptedReferencesIfNoOptimizedReferencesEnabled.kt") + public void testNoAdaptedReferencesIfNoOptimizedReferencesEnabled() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noAdaptedReferencesIfNoOptimizedReferencesEnabled.kt"); + } + @TestMetadata("noReflectionForAdaptedCallableReferences.kt") public void testNoReflectionForAdaptedCallableReferences() throws Exception { runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noReflectionForAdaptedCallableReferences.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index e99154a61b9..954534d0290 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -2090,6 +2090,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/manyDefaultsAndVararg.kt"); } + @TestMetadata("noAdaptedReferencesIfNoOptimizedReferencesEnabled.kt") + public void testNoAdaptedReferencesIfNoOptimizedReferencesEnabled() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noAdaptedReferencesIfNoOptimizedReferencesEnabled.kt"); + } + @TestMetadata("noReflectionForAdaptedCallableReferences.kt") public void testNoReflectionForAdaptedCallableReferences() throws Exception { runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noReflectionForAdaptedCallableReferences.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index d096009b640..61020652f46 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -2070,6 +2070,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/manyDefaultsAndVararg.kt"); } + @TestMetadata("noAdaptedReferencesIfNoOptimizedReferencesEnabled.kt") + public void testNoAdaptedReferencesIfNoOptimizedReferencesEnabled() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noAdaptedReferencesIfNoOptimizedReferencesEnabled.kt"); + } + @TestMetadata("noReflectionForAdaptedCallableReferences.kt") public void testNoReflectionForAdaptedCallableReferences() throws Exception { runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noReflectionForAdaptedCallableReferences.kt");