JVM_IR: Do not box/unbox result in continuations
Otherwise, it leads to CCE from kotlin/Result.
This commit is contained in:
+10
-13
@@ -15,10 +15,10 @@ import org.jetbrains.kotlin.codegen.ClassBuilder
|
|||||||
import org.jetbrains.kotlin.codegen.coroutines.CoroutineTransformerMethodVisitor
|
import org.jetbrains.kotlin.codegen.coroutines.CoroutineTransformerMethodVisitor
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME
|
import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_FUNCTION_COMPLETION_PARAMETER_NAME
|
import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_FUNCTION_COMPLETION_PARAMETER_NAME
|
||||||
import org.jetbrains.kotlin.config.coroutinesPackageFqName
|
|
||||||
import org.jetbrains.kotlin.config.isReleaseCoroutines
|
import org.jetbrains.kotlin.config.isReleaseCoroutines
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||||
@@ -37,7 +37,6 @@ import org.jetbrains.kotlin.ir.util.isSuspend
|
|||||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
|
||||||
@@ -106,12 +105,12 @@ internal fun IrFunction.isInvokeSuspendOfContinuation(context: JvmBackendContext
|
|||||||
// Transform `suspend fun foo(params): RetType` into `fun foo(params, $completion: Continuation<RetType>): Any?`
|
// Transform `suspend fun foo(params): RetType` into `fun foo(params, $completion: Continuation<RetType>): Any?`
|
||||||
// the result is called 'view', just to be consistent with old backend.
|
// the result is called 'view', just to be consistent with old backend.
|
||||||
internal fun IrFunction.getOrCreateSuspendFunctionViewIfNeeded(context: JvmBackendContext): IrFunction {
|
internal fun IrFunction.getOrCreateSuspendFunctionViewIfNeeded(context: JvmBackendContext): IrFunction {
|
||||||
if (!isSuspend) return this
|
if (!isSuspend || origin == SUSPEND_FUNCTION_VIEW) return this
|
||||||
// TODO: Optimize
|
|
||||||
if (context.suspendFunctionViews.values.contains(this)) return this
|
|
||||||
return if (isSuspend) context.suspendFunctionViews.getOrPut(this) { suspendFunctionView(context) } else this
|
return if (isSuspend) context.suspendFunctionViews.getOrPut(this) { suspendFunctionView(context) } else this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private object SUSPEND_FUNCTION_VIEW : IrDeclarationOriginImpl("SUSPEND_FUNCTION_VIEW")
|
||||||
|
|
||||||
private fun IrFunction.suspendFunctionView(context: JvmBackendContext): IrFunction {
|
private fun IrFunction.suspendFunctionView(context: JvmBackendContext): IrFunction {
|
||||||
require(this.isSuspend && this is IrSimpleFunction)
|
require(this.isSuspend && this is IrSimpleFunction)
|
||||||
val originalDescriptor = this.descriptor
|
val originalDescriptor = this.descriptor
|
||||||
@@ -121,7 +120,7 @@ private fun IrFunction.suspendFunctionView(context: JvmBackendContext): IrFuncti
|
|||||||
else
|
else
|
||||||
WrappedSimpleFunctionDescriptor(sourceElement = originalDescriptor.source)
|
WrappedSimpleFunctionDescriptor(sourceElement = originalDescriptor.source)
|
||||||
return IrFunctionImpl(
|
return IrFunctionImpl(
|
||||||
startOffset, endOffset, origin, IrSimpleFunctionSymbolImpl(descriptor),
|
startOffset, endOffset, SUSPEND_FUNCTION_VIEW, IrSimpleFunctionSymbolImpl(descriptor),
|
||||||
name, visibility, modality, context.irBuiltIns.anyNType,
|
name, visibility, modality, context.irBuiltIns.anyNType,
|
||||||
isInline, isExternal, isTailrec, isSuspend
|
isInline, isExternal, isTailrec, isSuspend
|
||||||
).also {
|
).also {
|
||||||
@@ -134,11 +133,8 @@ private fun IrFunction.suspendFunctionView(context: JvmBackendContext): IrFuncti
|
|||||||
|
|
||||||
valueParameters.mapTo(it.valueParameters) { p -> p.copyTo(it) }
|
valueParameters.mapTo(it.valueParameters) { p -> p.copyTo(it) }
|
||||||
it.addValueParameter(
|
it.addValueParameter(
|
||||||
SUSPEND_FUNCTION_COMPLETION_PARAMETER_NAME, context.getTopLevelClass(
|
SUSPEND_FUNCTION_COMPLETION_PARAMETER_NAME, context.ir.symbols.continuationClass
|
||||||
context.state.languageVersionSettings.coroutinesPackageFqName().child(
|
.createType(false, listOf(makeTypeProjection(returnType, Variance.INVARIANT)))
|
||||||
Name.identifier("Continuation")
|
|
||||||
)
|
|
||||||
).createType(false, listOf(makeTypeProjection(returnType, Variance.INVARIANT)))
|
|
||||||
)
|
)
|
||||||
val valueParametersMapping = explicitParameters.zip(it.explicitParameters).toMap()
|
val valueParametersMapping = explicitParameters.zip(it.explicitParameters).toMap()
|
||||||
it.body = body?.deepCopyWithSymbols(this)
|
it.body = body?.deepCopyWithSymbols(this)
|
||||||
@@ -150,19 +146,20 @@ private fun IrFunction.suspendFunctionView(context: JvmBackendContext): IrFuncti
|
|||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
if (!expression.isSuspend) return super.visitCall(expression)
|
if (!expression.isSuspend) return super.visitCall(expression)
|
||||||
return super.visitCall(expression.createView(context, it))
|
return super.visitCall(expression.createSuspendFunctionCallViewIfNeeded(context, it))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun IrCall.createView(context: JvmBackendContext, caller: IrFunction): IrCall {
|
internal fun IrCall.createSuspendFunctionCallViewIfNeeded(context: JvmBackendContext, caller: IrFunction): IrCall {
|
||||||
if (!isSuspend) return this
|
if (!isSuspend) return this
|
||||||
val view = (symbol.owner as IrSimpleFunction).getOrCreateSuspendFunctionViewIfNeeded(context)
|
val view = (symbol.owner as IrSimpleFunction).getOrCreateSuspendFunctionViewIfNeeded(context)
|
||||||
if (view == symbol.owner) return this
|
if (view == symbol.owner) return this
|
||||||
return IrCallImpl(startOffset, endOffset, view.returnType, view.symbol).also {
|
return IrCallImpl(startOffset, endOffset, view.returnType, view.symbol).also {
|
||||||
it.copyTypeArgumentsFrom(this)
|
it.copyTypeArgumentsFrom(this)
|
||||||
it.dispatchReceiver = dispatchReceiver
|
it.dispatchReceiver = dispatchReceiver
|
||||||
|
it.extensionReceiver = extensionReceiver
|
||||||
for (i in 0 until valueArgumentsCount) {
|
for (i in 0 until valueArgumentsCount) {
|
||||||
it.putValueArgument(i, getValueArgument(i))
|
it.putValueArgument(i, getValueArgument(i))
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-2
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.codegen.AsmUtil.*
|
|||||||
import org.jetbrains.kotlin.codegen.BaseExpressionCodegen
|
import org.jetbrains.kotlin.codegen.BaseExpressionCodegen
|
||||||
import org.jetbrains.kotlin.codegen.CallGenerator
|
import org.jetbrains.kotlin.codegen.CallGenerator
|
||||||
import org.jetbrains.kotlin.codegen.StackValue
|
import org.jetbrains.kotlin.codegen.StackValue
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME
|
|
||||||
import org.jetbrains.kotlin.codegen.extractReificationArgument
|
import org.jetbrains.kotlin.codegen.extractReificationArgument
|
||||||
import org.jetbrains.kotlin.codegen.inline.*
|
import org.jetbrains.kotlin.codegen.inline.*
|
||||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.Companion.putNeedClassReificationMarker
|
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.Companion.putNeedClassReificationMarker
|
||||||
@@ -297,8 +296,11 @@ class ExpressionCodegen(
|
|||||||
override fun visitContainerExpression(expression: IrContainerExpression, data: BlockInfo) =
|
override fun visitContainerExpression(expression: IrContainerExpression, data: BlockInfo) =
|
||||||
visitStatementContainer(expression, data).coerce(expression.type)
|
visitStatementContainer(expression, data).coerce(expression.type)
|
||||||
|
|
||||||
|
override fun visitCall(expression: IrCall, data: BlockInfo): PromisedValue {
|
||||||
|
return visitFunctionAccess(expression.createSuspendFunctionCallViewIfNeeded(context, irFunction), data)
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitFunctionAccess(expression: IrFunctionAccessExpression, data: BlockInfo): PromisedValue {
|
override fun visitFunctionAccess(expression: IrFunctionAccessExpression, data: BlockInfo): PromisedValue {
|
||||||
val expression = if (expression is IrCall) expression.createView(context, irFunction) else expression
|
|
||||||
classCodegen.context.irIntrinsics.getIntrinsic(expression.symbol)
|
classCodegen.context.irIntrinsics.getIntrinsic(expression.symbol)
|
||||||
?.invoke(expression, this, data)?.let { return it.coerce(expression.type) }
|
?.invoke(expression, this, data)?.let { return it.coerce(expression.type) }
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -84,7 +84,7 @@ open class FunctionCodegen(
|
|||||||
methodVisitor = when {
|
methodVisitor = when {
|
||||||
irFunction.isSuspend &&
|
irFunction.isSuspend &&
|
||||||
// We do not generate continuation and state-machine for synthetic accessors, in a sense, they are tail-call
|
// We do not generate continuation and state-machine for synthetic accessors, in a sense, they are tail-call
|
||||||
!irFunction.isDefault() &&
|
!irFunction.isKnownToBeTailCall() &&
|
||||||
// TODO: We should generate two versions of inline suspend function: one with state-machine and one without
|
// TODO: We should generate two versions of inline suspend function: one with state-machine and one without
|
||||||
!irFunction.isInline ->
|
!irFunction.isInline ->
|
||||||
generateStateMachineForNamedFunction(
|
generateStateMachineForNamedFunction(
|
||||||
@@ -104,7 +104,7 @@ open class FunctionCodegen(
|
|||||||
return signature
|
return signature
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrFunction.isDefault(): Boolean =
|
private fun IrFunction.isKnownToBeTailCall(): Boolean =
|
||||||
origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER || origin == JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
|
origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER || origin == JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
|
||||||
|
|
||||||
private fun calculateMethodFlags(isStatic: Boolean): Int {
|
private fun calculateMethodFlags(isStatic: Boolean): Int {
|
||||||
|
|||||||
+5
-1
@@ -88,8 +88,12 @@ fun PromisedValue.coerce(target: Type, irTarget: IrType): PromisedValue {
|
|||||||
val isFromTypeInlineClass = erasedSourceType.classOrNull!!.owner.isInline
|
val isFromTypeInlineClass = erasedSourceType.classOrNull!!.owner.isInline
|
||||||
val isToTypeInlineClass = erasedTargetType.classOrNull!!.owner.isInline
|
val isToTypeInlineClass = erasedTargetType.classOrNull!!.owner.isInline
|
||||||
|
|
||||||
|
// Boxing and unboxing kotlin.Result leads to CCE in generated code
|
||||||
|
val doNotCoerceKotlinResultInContinuation =
|
||||||
|
codegen.irFunction.isInvokeSuspendOfContinuation(codegen.context) && (irType.isKotlinResult() || irTarget.isKotlinResult())
|
||||||
|
|
||||||
// Coerce inline classes
|
// Coerce inline classes
|
||||||
if (isFromTypeInlineClass || isToTypeInlineClass) {
|
if ((isFromTypeInlineClass || isToTypeInlineClass) && !doNotCoerceKotlinResultInContinuation) {
|
||||||
val isFromTypeUnboxed = isFromTypeInlineClass && typeMapper.mapType(erasedSourceType.unboxed) == type
|
val isFromTypeUnboxed = isFromTypeInlineClass && typeMapper.mapType(erasedSourceType.unboxed) == type
|
||||||
val isToTypeUnboxed = isToTypeInlineClass && typeMapper.mapType(erasedTargetType.unboxed) == target
|
val isToTypeUnboxed = isToTypeInlineClass && typeMapper.mapType(erasedTargetType.unboxed) == target
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -155,7 +155,7 @@ private class SyntheticAccessorLowering(val context: JvmBackendContext) : IrElem
|
|||||||
origin = JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
|
origin = JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
|
||||||
name = source.accessorName()
|
name = source.accessorName()
|
||||||
visibility = Visibilities.PUBLIC
|
visibility = Visibilities.PUBLIC
|
||||||
isSuspend = this@makeSimpleFunctionAccessor.isSuspend // synthetic accessors of suspend functions are handled in codegen
|
isSuspend = source.isSuspend // synthetic accessors of suspend functions are handled in codegen
|
||||||
}.also { accessor ->
|
}.also { accessor ->
|
||||||
// Find the right container to insert the accessor. Simply put, when we call a function on a class A,
|
// Find the right container to insert the accessor. Simply put, when we call a function on a class A,
|
||||||
// we also need to put its accessor into A. However, due to the way that calls are implemented in the
|
// we also need to put its accessor into A. However, due to the way that calls are implemented in the
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JS_IR
|
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// WITH_REFLECT
|
// WITH_REFLECT
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
@@ -31,5 +29,5 @@ fun box(): String {
|
|||||||
result = A<String>().bar()
|
result = A<String>().bar()
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (result == "Continuation at test.A.bar(coroutineToString.kt:16)") "OK" else "Fail: $result"
|
return if (result == "Continuation at test.A.bar(coroutineToString.kt:14)") "OK" else "Fail: $result"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// COMMON_COROUTINES_TEST
|
// COMMON_COROUTINES_TEST
|
||||||
|
|||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
// KJS_WITH_FULL_RUNTIME
|
// KJS_WITH_FULL_RUNTIME
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// COMMON_COROUTINES_TEST
|
// COMMON_COROUTINES_TEST
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// COMMON_COROUTINES_TEST
|
// COMMON_COROUTINES_TEST
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// COMMON_COROUTINES_TEST
|
// COMMON_COROUTINES_TEST
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// COMMON_COROUTINES_TEST
|
// COMMON_COROUTINES_TEST
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// COMMON_COROUTINES_TEST
|
// COMMON_COROUTINES_TEST
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// IGNORE_BACKEND: NATIVE
|
// IGNORE_BACKEND: NATIVE
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// COMMON_COROUTINES_TEST
|
// COMMON_COROUTINES_TEST
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// COMMON_COROUTINES_TEST
|
// COMMON_COROUTINES_TEST
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// COMMON_COROUTINES_TEST
|
// COMMON_COROUTINES_TEST
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// COMMON_COROUTINES_TEST
|
// COMMON_COROUTINES_TEST
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// COMMON_COROUTINES_TEST
|
// COMMON_COROUTINES_TEST
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// FULL_JDK
|
// FULL_JDK
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// KJS_WITH_FULL_RUNTIME
|
// KJS_WITH_FULL_RUNTIME
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// COMMON_COROUTINES_TEST
|
// COMMON_COROUTINES_TEST
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// COMMON_COROUTINES_TEST
|
// COMMON_COROUTINES_TEST
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// COMMON_COROUTINES_TEST
|
// COMMON_COROUTINES_TEST
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// COMMON_COROUTINES_TEST
|
// COMMON_COROUTINES_TEST
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// COMMON_COROUTINES_TEST
|
// COMMON_COROUTINES_TEST
|
||||||
|
|||||||
Reference in New Issue
Block a user