Write metadata for suspend function into anonymous coroutine classes

To render nice Kotlin types in toString() of continuation
This commit is contained in:
Alexander Udalov
2017-06-29 21:07:04 +03:00
parent 5a8546519a
commit d97fa604e1
6 changed files with 58 additions and 3 deletions
@@ -250,7 +250,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
* This is needed because once we're serializing this to a proto, there's no place to store information about external type parameters.
*/
@NotNull
private static FunctionDescriptor createFreeLambdaDescriptor(@NotNull FunctionDescriptor descriptor) {
public static FunctionDescriptor createFreeLambdaDescriptor(@NotNull FunctionDescriptor descriptor) {
FunctionDescriptor.CopyBuilder<? extends FunctionDescriptor> builder = descriptor.newCopyBuilder();
List<TypeParameterDescriptor> typeParameters = new ArrayList<>(0);
builder.setTypeParameters(typeParameters);
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.context.ClosureContext
import org.jetbrains.kotlin.codegen.context.MethodContext
import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension
import org.jetbrains.kotlin.coroutines.isSuspendLambda
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
@@ -39,6 +40,7 @@ import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.serialization.DescriptorSerializer
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.makeNullable
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -475,8 +477,10 @@ class CoroutineCodegenForNamedFunction private constructor(
}
override fun generateKotlinMetadataAnnotation() {
writeKotlinMetadata(v, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, 0) {
// Do not write method metadata for raw coroutine state machines
writeKotlinMetadata(v, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, 0) { av ->
val serializer = DescriptorSerializer.createForLambda(JvmSerializerExtension(v.serializationBindings, state))
val functionProto = serializer.functionProto(createFreeLambdaDescriptor(suspendFunctionJvmView)).build()
AsmUtil.writeAnnotationData(av, serializer, functionProto)
}
}
@@ -0,0 +1,33 @@
// TARGET_BACKEND: JVM
// WITH_REFLECT
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
class A<T : String> {
suspend fun foo() {}
suspend fun bar(): T {
foo()
return suspendCoroutineOrReturn { x ->
x.resume(x.toString() as T)
COROUTINE_SUSPENDED
}
}
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var result = ""
builder {
result = A<String>().bar()
}
return if (result == "(kotlin.coroutines.experimental.Continuation<T>) -> kotlin.Any?") "OK" else "Fail: $result"
}
@@ -5018,6 +5018,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
doTest(fileName);
}
@TestMetadata("coroutineToString.kt")
public void testCoroutineToString() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/coroutineToString.kt");
doTest(fileName);
}
@TestMetadata("createCoroutineSafe.kt")
public void testCreateCoroutineSafe() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/createCoroutineSafe.kt");
@@ -5018,6 +5018,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("coroutineToString.kt")
public void testCoroutineToString() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/coroutineToString.kt");
doTest(fileName);
}
@TestMetadata("createCoroutineSafe.kt")
public void testCreateCoroutineSafe() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/createCoroutineSafe.kt");
@@ -5018,6 +5018,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
doTest(fileName);
}
@TestMetadata("coroutineToString.kt")
public void testCoroutineToString() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/coroutineToString.kt");
doTest(fileName);
}
@TestMetadata("createCoroutineSafe.kt")
public void testCreateCoroutineSafe() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/createCoroutineSafe.kt");