diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index afeee9f266b..dd2a4f9e2ae 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -52,7 +52,6 @@ import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor; import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.lexer.KtTokens; import org.jetbrains.kotlin.load.java.JvmAbi; -import org.jetbrains.kotlin.resolve.sam.SamConstructorDescriptor; import org.jetbrains.kotlin.load.kotlin.MethodSignatureMappingKt; import org.jetbrains.kotlin.load.kotlin.TypeSignatureMappingKt; import org.jetbrains.kotlin.name.Name; @@ -77,6 +76,7 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt; import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind; import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature; import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature; +import org.jetbrains.kotlin.resolve.sam.SamConstructorDescriptor; import org.jetbrains.kotlin.resolve.scopes.receivers.*; import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor; import org.jetbrains.kotlin.types.*; diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt index 678ac129a65..214422705d5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.codegen.coroutines import com.intellij.util.ArrayUtil import org.jetbrains.kotlin.backend.common.CodegenUtil import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype +import org.jetbrains.kotlin.cfg.index import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.binding.CalculatedClosure import org.jetbrains.kotlin.codegen.binding.CodegenBinding @@ -22,6 +23,7 @@ import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.isReleaseCoroutines import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.incremental.components.NoLookupLocation @@ -229,6 +231,7 @@ class CoroutineCodegenForLambda private constructor( override fun generateClosureBody() { for (parameter in allFunctionParameters()) { + if (parameter.isUnused()) continue val fieldInfo = parameter.getFieldInfoForCoroutineLambdaParameter() v.newField( OtherOrigin(parameter), @@ -241,6 +244,10 @@ class CoroutineCodegenForLambda private constructor( generateResumeImpl() } + private fun ParameterDescriptor.isUnused(): Boolean = + originalSuspendFunctionDescriptor is AnonymousFunctionDescriptor && + bindingContext[BindingContext.SUSPEND_LAMBDA_PARAMETER_USED, originalSuspendFunctionDescriptor to index()] != true + private val generateErasedCreate: Boolean = allFunctionParameters().size <= 1 private val doNotGenerateInvokeBridge: Boolean = !originalSuspendFunctionDescriptor.isLocalSuspendFunctionNotSuspendLambda() @@ -398,39 +405,41 @@ class CoroutineCodegenForLambda private constructor( var index = 1 for (parameter in allFunctionParameters()) { val fieldInfoForCoroutineLambdaParameter = parameter.getFieldInfoForCoroutineLambdaParameter() - if (isBigArity) { - load(cloneIndex, fieldInfoForCoroutineLambdaParameter.ownerType) - load(1, AsmTypes.OBJECT_TYPE) - iconst(index - 1) - aload(AsmTypes.OBJECT_TYPE) - StackValue.coerce( - AsmTypes.OBJECT_TYPE, builtIns.nullableAnyType, - fieldInfoForCoroutineLambdaParameter.fieldType, fieldInfoForCoroutineLambdaParameter.fieldKotlinType, - this - ) - putfield( - fieldInfoForCoroutineLambdaParameter.ownerInternalName, - fieldInfoForCoroutineLambdaParameter.fieldName, - fieldInfoForCoroutineLambdaParameter.fieldType.descriptor - ) - } else { - if (generateErasedCreate) { - load(index, AsmTypes.OBJECT_TYPE) + if (!parameter.isUnused()) { + if (isBigArity) { + load(cloneIndex, fieldInfoForCoroutineLambdaParameter.ownerType) + load(1, AsmTypes.OBJECT_TYPE) + iconst(index - 1) + aload(AsmTypes.OBJECT_TYPE) StackValue.coerce( AsmTypes.OBJECT_TYPE, builtIns.nullableAnyType, fieldInfoForCoroutineLambdaParameter.fieldType, fieldInfoForCoroutineLambdaParameter.fieldKotlinType, this ) + putfield( + fieldInfoForCoroutineLambdaParameter.ownerInternalName, + fieldInfoForCoroutineLambdaParameter.fieldName, + fieldInfoForCoroutineLambdaParameter.fieldType.descriptor + ) } else { - load(index, fieldInfoForCoroutineLambdaParameter.fieldType) + if (generateErasedCreate) { + load(index, AsmTypes.OBJECT_TYPE) + StackValue.coerce( + AsmTypes.OBJECT_TYPE, builtIns.nullableAnyType, + fieldInfoForCoroutineLambdaParameter.fieldType, fieldInfoForCoroutineLambdaParameter.fieldKotlinType, + this + ) + } else { + load(index, fieldInfoForCoroutineLambdaParameter.fieldType) + } + AsmUtil.genAssignInstanceFieldFromParam( + fieldInfoForCoroutineLambdaParameter, + index, + this, + cloneIndex, + generateErasedCreate + ) } - AsmUtil.genAssignInstanceFieldFromParam( - fieldInfoForCoroutineLambdaParameter, - index, - this, - cloneIndex, - generateErasedCreate - ) } index += if (isBigArity || generateErasedCreate) 1 else fieldInfoForCoroutineLambdaParameter.fieldType.size } @@ -442,6 +451,7 @@ class CoroutineCodegenForLambda private constructor( private fun ExpressionCodegen.initializeCoroutineParameters() { for (parameter in allFunctionParameters()) { + if (parameter.isUnused()) continue val fieldStackValue = StackValue.field( parameter.getFieldInfoForCoroutineLambdaParameter(), generateThisOrOuter(context.thisDescriptor, false) @@ -463,7 +473,11 @@ class CoroutineCodegenForLambda private constructor( v.visitLocalVariable(name, mappedType.descriptor, null, label, endLabel, newIndex) } - initializeVariablesForDestructuredLambdaParameters(this, originalSuspendFunctionDescriptor.valueParameters, endLabel) + initializeVariablesForDestructuredLambdaParameters( + this, + originalSuspendFunctionDescriptor.valueParameters.filter { !it.isUnused() }, + endLabel + ) } private fun allFunctionParameters(): List = diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt index 7f02b9803c1..2ee0695719d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitor import org.jetbrains.kotlin.cfg.pseudocode.instructions.KtElementInstruction import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.* import org.jetbrains.kotlin.cfg.pseudocode.instructions.jumps.* +import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.LocalFunctionDeclarationInstruction import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.MarkInstruction import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.VariableDeclarationInstruction import org.jetbrains.kotlin.cfg.pseudocode.sideEffectFree @@ -24,6 +25,8 @@ import org.jetbrains.kotlin.cfg.variable.VariableUseState.* import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor +import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.DiagnosticFactory import org.jetbrains.kotlin.diagnostics.Errors @@ -43,7 +46,9 @@ import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsResultOfLambda import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall +import org.jetbrains.kotlin.resolve.calls.checkers.findDestructuredVariable import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getDispatchReceiverWithSmartCast import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.hasThisOrNoDispatchReceiver import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject @@ -51,6 +56,7 @@ import org.jetbrains.kotlin.resolve.calls.util.isSingleUnderscore import org.jetbrains.kotlin.resolve.checkers.PlatformDiagnosticSuppressor import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils.* import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils @@ -101,6 +107,8 @@ class ControlFlowInformationProvider private constructor( markUnusedVariables() } + checkForSuspendLambdaAndMarkParameters(pseudocode) + markStatements() markAnnotationArguments() @@ -808,6 +816,88 @@ class ControlFlowInformationProvider private constructor( } } + private fun checkForSuspendLambdaAndMarkParameters(pseudocode: Pseudocode) { + for (instruction in pseudocode.instructionsIncludingDeadCode) { + if (instruction is LocalFunctionDeclarationInstruction) { + val psi = instruction.body.correspondingElement + if (psi is KtFunctionLiteral) { + val descriptor = trace.bindingContext[DECLARATION_TO_DESCRIPTOR, psi] + if (descriptor is AnonymousFunctionDescriptor && descriptor.isSuspend) { + markReadOfSuspendLambdaParameters(instruction.body) + continue + } + } + checkForSuspendLambdaAndMarkParameters(instruction.body) + } + } + } + + private fun markReadOfSuspendLambdaParameters(pseudocode: Pseudocode) { + val instructions = pseudocode.instructionsIncludingDeadCode + for (instruction in instructions) { + if (instruction is LocalFunctionDeclarationInstruction) { + markReadOfSuspendLambdaParameters(instruction.body) + continue + } + markReadOfSuspendLambdaParameter(instruction) + markImplicitReceiverOfSuspendLambda(instruction) + } + } + + private fun markReadOfSuspendLambdaParameter(instruction: Instruction) { + if (instruction !is ReadValueInstruction) return + val target = instruction.target as? AccessTarget.Call ?: return + val descriptor = target.resolvedCall.resultingDescriptor + if (descriptor is ParameterDescriptor) { + val containing = descriptor.containingDeclaration + if (containing is AnonymousFunctionDescriptor && containing.isSuspend) { + trace.record(SUSPEND_LAMBDA_PARAMETER_USED, containing to descriptor.index()) + } + } else if (descriptor is LocalVariableDescriptor) { + val containing = descriptor.containingDeclaration + if (containing is AnonymousFunctionDescriptor && containing.isSuspend) { + findDestructuredVariable(descriptor, containing)?.let { + trace.record(SUSPEND_LAMBDA_PARAMETER_USED, containing to it.index) + } + } + } + } + + private fun markImplicitReceiverOfSuspendLambda(instruction: Instruction) { + if (instruction !is MagicInstruction || instruction.kind != MagicKind.IMPLICIT_RECEIVER) return + + fun CallableDescriptor?.markIfNeeded() { + if (this is AnonymousFunctionDescriptor && isSuspend) { + trace.record(SUSPEND_LAMBDA_PARAMETER_USED, this to -1) + } + } + + if (instruction.element is KtDestructuringDeclarationEntry || instruction.element is KtCallExpression) { + val visited = mutableSetOf() + fun dfs(insn: Instruction) { + if (!visited.add(insn)) return + if (insn is CallInstruction && insn.element == instruction.element) { + for ((_, receiver) in insn.receiverValues) { + (receiver as? ExtensionReceiver)?.declarationDescriptor?.apply { markIfNeeded() } + } + } + for (next in insn.nextInstructions) { + dfs(next) + } + } + + instruction.next?.let { dfs(it) } + } else if (instruction.element is KtNameReferenceExpression) { + val call = instruction.element.getResolvedCall(trace.bindingContext) + if (call is VariableAsFunctionResolvedCall) { + (call.variableCall.dispatchReceiver as? ExtensionReceiver)?.declarationDescriptor?.apply { markIfNeeded() } + (call.variableCall.extensionReceiver as? ExtensionReceiver)?.declarationDescriptor?.apply { markIfNeeded() } + } + (call?.dispatchReceiver as? ExtensionReceiver)?.declarationDescriptor?.apply { markIfNeeded() } + (call?.extensionReceiver as? ExtensionReceiver)?.declarationDescriptor?.apply { markIfNeeded() } + } + } + private fun markAnnotationArguments() { if (subroutine is KtAnnotationEntry) { markAnnotationArguments(subroutine) @@ -1219,3 +1309,10 @@ class ControlFlowInformationProvider private constructor( || diagnosticFactory === UNUSED_CHANGED_VALUE } } + +fun ParameterDescriptor.index(): Int = + when (this) { + is ReceiverParameterDescriptor -> -1 + is ValueParameterDescriptor -> index + else -> error("expected either receiver or value parameter, but got: $this") + } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java index a1a012372e9..fc3fc31dda4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.resolve; import com.google.common.collect.ImmutableMap; import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; +import kotlin.Pair; import kotlin.annotations.jvm.ReadOnly; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -18,13 +19,13 @@ import org.jetbrains.kotlin.contracts.description.InvocationKind; import org.jetbrains.kotlin.contracts.model.Computation; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.FqNameUnsafe; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext; import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemCompleter; import org.jetbrains.kotlin.resolve.calls.model.PartialCallContainer; -import org.jetbrains.kotlin.resolve.calls.model.PartialCallResolutionResult; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue; @@ -169,6 +170,8 @@ public interface BindingContext { WritableSlice VARIABLE_REASSIGNMENT = Slices.createSimpleSetSlice(); WritableSlice AUTO_CREATED_IT = Slices.createSimpleSetSlice(); + WritableSlice, Boolean> SUSPEND_LAMBDA_PARAMETER_USED = Slices.createSimpleSlice(); + /** * Has type of current expression has been already resolved */ diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CapturingInClosureChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CapturingInClosureChecker.kt index 07076e88012..5bd166ff038 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CapturingInClosureChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CapturingInClosureChecker.kt @@ -103,7 +103,7 @@ class CapturingInClosureChecker : CallChecker { // We cannot box function/lambda arguments, destructured lambda arguments, for-loop index variables, // exceptions inside catch blocks ans vals in when return if (isArgument(variable, variableParent) || - isDestructuredVariable(variable, variableParent) || + findDestructuredVariable(variable, variableParent) != null || isForLoopParameter(variable) || isCatchBlockParameter(variable) || isValInWhen(variable) @@ -118,12 +118,6 @@ class CapturingInClosureChecker : CallChecker { variable is ValueParameterDescriptor && variableParent is CallableDescriptor && variableParent.valueParameters.contains(variable) - private fun isDestructuredVariable(variable: VariableDescriptor, variableParent: DeclarationDescriptor): Boolean = - variable is LocalVariableDescriptor && variableParent is AnonymousFunctionDescriptor && - variableParent.valueParameters.any { - it is ValueParameterDescriptorImpl.WithDestructuringDeclaration && it.destructuringVariables.contains(variable) - } - private fun isValInWhen(variable: VariableDescriptor): Boolean { val psi = ((variable as? LocalVariableDescriptor)?.source as? KotlinSourceElement)?.psi ?: return false return (psi.parent as? KtWhenExpression)?.let { it.subjectVariable == psi } == true @@ -178,3 +172,10 @@ class CapturingInClosureChecker : CallChecker { return getCalleeDescriptorAndParameter(bindingContext, argument)?.second?.isCrossinline == true } } + +fun findDestructuredVariable(variable: VariableDescriptor, variableParent: DeclarationDescriptor): ValueParameterDescriptor? = + if (variable is LocalVariableDescriptor && variableParent is AnonymousFunctionDescriptor) { + variableParent.valueParameters.find { + it is ValueParameterDescriptorImpl.WithDestructuringDeclaration && it.destructuringVariables.contains(variable) + } + } else null diff --git a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/parameters.kt b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/parameters.kt index 895f6f67ae2..3572a208fe1 100644 --- a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/parameters.kt +++ b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/parameters.kt @@ -3,7 +3,7 @@ data class Data(val x: String, val y: Int, val z: Int = 0) suspend fun test() { foo(Data("A", 1)) { str, (x, _, z), i -> - + println(str + x + z + i + this) } } diff --git a/compiler/testData/codegen/bytecodeListing/coroutines/spilling/component1.kt b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/component1.kt new file mode 100644 index 00000000000..75b79a6bd7a --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/component1.kt @@ -0,0 +1,20 @@ +// WITH_RUNTIME +// IGNORE_BACKEND: JVM_IR + +interface Result + +interface Foo { + suspend operator fun Result.component1(): Any = TODO() +} + +fun use(c: suspend Foo.() -> Unit) {} + +fun generate(): Result = TODO() + +fun test() { + use { + // This component1 accesses both dispatch and extension receivers, + // So, there should be p$ + val (value) = generate() + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/coroutines/spilling/component1.txt b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/component1.txt new file mode 100644 index 00000000000..0119307234f --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/component1.txt @@ -0,0 +1,35 @@ +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class Component1Kt$test$1 { + field L$0: java.lang.Object + field label: int + private field p$: Foo + inner class Component1Kt$test$1 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.Metadata +public final class Component1Kt { + inner class Component1Kt$test$1 + public final static @org.jetbrains.annotations.NotNull method generate(): Result + public final static method test(): void + public final static method use(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2): void +} + +@kotlin.Metadata +public final class Foo$DefaultImpls { + inner class Foo$DefaultImpls + public static @org.jetbrains.annotations.Nullable method component1(p0: Foo, @org.jetbrains.annotations.NotNull p1: Result, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): java.lang.Object +} + +@kotlin.Metadata +public interface Foo { + inner class Foo$DefaultImpls + public abstract @org.jetbrains.annotations.Nullable method component1(@org.jetbrains.annotations.NotNull p0: Result, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object +} + +@kotlin.Metadata +public interface Result diff --git a/compiler/testData/codegen/bytecodeListing/coroutines/spilling/destructured.kt b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/destructured.kt new file mode 100644 index 00000000000..f7cfe6c6580 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/destructured.kt @@ -0,0 +1,20 @@ +// WITH_RUNTIME +// IGNORE_BACKEND: JVM_IR + +fun use(c: suspend (Pair) -> Unit) {} + +fun blackhole(a: Any) {} + +fun test() { + use { (a, b) -> + } + use { (a, b) -> + blackhole(a) + } + use { (a, b) -> + blackhole(b) + } + use { + blackhole(it) + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/coroutines/spilling/destructured.txt b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/destructured.txt new file mode 100644 index 00000000000..0c324279e4a --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/destructured.txt @@ -0,0 +1,57 @@ +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class DestructuredKt$test$1 { + field label: int + inner class DestructuredKt$test$1 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class DestructuredKt$test$2 { + field label: int + private field p$0: kotlin.Pair + inner class DestructuredKt$test$2 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class DestructuredKt$test$3 { + field label: int + private field p$0: kotlin.Pair + inner class DestructuredKt$test$3 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class DestructuredKt$test$4 { + field label: int + private field p$0: kotlin.Pair + inner class DestructuredKt$test$4 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.Metadata +public final class DestructuredKt { + inner class DestructuredKt$test$1 + inner class DestructuredKt$test$2 + inner class DestructuredKt$test$3 + inner class DestructuredKt$test$4 + public final static method blackhole(@org.jetbrains.annotations.NotNull p0: java.lang.Object): void + public final static method test(): void + public final static method use(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2): void +} diff --git a/compiler/testData/codegen/bytecodeListing/coroutines/spilling/field.kt b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/field.kt new file mode 100644 index 00000000000..8379fd24a4b --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/field.kt @@ -0,0 +1,19 @@ +// WITH_RUNTIME +// IGNORE_BACKEND: JVM_IR + +interface Result + +interface Foo { + val Result.value: Any + get() = TODO() +} + +fun use(c: suspend Foo.() -> Unit) {} + +fun generate(): Result = TODO() + +fun test() { + use { + val value = generate().value + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/coroutines/spilling/field.txt b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/field.txt new file mode 100644 index 00000000000..677d04086cf --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/field.txt @@ -0,0 +1,34 @@ +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class FieldKt$test$1 { + field label: int + private field p$: Foo + inner class FieldKt$test$1 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.Metadata +public final class FieldKt { + inner class FieldKt$test$1 + public final static @org.jetbrains.annotations.NotNull method generate(): Result + public final static method test(): void + public final static method use(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2): void +} + +@kotlin.Metadata +public final class Foo$DefaultImpls { + inner class Foo$DefaultImpls + public static @org.jetbrains.annotations.NotNull method getValue(p0: Foo, @org.jetbrains.annotations.NotNull p1: Result): java.lang.Object +} + +@kotlin.Metadata +public interface Foo { + inner class Foo$DefaultImpls + public abstract @org.jetbrains.annotations.NotNull method getValue(@org.jetbrains.annotations.NotNull p0: Result): java.lang.Object +} + +@kotlin.Metadata +public interface Result diff --git a/compiler/testData/codegen/bytecodeListing/coroutines/spilling/lambda.kt b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/lambda.kt new file mode 100644 index 00000000000..dfe3b533dcf --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/lambda.kt @@ -0,0 +1,74 @@ +// WITH_RUNTIME +// IGNORE_BACKEND: JVM_IR + +fun use2(c: suspend Long.(Double, String) -> Unit) {} +fun use(c: suspend Long.(String) -> Unit) {} + +fun blackhole(a: Any) {} + +fun test() { + // test$1: p$0, p$1 + use2 { a, b -> + blackhole(b + a) + } + // test$2: p$0 + use2 { a, b -> + blackhole(a) + } + // test$3: p$1 + use2 { a, b -> + blackhole(b) + } + // test$4: p$0 + use2 { a, _ -> + blackhole(a) + } + // test$5: p$1 + use2 { _, b -> + blackhole(b) + } + // test$6: p$, p$0, p$1 + use2 { a, b -> + blackhole(b + a + this) + } + // test$7: p$, p$0 + use2 { a, b -> + blackhole(a + this.toDouble()) + } + // test$8: p$, p$1 + use2 { a, b -> + blackhole(b + this) + } + // test$9: p$, p$0 + use2 { a, _ -> + blackhole(a + this.toDouble()) + } + // test$10: p$, p$1 + use2 { _, b -> + blackhole(b + this) + } + // test$11: p$ + use2 { _, _ -> + blackhole(this) + } + // test$12: + use2 { _, _ -> } + // test$13: p$, p$0 + use { + blackhole(it + this) + } + // test$14: p$ + use { + blackhole(this) + } + // test$15: p$0 + use { + blackhole(it) + } + // test$16: + use {} + // test$17: p$ + use { + blackhole(toString()) + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/coroutines/spilling/lambda.txt b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/lambda.txt new file mode 100644 index 00000000000..f1c07667b1b --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/lambda.txt @@ -0,0 +1,234 @@ +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class LambdaKt$test$1 { + field label: int + private field p$0: double + private field p$1: java.lang.String + inner class LambdaKt$test$1 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class LambdaKt$test$10 { + field label: int + private field p$1: java.lang.String + private field p$: long + inner class LambdaKt$test$10 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class LambdaKt$test$11 { + field label: int + private field p$: long + inner class LambdaKt$test$11 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class LambdaKt$test$12 { + field label: int + inner class LambdaKt$test$12 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class LambdaKt$test$13 { + field label: int + private field p$0: java.lang.String + private field p$: long + inner class LambdaKt$test$13 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(p0: long, @org.jetbrains.annotations.NotNull p1: java.lang.String, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class LambdaKt$test$14 { + field label: int + private field p$: long + inner class LambdaKt$test$14 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(p0: long, @org.jetbrains.annotations.NotNull p1: java.lang.String, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class LambdaKt$test$15 { + field label: int + private field p$0: java.lang.String + inner class LambdaKt$test$15 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(p0: long, @org.jetbrains.annotations.NotNull p1: java.lang.String, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class LambdaKt$test$16 { + field label: int + inner class LambdaKt$test$16 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(p0: long, @org.jetbrains.annotations.NotNull p1: java.lang.String, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class LambdaKt$test$17 { + field label: int + private field p$: long + inner class LambdaKt$test$17 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(p0: long, @org.jetbrains.annotations.NotNull p1: java.lang.String, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class LambdaKt$test$2 { + field label: int + private field p$0: double + inner class LambdaKt$test$2 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class LambdaKt$test$3 { + field label: int + private field p$1: java.lang.String + inner class LambdaKt$test$3 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class LambdaKt$test$4 { + field label: int + private field p$0: double + inner class LambdaKt$test$4 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class LambdaKt$test$5 { + field label: int + private field p$1: java.lang.String + inner class LambdaKt$test$5 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class LambdaKt$test$6 { + field label: int + private field p$0: double + private field p$1: java.lang.String + private field p$: long + inner class LambdaKt$test$6 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class LambdaKt$test$7 { + field label: int + private field p$0: double + private field p$: long + inner class LambdaKt$test$7 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class LambdaKt$test$8 { + field label: int + private field p$1: java.lang.String + private field p$: long + inner class LambdaKt$test$8 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class LambdaKt$test$9 { + field label: int + private field p$0: double + private field p$: long + inner class LambdaKt$test$9 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.Metadata +public final class LambdaKt { + inner class LambdaKt$test$1 + inner class LambdaKt$test$10 + inner class LambdaKt$test$11 + inner class LambdaKt$test$12 + inner class LambdaKt$test$13 + inner class LambdaKt$test$14 + inner class LambdaKt$test$15 + inner class LambdaKt$test$16 + inner class LambdaKt$test$17 + inner class LambdaKt$test$2 + inner class LambdaKt$test$3 + inner class LambdaKt$test$4 + inner class LambdaKt$test$5 + inner class LambdaKt$test$6 + inner class LambdaKt$test$7 + inner class LambdaKt$test$8 + inner class LambdaKt$test$9 + public final static method blackhole(@org.jetbrains.annotations.NotNull p0: java.lang.Object): void + public final static method test(): void + public final static method use(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function3): void + public final static method use2(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function4): void +} diff --git a/compiler/testData/codegen/bytecodeListing/coroutines/spilling/select.kt b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/select.kt new file mode 100644 index 00000000000..e46e66595ba --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/select.kt @@ -0,0 +1,34 @@ +// WITH_RUNTIME +// IGNORE_BACKEND: JVM_IR + +import kotlin.coroutines.* +import kotlin.experimental.* + +interface CoroutineScope + +@OptIn(ExperimentalTypeInference::class) +public fun CoroutineScope.produce( + @BuilderInference block: suspend ProducerScope.() -> Unit +): ReceiveChannel = TODO() + +interface ProducerScope : CoroutineScope, SendChannel { + public val channel: SendChannel +} + +interface ReceiveChannel +interface SelectBuilder { + operator fun SelectClause2.invoke(param: P, block: suspend (Q) -> R) +} +interface SelectClause2 +interface SendChannel { + val onSend: SelectClause2> +} +suspend inline fun select(crossinline builder: SelectBuilder.() -> Unit): R { + TODO() +} + +fun CoroutineScope.produceNumbers(side: SendChannel) = produce { + select { + onSend(1) {} + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/coroutines/spilling/select.txt b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/select.txt new file mode 100644 index 00000000000..18976202db7 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/select.txt @@ -0,0 +1,55 @@ +@kotlin.Metadata +public interface CoroutineScope + +@kotlin.Metadata +public interface ProducerScope { + public abstract @org.jetbrains.annotations.NotNull method getChannel(): SendChannel +} + +@kotlin.Metadata +public interface ReceiveChannel + +@kotlin.Metadata +public interface SelectBuilder { + public abstract method invoke(@org.jetbrains.annotations.NotNull p0: SelectClause2, p1: java.lang.Object, @org.jetbrains.annotations.NotNull p2: kotlin.jvm.functions.Function2): void +} + +@kotlin.Metadata +public interface SelectClause2 + +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class SelectKt$produceNumbers$1$1$1 { + field label: int + inner class SelectKt$produceNumbers$1$1$1 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class SelectKt$produceNumbers$1 { + field label: int + private field p$: ProducerScope + inner class SelectKt$produceNumbers$1 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.Metadata +public final class SelectKt { + inner class SelectKt$produceNumbers$1 + public final static @org.jetbrains.annotations.NotNull method produce(@org.jetbrains.annotations.NotNull p0: CoroutineScope, @kotlin.BuilderInference @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2): ReceiveChannel + public final static @org.jetbrains.annotations.NotNull method produceNumbers(@org.jetbrains.annotations.NotNull p0: CoroutineScope, @org.jetbrains.annotations.NotNull p1: SendChannel): ReceiveChannel + private final static @org.jetbrains.annotations.Nullable method select$$forInline(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object + public final static @org.jetbrains.annotations.Nullable method select(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object +} + +@kotlin.Metadata +public interface SendChannel { + public abstract @org.jetbrains.annotations.NotNull method getOnSend(): SelectClause2 +} diff --git a/compiler/testData/codegen/bytecodeListing/coroutines/spilling/unreachable.kt b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/unreachable.kt new file mode 100644 index 00000000000..fdc65e964a0 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/unreachable.kt @@ -0,0 +1,11 @@ +// WITH_RUNTIME +// IGNORE_BACKEND: JVM_IR + +fun use(c: suspend (String) -> Unit) {} + +fun test() { + use { + throw IllegalStateException("") + it + "" + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/coroutines/spilling/unreachable.txt b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/unreachable.txt new file mode 100644 index 00000000000..ac0f81379a9 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/coroutines/spilling/unreachable.txt @@ -0,0 +1,18 @@ +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class UnreachableKt$test$1 { + field label: int + private field p$0: java.lang.String + inner class UnreachableKt$test$1 + method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.Metadata +public final class UnreachableKt { + inner class UnreachableKt$test$1 + public final static method test(): void + public final static method use(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2): void +} diff --git a/compiler/testData/codegen/dumpDeclarations/suspendLambda.kt b/compiler/testData/codegen/dumpDeclarations/suspendLambda.kt index 86de557aa89..b046f00e2b9 100644 --- a/compiler/testData/codegen/dumpDeclarations/suspendLambda.kt +++ b/compiler/testData/codegen/dumpDeclarations/suspendLambda.kt @@ -1,6 +1,7 @@ // WITH_RUNTIME public fun invokeCoroutineBuilder() { return buildCoroutine { + println(this) } } diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java index cebfa826cf6..80f0c1a9587 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java @@ -300,6 +300,49 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { public void testTcoContinuation_1_3() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/bytecodeListing/coroutines/tcoContinuation.kt", "kotlin.coroutines"); } + + @TestMetadata("compiler/testData/codegen/bytecodeListing/coroutines/spilling") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Spilling extends AbstractBytecodeListingTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInSpilling() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeListing/coroutines/spilling"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("component1.kt") + public void testComponent1() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/coroutines/spilling/component1.kt"); + } + + @TestMetadata("destructured.kt") + public void testDestructured() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/coroutines/spilling/destructured.kt"); + } + + @TestMetadata("field.kt") + public void testField() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/coroutines/spilling/field.kt"); + } + + @TestMetadata("lambda.kt") + public void testLambda() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/coroutines/spilling/lambda.kt"); + } + + @TestMetadata("select.kt") + public void testSelect() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/coroutines/spilling/select.kt"); + } + + @TestMetadata("unreachable.kt") + public void testUnreachable() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/coroutines/spilling/unreachable.kt"); + } + } } @TestMetadata("compiler/testData/codegen/bytecodeListing/inline") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java index 9e8fcbe7642..16aaa5cacaa 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java @@ -270,6 +270,49 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes public void testTcoContinuation_1_3() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/bytecodeListing/coroutines/tcoContinuation.kt", "kotlin.coroutines"); } + + @TestMetadata("compiler/testData/codegen/bytecodeListing/coroutines/spilling") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Spilling extends AbstractIrBytecodeListingTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath); + } + + public void testAllFilesPresentInSpilling() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeListing/coroutines/spilling"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @TestMetadata("component1.kt") + public void testComponent1() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/coroutines/spilling/component1.kt"); + } + + @TestMetadata("destructured.kt") + public void testDestructured() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/coroutines/spilling/destructured.kt"); + } + + @TestMetadata("field.kt") + public void testField() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/coroutines/spilling/field.kt"); + } + + @TestMetadata("lambda.kt") + public void testLambda() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/coroutines/spilling/lambda.kt"); + } + + @TestMetadata("select.kt") + public void testSelect() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/coroutines/spilling/select.kt"); + } + + @TestMetadata("unreachable.kt") + public void testUnreachable() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/coroutines/spilling/unreachable.kt"); + } + } } @TestMetadata("compiler/testData/codegen/bytecodeListing/inline")