diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java index cc197008993..08202cad140 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java @@ -12,7 +12,6 @@ import kotlin.Unit; import kotlin.collections.CollectionsKt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.builtins.FunctionTypesKt; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.codegen.binding.CalculatedClosure; import org.jetbrains.kotlin.codegen.binding.CodegenBinding; @@ -528,7 +527,7 @@ public class ClosureCodegen extends MemberCodegen { PropertyReferenceCodegen.generateCallableReferenceSignature(iv, functionReferenceTarget, state); int flags = (isTopLevelCallableReference(functionReferenceTarget) ? 1 : 0) + - (calculateFunctionReferenceFlags(functionReferenceCall, funDescriptor, classDescriptor) << 1); + (calculateFunctionReferenceFlags(functionReferenceCall, funDescriptor) << 1); iv.aconst(flags); superCtorArgTypes.add(JAVA_CLASS_TYPE); superCtorArgTypes.add(JAVA_STRING_TYPE); @@ -553,8 +552,7 @@ public class ClosureCodegen extends MemberCodegen { private static int calculateFunctionReferenceFlags( @NotNull ResolvedCall call, - @NotNull FunctionDescriptor anonymousAdaptedFunction, - @NotNull ClassDescriptor classDescriptor + @NotNull FunctionDescriptor anonymousAdapterFunction ) { boolean hasVarargMappedToElement = false; FunctionDescriptor target = (FunctionDescriptor) call.getResultingDescriptor(); @@ -562,10 +560,10 @@ public class ClosureCodegen extends MemberCodegen { (call.getDispatchReceiver() instanceof TransientReceiver ? 1 : 0) + (call.getExtensionReceiver() instanceof TransientReceiver ? 1 : 0); for (int i = shift; - i < anonymousAdaptedFunction.getValueParameters().size() && i - shift < target.getValueParameters().size(); + i < anonymousAdapterFunction.getValueParameters().size() && i - shift < target.getValueParameters().size(); i++) { ValueParameterDescriptor targetParameter = target.getValueParameters().get(i - shift); - ValueParameterDescriptor adaptedParameter = anonymousAdaptedFunction.getValueParameters().get(i); + ValueParameterDescriptor adaptedParameter = anonymousAdapterFunction.getValueParameters().get(i); // Vararg to element conversion is happening if the target parameter is vararg (e.g. `vararg xs: Int`), // but the adapted parameter's type is not equal to the target parameter's type (which is `IntArray`). @@ -577,12 +575,10 @@ public class ClosureCodegen extends MemberCodegen { } //noinspection ConstantConditions - boolean hasCoercionToUnit = KotlinBuiltIns.isUnit(anonymousAdaptedFunction.getReturnType()) && + boolean hasCoercionToUnit = KotlinBuiltIns.isUnit(anonymousAdapterFunction.getReturnType()) && !KotlinBuiltIns.isUnit(target.getReturnType()); - boolean hasSuspendConversion = - !target.isSuspend() && - classDescriptor.getTypeConstructor().getSupertypes().stream().anyMatch(FunctionTypesKt::isSuspendFunctionType); + boolean hasSuspendConversion = !target.isSuspend() && anonymousAdapterFunction.isSuspend(); return (hasVarargMappedToElement ? 1 : 0) + (hasSuspendConversion ? 2 : 0) + diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmRuntimeTypes.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmRuntimeTypes.kt index 2481fba4830..5e8d9872b71 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmRuntimeTypes.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmRuntimeTypes.kt @@ -154,7 +154,7 @@ class JvmRuntimeTypes( val suspendFunctionType = if (referencedFunction.isSuspend) suspendFunctionInterface?.defaultType else null val superClass = when { - isAdaptedCallableReference -> adaptedFunctionReference + isAdaptedCallableReference || isSuspendConversion -> adaptedFunctionReference generateOptimizedCallableReferenceSuperClasses -> functionReferenceImpl else -> functionReference } 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 9424f74e985..4efc6d6f598 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 @@ -2075,6 +2075,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noReflectionForAdaptedCallableReferences.kt"); } + @TestMetadata("noReflectionForAdaptedCallableReferencesWithSuspendConversion.kt") + public void testNoReflectionForAdaptedCallableReferencesWithSuspendConversion() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noReflectionForAdaptedCallableReferencesWithSuspendConversion.kt"); + } + @TestMetadata("reflectionForVarargAsArray.kt") public void testReflectionForVarargAsArray() throws Exception { runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/reflectionForVarargAsArray.kt"); diff --git a/compiler/testData/codegen/box/callableReference/adaptedReferences/noReflectionForAdaptedCallableReferencesWithSuspendConversion.kt b/compiler/testData/codegen/box/callableReference/adaptedReferences/noReflectionForAdaptedCallableReferencesWithSuspendConversion.kt new file mode 100644 index 00000000000..4a4f2e8f344 --- /dev/null +++ b/compiler/testData/codegen/box/callableReference/adaptedReferences/noReflectionForAdaptedCallableReferencesWithSuspendConversion.kt @@ -0,0 +1,26 @@ +// !LANGUAGE: +SuspendConversion +// TARGET_BACKEND: JVM +// IGNORE_BACKEND_FIR: JVM_IR +// WITH_RUNTIME + +import kotlin.reflect.KCallable + +private fun check(label: String, fn: Any) { + if (fn is KCallable<*>) { + throw AssertionError("$label is KCallable, ${fn::class.java.simpleName}") + } +} + +fun checkSuspend(label: String, fn: suspend () -> Unit) = check(label, fn) +fun checkSuspendAny(label: String, fn: suspend () -> Any) = check(label, fn) + +fun withSuspendConversion() {} + +class CCtorAsSuspend() + +fun box(): String { + checkSuspend("::withSuspendConversion", ::withSuspendConversion) + checkSuspendAny("::CCtorAsSuspend", ::CCtorAsSuspend) + + return "OK" +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index fcedd261961..ab679bcc0d8 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -2095,6 +2095,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noReflectionForAdaptedCallableReferences.kt"); } + @TestMetadata("noReflectionForAdaptedCallableReferencesWithSuspendConversion.kt") + public void testNoReflectionForAdaptedCallableReferencesWithSuspendConversion() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noReflectionForAdaptedCallableReferencesWithSuspendConversion.kt"); + } + @TestMetadata("reflectionForVarargAsArray.kt") public void testReflectionForVarargAsArray() throws Exception { runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/reflectionForVarargAsArray.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index dd50b51d3ce..f1e1493a3ce 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -2095,6 +2095,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noReflectionForAdaptedCallableReferences.kt"); } + @TestMetadata("noReflectionForAdaptedCallableReferencesWithSuspendConversion.kt") + public void testNoReflectionForAdaptedCallableReferencesWithSuspendConversion() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noReflectionForAdaptedCallableReferencesWithSuspendConversion.kt"); + } + @TestMetadata("reflectionForVarargAsArray.kt") public void testReflectionForVarargAsArray() throws Exception { runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/reflectionForVarargAsArray.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 2e816e6c21a..b2de0adb413 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -2075,6 +2075,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noReflectionForAdaptedCallableReferences.kt"); } + @TestMetadata("noReflectionForAdaptedCallableReferencesWithSuspendConversion.kt") + public void testNoReflectionForAdaptedCallableReferencesWithSuspendConversion() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noReflectionForAdaptedCallableReferencesWithSuspendConversion.kt"); + } + @TestMetadata("reflectionForVarargAsArray.kt") public void testReflectionForVarargAsArray() throws Exception { runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/reflectionForVarargAsArray.kt"); diff --git a/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/FunctionReference.java b/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/FunctionReference.java index e39f264fe3f..553677fe8e0 100644 --- a/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/FunctionReference.java +++ b/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/FunctionReference.java @@ -26,6 +26,11 @@ public class FunctionReference extends CallableReference implements FunctionBase * fun use(f: () -> Unit) {} * use(::target) * + *
    2 - whether suspend conversion happened, i.e.,
    +     *         fun target() {}
    +     *         fun useSuspend(f: suspend () -> Unit) {}
    +     *         useSuspend(::target)
    +     *     
* */ @SinceKotlin(version = "1.4")