Check variables, captured by outer object when searching for suspend crossinline parameters
This commit is contained in:
@@ -14,6 +14,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
||||||
import org.jetbrains.kotlin.backend.common.bridges.Bridge;
|
import org.jetbrains.kotlin.backend.common.bridges.Bridge;
|
||||||
|
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
|
||||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||||
import org.jetbrains.kotlin.codegen.context.*;
|
import org.jetbrains.kotlin.codegen.context.*;
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
|
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
|
||||||
@@ -1645,7 +1646,7 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Map<DeclarationDescriptor, EnclosedValueDescriptor> getCaptureVariables() {
|
public CalculatedClosure getClosure() {
|
||||||
return owner.closure == null ? null : owner.closure.getCaptureVariables();
|
return owner.closure;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,11 @@ package org.jetbrains.kotlin.codegen.coroutines
|
|||||||
import com.intellij.util.ArrayUtil
|
import com.intellij.util.ArrayUtil
|
||||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
|
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
|
||||||
import org.jetbrains.kotlin.codegen.*
|
import org.jetbrains.kotlin.codegen.*
|
||||||
|
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure
|
||||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA
|
||||||
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLOSURE
|
||||||
import org.jetbrains.kotlin.codegen.context.ClosureContext
|
import org.jetbrains.kotlin.codegen.context.ClosureContext
|
||||||
import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor
|
|
||||||
import org.jetbrains.kotlin.codegen.context.MethodContext
|
import org.jetbrains.kotlin.codegen.context.MethodContext
|
||||||
import org.jetbrains.kotlin.codegen.inline.coroutines.SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor
|
import org.jetbrains.kotlin.codegen.inline.coroutines.SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor
|
||||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION
|
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION
|
||||||
@@ -26,6 +27,7 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
|||||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
@@ -479,7 +481,7 @@ class CoroutineCodegenForLambda private constructor(
|
|||||||
MethodNodeCopyingMethodVisitor(
|
MethodNodeCopyingMethodVisitor(
|
||||||
SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
|
SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
|
||||||
stateMachineBuilder, access, name, desc, v.thisName,
|
stateMachineBuilder, access, name, desc, v.thisName,
|
||||||
isCapturedSuspendLambda = { isCapturedSuspendLambda(closure.captureVariables, it.name) }
|
isCapturedSuspendLambda = { isCapturedSuspendLambda(closure, it.name, state.bindingContext) }
|
||||||
), access, name, desc,
|
), access, name, desc,
|
||||||
newMethod = { origin, newAccess, newName, newDesc ->
|
newMethod = { origin, newAccess, newName, newDesc ->
|
||||||
functionCodegen.newMethod(origin, newAccess, newName, newDesc, null, null)
|
functionCodegen.newMethod(origin, newAccess, newName, newDesc, null, null)
|
||||||
@@ -528,13 +530,19 @@ class CoroutineCodegenForLambda private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isCapturedSuspendLambda(captureVariables: Map<DeclarationDescriptor, EnclosedValueDescriptor>, name: String): Boolean {
|
fun isCapturedSuspendLambda(closure: CalculatedClosure, name: String, bindingContext: BindingContext): Boolean {
|
||||||
for ((param, value) in captureVariables) {
|
for ((param, value) in closure.captureVariables) {
|
||||||
if (param !is ValueParameterDescriptor) continue
|
if (param !is ValueParameterDescriptor) continue
|
||||||
if (value.fieldName != name) continue
|
if (value.fieldName != name) continue
|
||||||
return param.type.isSuspendFunctionTypeOrSubtype
|
return param.type.isSuspendFunctionTypeOrSubtype
|
||||||
}
|
}
|
||||||
return false
|
val classDescriptor = closure.capturedOuterClassDescriptor ?: return false
|
||||||
|
return isCapturedSuspendLambda(classDescriptor, name, bindingContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isCapturedSuspendLambda(classDescriptor: ClassDescriptor, name: String, bindingContext: BindingContext): Boolean {
|
||||||
|
val closure = bindingContext[CLOSURE, classDescriptor] ?: return false
|
||||||
|
return isCapturedSuspendLambda(closure, name, bindingContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AddEndLabelMethodVisitor(
|
private class AddEndLabelMethodVisitor(
|
||||||
|
|||||||
+3
-2
@@ -76,10 +76,11 @@ open class SuspendFunctionGenerationStrategy(
|
|||||||
access, name, desc, containingClassInternalName,
|
access, name, desc, containingClassInternalName,
|
||||||
isCapturedSuspendLambda = {
|
isCapturedSuspendLambda = {
|
||||||
isCapturedSuspendLambda(
|
isCapturedSuspendLambda(
|
||||||
functionCodegen.captureVariables.sure {
|
functionCodegen.closure.sure {
|
||||||
"Anonymous object should have closure"
|
"Anonymous object should have closure"
|
||||||
},
|
},
|
||||||
it.name
|
it.name,
|
||||||
|
state.bindingContext
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
), access, name, desc,
|
), access, name, desc,
|
||||||
|
|||||||
+2
-2
@@ -484,9 +484,9 @@ class AnonymousObjectTransformer(
|
|||||||
alreadyAddedParam?.newFieldName ?: getNewFieldName(desc.fieldName, false),
|
alreadyAddedParam?.newFieldName ?: getNewFieldName(desc.fieldName, false),
|
||||||
alreadyAddedParam != null
|
alreadyAddedParam != null
|
||||||
)
|
)
|
||||||
if (info is PsiExpressionLambda && info.captureVariables.any { it.value.fieldName == desc.fieldName }) {
|
if (info is PsiExpressionLambda && info.closure.captureVariables.any { it.value.fieldName == desc.fieldName }) {
|
||||||
recapturedParamInfo.functionalArgument = NonInlineableArgumentForInlineableParameterCalledInSuspend(
|
recapturedParamInfo.functionalArgument = NonInlineableArgumentForInlineableParameterCalledInSuspend(
|
||||||
isCapturedSuspendLambda(info.captureVariables, desc.fieldName)
|
isCapturedSuspendLambda(info.closure, desc.fieldName, inliningContext.state.bindingContext)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val composed = StackValue.field(
|
val composed = StackValue.field(
|
||||||
|
|||||||
@@ -230,7 +230,8 @@ class PsiExpressionLambda(
|
|||||||
|
|
||||||
private val labels: Set<String>
|
private val labels: Set<String>
|
||||||
|
|
||||||
private var closure: CalculatedClosure
|
var closure: CalculatedClosure
|
||||||
|
private set
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val bindingContext = typeMapper.bindingContext
|
val bindingContext = typeMapper.bindingContext
|
||||||
@@ -307,6 +308,4 @@ class PsiExpressionLambda(
|
|||||||
|
|
||||||
val isPropertyReference: Boolean
|
val isPropertyReference: Boolean
|
||||||
get() = propertyReferenceInfo != null
|
get() = propertyReferenceInfo != null
|
||||||
|
|
||||||
val captureVariables = closure.captureVariables
|
|
||||||
}
|
}
|
||||||
+31
-13
@@ -10,13 +10,13 @@ import org.jetbrains.kotlin.codegen.AsmUtil.CAPTURED_THIS_FIELD
|
|||||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||||
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
|
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.*
|
import org.jetbrains.kotlin.codegen.coroutines.*
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.getLastParameterIndex
|
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.replaceFakeContinuationsWithRealOnes
|
|
||||||
import org.jetbrains.kotlin.codegen.inline.*
|
import org.jetbrains.kotlin.codegen.inline.*
|
||||||
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
|
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
|
||||||
import org.jetbrains.kotlin.codegen.optimization.common.findPreviousOrNull
|
import org.jetbrains.kotlin.codegen.optimization.common.findPreviousOrNull
|
||||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||||
import org.jetbrains.kotlin.config.isReleaseCoroutines
|
import org.jetbrains.kotlin.config.isReleaseCoroutines
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||||
@@ -98,7 +98,7 @@ class CoroutineTransformer(
|
|||||||
ArrayUtil.toStringArray(node.exceptions)
|
ArrayUtil.toStringArray(node.exceptions)
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
val stateMachineBuilder = surroundNoinlineCallsWithMarkersIfNeeded(
|
val stateMachineBuilder = surroundNoinlineCallsWithMarkers(
|
||||||
node,
|
node,
|
||||||
CoroutineTransformerMethodVisitor(
|
CoroutineTransformerMethodVisitor(
|
||||||
createNewMethodFrom(node, name), node.access, name, node.desc, null, null,
|
createNewMethodFrom(node, name), node.access, name, node.desc, null, null,
|
||||||
@@ -137,7 +137,7 @@ class CoroutineTransformer(
|
|||||||
ArrayUtil.toStringArray(node.exceptions)
|
ArrayUtil.toStringArray(node.exceptions)
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
val stateMachineBuilder = surroundNoinlineCallsWithMarkersIfNeeded(
|
val stateMachineBuilder = surroundNoinlineCallsWithMarkers(
|
||||||
node,
|
node,
|
||||||
CoroutineTransformerMethodVisitor(
|
CoroutineTransformerMethodVisitor(
|
||||||
createNewMethodFrom(node, name), node.access, name, node.desc, null, null,
|
createNewMethodFrom(node, name), node.access, name, node.desc, null, null,
|
||||||
@@ -165,16 +165,34 @@ class CoroutineTransformer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun surroundNoinlineCallsWithMarkersIfNeeded(node: MethodNode, delegate: MethodVisitor): MethodVisitor =
|
private fun surroundNoinlineCallsWithMarkers(node: MethodNode, delegate: MethodVisitor): MethodVisitor =
|
||||||
if (capturedParams.any { it.functionalArgument?.isSuspendLambda() == true })
|
SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
|
||||||
SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
|
delegate, node.access, node.name, node.desc, classBuilder.thisName, this::fieldIsCapturedSuspendLambda
|
||||||
delegate, node.access, node.name, node.desc, classBuilder.thisName, this::isCapturedSuspendLambda
|
)
|
||||||
)
|
|
||||||
else
|
|
||||||
delegate
|
|
||||||
|
|
||||||
private fun isCapturedSuspendLambda(field: FieldInsnNode): Boolean =
|
private fun fieldIsCapturedSuspendLambda(field: FieldInsnNode): Boolean =
|
||||||
capturedParams.find { it.newFieldName == field.name }?.functionalArgument?.isSuspendLambda() == true
|
capturedParams.find { it.newFieldName == field.name }?.let { it.functionalArgument?.isSuspendLambda() == true }
|
||||||
|
?: isSuspendLambdaCapturedByOuterObjectOrLambda(field)
|
||||||
|
|
||||||
|
// We cannot find the lambda in captured parameters: it came from object outside of the our reach:
|
||||||
|
// this can happen when the lambda capture by non-transformed closure:
|
||||||
|
// inline fun inlineMe(crossinline c: suspend() -> Unit) = suspend { c() }
|
||||||
|
// inline fun inlineMe2(crossinline c: suspend() -> Unit) = suspend { inlineMe { c() }() }
|
||||||
|
// Suppose, we inline inlineMe into inlineMe2: the only knowledge we have about inlineMe$1 is captured receiver (this$0)
|
||||||
|
// Thus, transformed lambda from inlineMe, inlineMe3$$inlined$inlineMe2$1 contains the following bytecode
|
||||||
|
// ALOAD 0
|
||||||
|
// GETFIELD inlineMe2$1$invokeSuspend$$inlined$inlineMe$1.this$0 : LScratchKt$inlineMe2$1;
|
||||||
|
// GETFIELD inlineMe2$1.$c : Lkotlin/jvm/functions/Function1;
|
||||||
|
// Since inlineMe2's lambda is outside of reach of the inliner, find crossinline parameter from compilation context:
|
||||||
|
private fun isSuspendLambdaCapturedByOuterObjectOrLambda(field: FieldInsnNode): Boolean {
|
||||||
|
val functionDescriptor = inliningContext.root.sourceCompilerForInline.compilationContextFunctionDescriptor
|
||||||
|
val classDescriptor = functionDescriptor.findContainingClassOrLambda() ?: return false
|
||||||
|
return isCapturedSuspendLambda(classDescriptor, field.name, inliningContext.state.bindingContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
private tailrec fun DeclarationDescriptor.findContainingClassOrLambda(): ClassDescriptor? =
|
||||||
|
if (containingDeclaration is ClassDescriptor) containingDeclaration as ClassDescriptor
|
||||||
|
else containingDeclaration?.findContainingClassOrLambda()
|
||||||
|
|
||||||
private fun createNewMethodFrom(node: MethodNode, name: String): MethodVisitor {
|
private fun createNewMethodFrom(node: MethodNode, name: String): MethodVisitor {
|
||||||
return classBuilder.newMethod(
|
return classBuilder.newMethod(
|
||||||
|
|||||||
@@ -0,0 +1,283 @@
|
|||||||
|
// IGNORE_BACKEND: JVM_IR
|
||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// COMMON_COROUTINES_TEST
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// WITH_COROUTINES
|
||||||
|
// CHECK_STATE_MACHINE
|
||||||
|
|
||||||
|
// FILE: inlineMe.kt
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
import helpers.*
|
||||||
|
|
||||||
|
interface SuspendRunnable {
|
||||||
|
suspend fun run1()
|
||||||
|
suspend fun run2()
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun inlineMe(crossinline c1: suspend () -> Unit, crossinline c2: suspend () -> Unit) = object : SuspendRunnable {
|
||||||
|
override suspend fun run1() {
|
||||||
|
c1(); c1()
|
||||||
|
}
|
||||||
|
override suspend fun run2() {
|
||||||
|
c2(); c2()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun inlineMe2(crossinline c1: suspend () -> Unit, crossinline c2: suspend () -> Unit) = inlineMe({ c1(); c1() }) { c2(); c2() }
|
||||||
|
|
||||||
|
inline fun inlineMe3(crossinline c1: suspend () -> Unit, crossinline c2: suspend () -> Unit) = object : SuspendRunnable {
|
||||||
|
override suspend fun run1() {
|
||||||
|
val sr = inlineMe({ c1(); c1() }) { c2(); c2() }
|
||||||
|
sr.run1()
|
||||||
|
sr.run2()
|
||||||
|
}
|
||||||
|
override suspend fun run2() {
|
||||||
|
val sr = inlineMe2({ c1(); c1() }) { c2(); c2() }
|
||||||
|
sr.run1()
|
||||||
|
sr.run2()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun inlineMe4(crossinline c1: suspend () -> Unit, crossinline c2: suspend () -> Unit) = object : SuspendRunnable {
|
||||||
|
override suspend fun run1() {
|
||||||
|
val sr = suspend {
|
||||||
|
c1();
|
||||||
|
c2()
|
||||||
|
}
|
||||||
|
sr()
|
||||||
|
sr()
|
||||||
|
}
|
||||||
|
override suspend fun run2() {
|
||||||
|
val sr = object : SuspendRunnable {
|
||||||
|
override suspend fun run1() {
|
||||||
|
c1(); c1()
|
||||||
|
}
|
||||||
|
override suspend fun run2() {
|
||||||
|
c2(); c2()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sr.run1()
|
||||||
|
sr.run2()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun inlineMe5(crossinline c1: suspend () -> Unit) = inlineMe({ c1(); c1() }) {
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: A.java
|
||||||
|
|
||||||
|
import test.InlineMeKt;
|
||||||
|
import helpers.CoroutineUtilKt;
|
||||||
|
import helpers.EmptyContinuation;
|
||||||
|
import kotlin.Unit;
|
||||||
|
|
||||||
|
public class A {
|
||||||
|
public static Object call() {
|
||||||
|
return InlineMeKt.inlineMe((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation),
|
||||||
|
(continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||||
|
}
|
||||||
|
public static Object call2() {
|
||||||
|
return InlineMeKt.inlineMe2((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation),
|
||||||
|
(continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||||
|
}
|
||||||
|
public static Object call3() {
|
||||||
|
return InlineMeKt.inlineMe3((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation),
|
||||||
|
(continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||||
|
}
|
||||||
|
public static Object call4() {
|
||||||
|
return InlineMeKt.inlineMe4((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation),
|
||||||
|
(continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||||
|
}
|
||||||
|
public static Object call5() {
|
||||||
|
return InlineMeKt.inlineMe5((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: box.kt
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
import helpers.*
|
||||||
|
import COROUTINES_PACKAGE.*
|
||||||
|
|
||||||
|
fun builder(c: suspend () -> Unit) {
|
||||||
|
c.startCoroutine(CheckStateMachineContinuation)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
builder {
|
||||||
|
(A.call() as SuspendRunnable).run1()
|
||||||
|
}
|
||||||
|
StateMachineChecker.check(2)
|
||||||
|
StateMachineChecker.reset()
|
||||||
|
|
||||||
|
builder {
|
||||||
|
(A.call() as SuspendRunnable).run2()
|
||||||
|
}
|
||||||
|
StateMachineChecker.check(2)
|
||||||
|
StateMachineChecker.reset()
|
||||||
|
|
||||||
|
builder {
|
||||||
|
(A.call2() as SuspendRunnable).run1()
|
||||||
|
}
|
||||||
|
StateMachineChecker.check(4)
|
||||||
|
StateMachineChecker.reset()
|
||||||
|
|
||||||
|
builder {
|
||||||
|
(A.call2() as SuspendRunnable).run2()
|
||||||
|
}
|
||||||
|
StateMachineChecker.check(4)
|
||||||
|
StateMachineChecker.reset()
|
||||||
|
|
||||||
|
builder {
|
||||||
|
(A.call3() as SuspendRunnable).run1()
|
||||||
|
}
|
||||||
|
StateMachineChecker.check(8)
|
||||||
|
StateMachineChecker.reset()
|
||||||
|
|
||||||
|
builder {
|
||||||
|
(A.call3() as SuspendRunnable).run2()
|
||||||
|
}
|
||||||
|
StateMachineChecker.check(16)
|
||||||
|
StateMachineChecker.reset()
|
||||||
|
|
||||||
|
builder {
|
||||||
|
(A.call4() as SuspendRunnable).run1()
|
||||||
|
}
|
||||||
|
StateMachineChecker.check(4)
|
||||||
|
StateMachineChecker.reset()
|
||||||
|
|
||||||
|
builder {
|
||||||
|
(A.call4() as SuspendRunnable).run2()
|
||||||
|
}
|
||||||
|
StateMachineChecker.check(4)
|
||||||
|
StateMachineChecker.reset()
|
||||||
|
|
||||||
|
builder {
|
||||||
|
(A.call5() as SuspendRunnable).run1()
|
||||||
|
}
|
||||||
|
StateMachineChecker.check(4)
|
||||||
|
StateMachineChecker.reset()
|
||||||
|
|
||||||
|
builder {
|
||||||
|
(A.call5() as SuspendRunnable).run2()
|
||||||
|
}
|
||||||
|
StateMachineChecker.check(2)
|
||||||
|
StateMachineChecker.reset()
|
||||||
|
|
||||||
|
builder {
|
||||||
|
inlineMe({
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
}) {
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
}.run1()
|
||||||
|
}
|
||||||
|
StateMachineChecker.check(4)
|
||||||
|
StateMachineChecker.reset()
|
||||||
|
builder {
|
||||||
|
inlineMe({
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
}) {
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
}.run2()
|
||||||
|
}
|
||||||
|
StateMachineChecker.check(4)
|
||||||
|
StateMachineChecker.reset()
|
||||||
|
|
||||||
|
builder {
|
||||||
|
inlineMe2 ({
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
}) {
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
}.run1()
|
||||||
|
}
|
||||||
|
StateMachineChecker.check(8)
|
||||||
|
StateMachineChecker.reset()
|
||||||
|
builder {
|
||||||
|
inlineMe2 ({
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
}) {
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
}.run2()
|
||||||
|
}
|
||||||
|
StateMachineChecker.check(8)
|
||||||
|
StateMachineChecker.reset()
|
||||||
|
|
||||||
|
builder {
|
||||||
|
inlineMe3 ({
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
}) {
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
}.run1()
|
||||||
|
}
|
||||||
|
StateMachineChecker.check(16)
|
||||||
|
StateMachineChecker.reset()
|
||||||
|
|
||||||
|
builder {
|
||||||
|
inlineMe3 ({
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
}) {
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
}.run2()
|
||||||
|
}
|
||||||
|
StateMachineChecker.check(32)
|
||||||
|
StateMachineChecker.reset()
|
||||||
|
|
||||||
|
builder {
|
||||||
|
inlineMe4 ({
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
}) {
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
}.run1()
|
||||||
|
}
|
||||||
|
StateMachineChecker.check(8)
|
||||||
|
StateMachineChecker.reset()
|
||||||
|
|
||||||
|
builder {
|
||||||
|
inlineMe4 ({
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
}) {
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
}.run2()
|
||||||
|
}
|
||||||
|
StateMachineChecker.check(8)
|
||||||
|
StateMachineChecker.reset()
|
||||||
|
|
||||||
|
builder {
|
||||||
|
inlineMe5 {
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
}.run1()
|
||||||
|
}
|
||||||
|
StateMachineChecker.check(8)
|
||||||
|
StateMachineChecker.reset()
|
||||||
|
|
||||||
|
builder {
|
||||||
|
inlineMe5 {
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
StateMachineChecker.suspendHere()
|
||||||
|
}.run2()
|
||||||
|
}
|
||||||
|
StateMachineChecker.check(2)
|
||||||
|
StateMachineChecker.reset()
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+6
@@ -261,7 +261,13 @@ public final class CrossinlineKt$filter$$inlined$source$1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@kotlin.Metadata
|
@kotlin.Metadata
|
||||||
|
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||||
public final class CrossinlineKt$fold$$inlined$consumeEach$1$1 {
|
public final class CrossinlineKt$fold$$inlined$consumeEach$1$1 {
|
||||||
|
field L$0: java.lang.Object
|
||||||
|
field L$1: java.lang.Object
|
||||||
|
field L$2: java.lang.Object
|
||||||
|
field L$3: java.lang.Object
|
||||||
|
field L$4: java.lang.Object
|
||||||
field label: int
|
field label: int
|
||||||
synthetic field result: java.lang.Object
|
synthetic field result: java.lang.Object
|
||||||
synthetic final field this$0: CrossinlineKt$fold$$inlined$consumeEach$1
|
synthetic final field this$0: CrossinlineKt$fold$$inlined$consumeEach$1
|
||||||
|
|||||||
+5
@@ -271,6 +271,11 @@ public final class CrossinlineKt$filter$$inlined$source$1 {
|
|||||||
|
|
||||||
@kotlin.Metadata
|
@kotlin.Metadata
|
||||||
public final class CrossinlineKt$fold$$inlined$consumeEach$1$1 {
|
public final class CrossinlineKt$fold$$inlined$consumeEach$1$1 {
|
||||||
|
field L$0: java.lang.Object
|
||||||
|
field L$1: java.lang.Object
|
||||||
|
field L$2: java.lang.Object
|
||||||
|
field L$3: java.lang.Object
|
||||||
|
field L$4: java.lang.Object
|
||||||
synthetic field data: java.lang.Object
|
synthetic field data: java.lang.Object
|
||||||
synthetic field exception: java.lang.Throwable
|
synthetic field exception: java.lang.Throwable
|
||||||
synthetic final field this$0: CrossinlineKt$fold$$inlined$consumeEach$1
|
synthetic final field this$0: CrossinlineKt$fold$$inlined$consumeEach$1
|
||||||
|
|||||||
Vendored
+5
@@ -140,7 +140,12 @@ public final class flow/InnerObjectRetransformationKt$flow$1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@kotlin.Metadata
|
@kotlin.Metadata
|
||||||
|
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||||
public final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1$1 {
|
public final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1$1 {
|
||||||
|
field L$0: java.lang.Object
|
||||||
|
field L$1: java.lang.Object
|
||||||
|
field L$2: java.lang.Object
|
||||||
|
field L$3: java.lang.Object
|
||||||
field label: int
|
field label: int
|
||||||
synthetic field result: java.lang.Object
|
synthetic field result: java.lang.Object
|
||||||
synthetic final field this$0: flow.InnerObjectRetransformationKt$flowWith$$inlined$flow$1
|
synthetic final field this$0: flow.InnerObjectRetransformationKt$flowWith$$inlined$flow$1
|
||||||
|
|||||||
Vendored
+4
@@ -149,6 +149,10 @@ public final class flow/InnerObjectRetransformationKt$flow$1 {
|
|||||||
|
|
||||||
@kotlin.Metadata
|
@kotlin.Metadata
|
||||||
public final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1$1 {
|
public final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1$1 {
|
||||||
|
field L$0: java.lang.Object
|
||||||
|
field L$1: java.lang.Object
|
||||||
|
field L$2: java.lang.Object
|
||||||
|
field L$3: java.lang.Object
|
||||||
synthetic field data: java.lang.Object
|
synthetic field data: java.lang.Object
|
||||||
synthetic field exception: java.lang.Throwable
|
synthetic field exception: java.lang.Throwable
|
||||||
synthetic final field this$0: flow.InnerObjectRetransformationKt$flowWith$$inlined$flow$1
|
synthetic final field this$0: flow.InnerObjectRetransformationKt$flowWith$$inlined$flow$1
|
||||||
|
|||||||
+10
@@ -7426,6 +7426,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
public void testReturnObject_1_3() throws Exception {
|
public void testReturnObject_1_3() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("severalCaptures.kt")
|
||||||
|
public void testSeveralCaptures_1_2() throws Exception {
|
||||||
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/severalCaptures.kt", "kotlin.coroutines.experimental");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("severalCaptures.kt")
|
||||||
|
public void testSeveralCaptures_1_3() throws Exception {
|
||||||
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/severalCaptures.kt", "kotlin.coroutines");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
|
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
|
||||||
|
|||||||
+10
@@ -7426,6 +7426,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
public void testReturnObject_1_3() throws Exception {
|
public void testReturnObject_1_3() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("severalCaptures.kt")
|
||||||
|
public void testSeveralCaptures_1_2() throws Exception {
|
||||||
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/severalCaptures.kt", "kotlin.coroutines.experimental");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("severalCaptures.kt")
|
||||||
|
public void testSeveralCaptures_1_3() throws Exception {
|
||||||
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/severalCaptures.kt", "kotlin.coroutines");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
|
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
|
||||||
|
|||||||
+10
@@ -7426,6 +7426,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
public void testReturnObject_1_3() throws Exception {
|
public void testReturnObject_1_3() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("severalCaptures.kt")
|
||||||
|
public void testSeveralCaptures_1_2() throws Exception {
|
||||||
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/severalCaptures.kt", "kotlin.coroutines.experimental");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("severalCaptures.kt")
|
||||||
|
public void testSeveralCaptures_1_3() throws Exception {
|
||||||
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/severalCaptures.kt", "kotlin.coroutines");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
|
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
|
||||||
|
|||||||
Reference in New Issue
Block a user