JVM: Suspend converted references inherit AdaptedFunctionReference

This commit is contained in:
Dmitry Petrov
2020-04-28 13:40:00 +03:00
parent deecb6a28e
commit 878e838f0b
8 changed files with 58 additions and 11 deletions
@@ -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<KtElement> {
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<KtElement> {
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<KtElement> {
(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<KtElement> {
}
//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) +
@@ -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
}
@@ -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");
@@ -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"
}
@@ -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");
@@ -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");
@@ -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");
@@ -26,6 +26,11 @@ public class FunctionReference extends CallableReference implements FunctionBase
* fun use(f: () -> Unit) {}
* use(::target)
* </pre></ul>
* <ul>2 - whether suspend conversion happened, i.e.,<pre>
* fun target() {}
* fun useSuspend(f: suspend () -> Unit) {}
* useSuspend(::target)
* </pre></ul>
* </li>
*/
@SinceKotlin(version = "1.4")