diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java index 3600998a642..a53515b4212 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java @@ -1247,6 +1247,11 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest { runTest("compiler/testData/ir/irText/expressions/stringTemplates.kt"); } + @TestMetadata("suspendConversionOnArbitraryExpression.kt") + public void testSuspendConversionOnArbitraryExpression() throws Exception { + runTest("compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.kt"); + } + @TestMetadata("temporaryInEnumEntryInitializer.kt") public void testTemporaryInEnumEntryInitializer() throws Exception { runTest("compiler/testData/ir/irText/expressions/temporaryInEnumEntryInitializer.kt"); diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt index 2a6f107e0f2..0426193b7a9 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt @@ -23,11 +23,22 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl +import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor +import org.jetbrains.kotlin.ir.descriptors.WrappedValueParameterDescriptor import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.isImmutable +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.psi.ValueArgument import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments import org.jetbrains.kotlin.psi2ir.intermediate.* @@ -45,6 +56,8 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeProjectionImpl import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.types.typeUtil.isUnit +import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.utils.addToStdlib.safeAs import kotlin.math.max import kotlin.math.min @@ -235,9 +248,10 @@ private fun StatementGenerator.generateReceiverForCalleeImportedFromObject( } } -fun StatementGenerator.generateVarargExpressionUsing( +private fun StatementGenerator.generateVarargExpressionUsing( varargArgument: VarargValueArgument, valueParameter: ValueParameterDescriptor, + resolvedCall: ResolvedCall<*>, // TODO resolvedCall is required for suspend conversions, see KT-38604 generateArgumentExpression: (KtExpression) -> IrExpression? ): IrExpression? { if (varargArgument.arguments.isEmpty()) { @@ -282,12 +296,14 @@ fun StatementGenerator.generateVarargExpressionUsing( fun StatementGenerator.generateValueArgument( valueArgument: ResolvedValueArgument, - valueParameter: ValueParameterDescriptor -) = generateValueArgumentUsing(valueArgument, valueParameter) { generateExpression(it) } + valueParameter: ValueParameterDescriptor, + resolvedCall: ResolvedCall<*> +) = generateValueArgumentUsing(valueArgument, valueParameter, resolvedCall) { generateExpression(it) } -fun StatementGenerator.generateValueArgumentUsing( +private fun StatementGenerator.generateValueArgumentUsing( valueArgument: ResolvedValueArgument, valueParameter: ValueParameterDescriptor, + resolvedCall: ResolvedCall<*>, generateArgumentExpression: (KtExpression) -> IrExpression? ): IrExpression? = when (valueArgument) { @@ -298,14 +314,157 @@ fun StatementGenerator.generateValueArgumentUsing( ?: throw AssertionError("No value argument: $valueArgument") val argumentExpression = valueArgument1.getArgumentExpression() ?: throw AssertionError("No argument expression: $valueArgument1") - generateArgumentExpression(argumentExpression) + generateArgumentExpression(argumentExpression)?.let { expression -> + applySuspendConversionForValueArgumentIfRequired(expression, valueArgument1, valueParameter, resolvedCall) + } } is VarargValueArgument -> - generateVarargExpressionUsing(valueArgument, valueParameter, generateArgumentExpression) + generateVarargExpressionUsing(valueArgument, valueParameter, resolvedCall, generateArgumentExpression) else -> TODO("Unexpected valueArgument: ${valueArgument::class.java.simpleName}") } +private fun StatementGenerator.applySuspendConversionForValueArgumentIfRequired( + expression: IrExpression, + valueArgument: ValueArgument, + valueParameter: ValueParameterDescriptor, + resolvedCall: ResolvedCall<*> +): IrExpression { + if (!context.languageVersionSettings.supportsFeature(LanguageFeature.SuspendConversion)) + return expression + + if (expression is IrBlock && expression.origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE) + return expression + + val newResolvedCall = resolvedCall as? NewResolvedCallImpl<*> + ?: return expression + + val suspendConversionType = newResolvedCall.getExpectedTypeForSuspendConvertedArgument(valueArgument) + ?: return expression + + val valueParameterType = if (valueParameter.isVararg) valueParameter.varargElementType!! else valueParameter.type + + return wrapInSuspendConversion(expression, suspendConversionType, valueParameterType) +} + +private fun StatementGenerator.wrapInSuspendConversion( + expression: IrExpression, + funType: KotlinType, + suspendFunType: KotlinType +): IrExpression { + val irFunType = funType.toIrType() + val irSuspendFunType = suspendFunType.toIrType() + + return irBlock( + expression.startOffset, expression.endOffset, + IrStatementOrigin.SUSPEND_CONVERSION, + irSuspendFunType + ) { + val irArgumentValue = + if (expression is IrGetValue && expression.symbol.owner.isImmutable) + expression.symbol.owner + else + irTemporary(expression, typeHint = funType, irType = irFunType) + +IrFunctionExpressionImpl( + startOffset, endOffset, irSuspendFunType, + createFunctionForSuspendConversion(startOffset, endOffset, irArgumentValue.symbol, funType, suspendFunType), + IrStatementOrigin.SUSPEND_CONVERSION + ) + } +} + +private fun StatementGenerator.createFunctionForSuspendConversion( + startOffset: Int, + endOffset: Int, + irCapturedValueSymbol: IrValueSymbol, + funType: KotlinType, + suspendFunType: KotlinType +): IrSimpleFunction { + val irFunReturnType = funType.arguments.last().type.toIrType() + val suspendFunReturnType = suspendFunType.arguments.last().type + val irSuspendFunReturnType = suspendFunReturnType.toIrType() + + val adapterFunctionDescriptor = WrappedSimpleFunctionDescriptor() + + val irAdapterFun = context.symbolTable.declareSimpleFunction( + startOffset, endOffset, + IrDeclarationOrigin.ADAPTER_FOR_SUSPEND_CONVERSION, + adapterFunctionDescriptor + ) { irAdapterSymbol -> + IrFunctionImpl( + startOffset, endOffset, + IrDeclarationOrigin.ADAPTER_FOR_SUSPEND_CONVERSION, + irAdapterSymbol, + Name.identifier(scope.inventNameForTemporary("suspendConversion")), + Visibilities.LOCAL, Modality.FINAL, + irSuspendFunReturnType, + isInline = false, isExternal = false, isTailrec = false, + isSuspend = true, + isOperator = false, isExpect = false, isFakeOverride = false + ) + } + adapterFunctionDescriptor.bind(irAdapterFun) + + context.symbolTable.enterScope(adapterFunctionDescriptor) + + irAdapterFun.valueParameters = suspendFunType.arguments + .take(suspendFunType.arguments.size - 1) + .mapIndexed { index, typeProjection -> + val adaptedParameterDescriptor = WrappedValueParameterDescriptor() + val irParameterType = typeProjection.type.toIrType() + context.symbolTable.declareValueParameter( + startOffset, endOffset, IrDeclarationOrigin.ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION, + adaptedParameterDescriptor, + irParameterType, + ) { irValueParameterSymbol -> + IrValueParameterImpl( + startOffset, endOffset, IrDeclarationOrigin.ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION, + irValueParameterSymbol, + Name.identifier("p$index"), + index, + irParameterType, + varargElementType = null, isCrossinline = false, isNoinline = false + ) + }.also { + adaptedParameterDescriptor.bind(it) + } + } + + val valueArgumentsCount = irAdapterFun.valueParameters.size + val invokeDescriptor = funType.memberScope + .getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND) + .find { it.valueParameters.size == valueArgumentsCount } + ?: error("No matching operator fun 'invoke' for suspend conversion: funType=$funType, suspendFunType=$suspendFunType") + val invokeSymbol = context.symbolTable.referenceSimpleFunction(invokeDescriptor.original) + + irAdapterFun.body = irBlockBody(startOffset, endOffset) { + val irAdapteeCall = IrCallImpl( + startOffset, endOffset, irFunReturnType, + invokeSymbol, + typeArgumentsCount = 0, + valueArgumentsCount = valueArgumentsCount + ) + + irAdapteeCall.dispatchReceiver = irGet(irCapturedValueSymbol.owner) + + this@createFunctionForSuspendConversion.context + .callToSubstitutedDescriptorMap[irAdapteeCall] = invokeDescriptor + + for (irAdapterParameter in irAdapterFun.valueParameters) { + irAdapteeCall.putValueArgument(irAdapterParameter.index, irGet(irAdapterParameter)) + } + if (suspendFunReturnType.isUnit()) { + +irAdapteeCall + } else { + +irReturn(irAdapteeCall) + } + } + + context.symbolTable.leaveScope(adapterFunctionDescriptor) + + return irAdapterFun +} + fun StatementGenerator.castArgumentToFunctionalInterfaceForSamType(irExpression: IrExpression, samType: KotlinType): IrExpression { val kotlinFunctionType = samType.getSubstitutedFunctionTypeForSamType() val irFunctionType = context.typeTranslator.translateType(kotlinFunctionType) @@ -392,7 +551,7 @@ fun StatementGenerator.pregenerateExtensionInvokeCall(resolvedCall: ResolvedCall call.irValueArgumentsByIndex[0] = null resolvedCall.valueArgumentsByIndex!!.forEachIndexed { index, valueArgument -> val valueParameter = call.descriptor.valueParameters[index] - call.irValueArgumentsByIndex[index + 1] = generateValueArgument(valueArgument, valueParameter) + call.irValueArgumentsByIndex[index + 1] = generateValueArgument(valueArgument, valueParameter, resolvedCall) } return call @@ -530,12 +689,13 @@ fun StatementGenerator.pregenerateValueArgumentsUsing( ) { resolvedCall.valueArgumentsByIndex!!.forEachIndexed { index, valueArgument -> val valueParameter = call.descriptor.valueParameters[index] - call.irValueArgumentsByIndex[index] = generateValueArgumentUsing(valueArgument, valueParameter, generateArgumentExpression) + call.irValueArgumentsByIndex[index] = + generateValueArgumentUsing(valueArgument, valueParameter, resolvedCall, generateArgumentExpression) } } fun StatementGenerator.pregenerateCallReceivers(resolvedCall: ResolvedCall<*>): CallBuilder { - val call = unwrapCallableDescriptorAndTypeArguments(resolvedCall, context.extensions.samConversion) + val call = unwrapCallableDescriptorAndTypeArguments(resolvedCall) call.callReceiver = generateCallReceiver( resolvedCall.call.callElement, @@ -560,7 +720,7 @@ private fun unwrapSpecialDescriptor(descriptor: CallableDescriptor): CallableDes descriptor.getOriginalForFunctionInterfaceAdapter()?.let { unwrapSpecialDescriptor(it) } ?: descriptor } -fun unwrapCallableDescriptorAndTypeArguments(resolvedCall: ResolvedCall<*>, samConversion: GeneratorExtensions.SamConversion): CallBuilder { +fun unwrapCallableDescriptorAndTypeArguments(resolvedCall: ResolvedCall<*>): CallBuilder { val originalDescriptor = resolvedCall.resultingDescriptor val candidateDescriptor = resolvedCall.candidateDescriptor diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ReflectionReferencesGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ReflectionReferencesGenerator.kt index a92e9c1cdba..0ccfa334519 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ReflectionReferencesGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ReflectionReferencesGenerator.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol +import org.jetbrains.kotlin.ir.util.isImmutable import org.jetbrains.kotlin.ir.util.referenceClassifier import org.jetbrains.kotlin.ir.util.referenceFunction import org.jetbrains.kotlin.ir.util.withScope @@ -75,7 +76,7 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St val resolvedCall = getResolvedCall(ktCallableReference.callableReference)!! val resolvedDescriptor = resolvedCall.resultingDescriptor - val callBuilder = unwrapCallableDescriptorAndTypeArguments(resolvedCall, context.extensions.samConversion) + val callBuilder = unwrapCallableDescriptorAndTypeArguments(resolvedCall) val callableReferenceType = getTypeInferredByFrontendOrFail(ktCallableReference) if (resolvedCall.valueArguments.isNotEmpty() || @@ -237,10 +238,7 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St this is IrGetObjectValue || this is IrGetEnumValue || this is IrConst<*> || - this is IrGetValue && symbol.isBound && symbol.owner.isImmutable() - - private fun IrValueDeclaration.isImmutable() = - this is IrValueParameter || this is IrVariable && !this.isVar + this is IrGetValue && symbol.isBound && symbol.owner.isImmutable private fun putAdaptedValueArguments( startOffset: Int, diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/Scope.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/Scope.kt index 84b4cad1b96..ab6558e9889 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/Scope.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/Scope.kt @@ -53,6 +53,11 @@ class Scope(val scopeOwnerSymbol: IrSymbol) { private var lastTemporaryIndex: Int = 0 private fun nextTemporaryIndex(): Int = lastTemporaryIndex++ + fun inventNameForTemporary(prefix: String = "tmp", nameHint: String? = null): String { + val index = nextTemporaryIndex() + return if (nameHint != null) "$prefix${index}_$nameHint" else "$prefix$index" + } + private fun createDescriptorForTemporaryVariable( type: KotlinType, nameHint: String? = null, @@ -60,10 +65,8 @@ class Scope(val scopeOwnerSymbol: IrSymbol) { ): IrTemporaryVariableDescriptor = IrTemporaryVariableDescriptorImpl(scopeOwner, Name.identifier(getNameForTemporary(nameHint)), type, isMutable) - private fun getNameForTemporary(nameHint: String?): String { - val index = nextTemporaryIndex() - return if (nameHint != null) "tmp${index}_$nameHint" else "tmp$index" - } + private fun getNameForTemporary(nameHint: String?): String = + inventNameForTemporary("tmp", nameHint) fun createTemporaryVariableDeclaration( irType: IrType, diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclarationOrigin.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclarationOrigin.kt index aed566ccbca..1c11f5d9a0b 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclarationOrigin.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclarationOrigin.kt @@ -57,6 +57,8 @@ interface IrDeclarationOrigin { object ADAPTER_FOR_CALLABLE_REFERENCE : IrDeclarationOriginImpl("ADAPTER_FOR_CALLABLE_REFERENCE") object ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE : IrDeclarationOriginImpl("ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE") + object ADAPTER_FOR_SUSPEND_CONVERSION : IrDeclarationOriginImpl("ADAPTER_FOR_SUSPEND_CONVERSION") + object ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION : IrDeclarationOriginImpl("ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION") object GENERATED_SAM_IMPLEMENTATION : IrDeclarationOriginImpl("GENERATED_SAM_IMPLEMENTATION", isSynthetic = true) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrStatementOrigin.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrStatementOrigin.kt index b4c366b4369..9798b057a05 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrStatementOrigin.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrStatementOrigin.kt @@ -90,6 +90,7 @@ interface IrStatementOrigin { object ANONYMOUS_FUNCTION : IrStatementOriginImpl("ANONYMOUS_FUNCTION") object OBJECT_LITERAL : IrStatementOriginImpl("OBJECT_LITERAL") object ADAPTED_FUNCTION_REFERENCE : IrStatementOriginImpl("ADAPTED_FUNCTION_REFERENCE") + object SUSPEND_CONVERSION: IrStatementOriginImpl("SUSPEND_CONVERSION") object INITIALIZE_PROPERTY_FROM_PARAMETER : IrStatementOriginImpl("INITIALIZE_PROPERTY_FROM_PARAMETER") object INITIALIZE_FIELD : IrStatementOriginImpl("INITIALIZE_FIELD") diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt index ab50739877c..97bc836e9f8 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt @@ -31,7 +31,9 @@ class ExternalDependenciesGenerator( ) { fun generateUnboundSymbolsAsDependencies() { if (languageVersionSettings.supportsFeature(LanguageFeature.NewInference)) { - require(symbolTable.unboundTypeParameters.isEmpty()) { "Unbound type parameters are forbidden" } + require(symbolTable.unboundTypeParameters.isEmpty()) { + "Unbound type parameters are forbidden: ${symbolTable.unboundTypeParameters.map { it.descriptor }}" + } } // There should be at most one DeclarationStubGenerator (none in closed world?) irProviders.singleOrNull { it is DeclarationStubGenerator }?.let { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt index f5a90d682d5..503c227fda3 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt @@ -680,3 +680,6 @@ fun SymbolTable.findOrDeclareExternalPackageFragment(descriptor: PackageFragment val IrDeclaration.isFileClass: Boolean get() = origin == IrDeclarationOrigin.FILE_CLASS || origin == IrDeclarationOrigin.SYNTHETIC_FILE_CLASS + +val IrValueDeclaration.isImmutable: Boolean + get() = this is IrValueParameter || this is IrVariable && !isVar \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.fir.txt b/compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.fir.txt new file mode 100644 index 00000000000..a96d6f7e020 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.fir.txt @@ -0,0 +1,135 @@ +FILE fqName: fileName:/suspendConversionOnArbitraryExpression.kt + FUN name:useSuspend visibility:public modality:FINAL <> (sfn:kotlin.coroutines.SuspendFunction0) returnType:kotlin.Unit + VALUE_PARAMETER name:sfn index:0 type:kotlin.coroutines.SuspendFunction0 + BLOCK_BODY + FUN name:useSuspendExt visibility:public modality:FINAL <> (sfn:kotlin.coroutines.SuspendFunction1) returnType:kotlin.Unit + VALUE_PARAMETER name:sfn index:0 type:kotlin.coroutines.SuspendFunction1 + BLOCK_BODY + FUN name:useSuspendArg visibility:public modality:FINAL <> (sfn:kotlin.coroutines.SuspendFunction1) returnType:kotlin.Unit + VALUE_PARAMETER name:sfn index:0 type:kotlin.coroutines.SuspendFunction1 + BLOCK_BODY + FUN name:useSuspendArgT visibility:public modality:FINAL (sfn:kotlin.coroutines.SuspendFunction1.useSuspendArgT, kotlin.Unit>) returnType:kotlin.Unit + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + VALUE_PARAMETER name:sfn index:0 type:kotlin.coroutines.SuspendFunction1.useSuspendArgT, kotlin.Unit> + BLOCK_BODY + FUN name:useSuspendExtT visibility:public modality:FINAL (sfn:kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit>) returnType:kotlin.Unit + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + VALUE_PARAMETER name:sfn index:0 type:kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit> + BLOCK_BODY + FUN name:produceFun visibility:public modality:FINAL <> () returnType:kotlin.Function0 + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun produceFun (): kotlin.Function0 declared in ' + FUN_EXPR type=kotlin.Function0 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.Unit + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (): kotlin.Unit declared in .produceFun' + GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit + FUN name:testSimple visibility:public modality:FINAL <> (fn:kotlin.Function0) returnType:kotlin.Unit + VALUE_PARAMETER name:fn index:0 type:kotlin.Function0 + BLOCK_BODY + ERROR_CALL 'Unresolved reference: #' type=IrErrorType + GET_VAR 'fn: kotlin.Function0 declared in .testSimple' type=kotlin.Function0 origin=null + FUN name:testSimpleNonVal visibility:public modality:FINAL <> () returnType:kotlin.Unit + BLOCK_BODY + ERROR_CALL 'Unresolved reference: #' type=IrErrorType + CALL 'public final fun produceFun (): kotlin.Function0 declared in ' type=kotlin.Function0 origin=null + FUN name:testExtAsExt visibility:public modality:FINAL <> (fn:kotlin.Function1) returnType:kotlin.Unit + VALUE_PARAMETER name:fn index:0 type:kotlin.Function1 + BLOCK_BODY + ERROR_CALL 'Unresolved reference: #' type=IrErrorType + GET_VAR 'fn: kotlin.Function1 declared in .testExtAsExt' type=kotlin.Function1 origin=null + FUN name:testExtAsSimple visibility:public modality:FINAL <> (fn:kotlin.Function1) returnType:kotlin.Unit + VALUE_PARAMETER name:fn index:0 type:kotlin.Function1 + BLOCK_BODY + ERROR_CALL 'Unresolved reference: #' type=IrErrorType + GET_VAR 'fn: kotlin.Function1 declared in .testExtAsSimple' type=kotlin.Function1 origin=null + FUN name:testSimpleAsExt visibility:public modality:FINAL <> (fn:kotlin.Function1) returnType:kotlin.Unit + VALUE_PARAMETER name:fn index:0 type:kotlin.Function1 + BLOCK_BODY + ERROR_CALL 'Unresolved reference: #' type=IrErrorType + GET_VAR 'fn: kotlin.Function1 declared in .testSimpleAsExt' type=kotlin.Function1 origin=null + FUN name:testSimpleAsSimpleT visibility:public modality:FINAL <> (fn:kotlin.Function1) returnType:kotlin.Unit + VALUE_PARAMETER name:fn index:0 type:kotlin.Function1 + BLOCK_BODY + ERROR_CALL 'Unresolved reference: #' type=IrErrorType + GET_VAR 'fn: kotlin.Function1 declared in .testSimpleAsSimpleT' type=kotlin.Function1 origin=null + FUN name:testSimpleAsExtT visibility:public modality:FINAL <> (fn:kotlin.Function1) returnType:kotlin.Unit + VALUE_PARAMETER name:fn index:0 type:kotlin.Function1 + BLOCK_BODY + ERROR_CALL 'Unresolved reference: #' type=IrErrorType + GET_VAR 'fn: kotlin.Function1 declared in .testSimpleAsExtT' type=kotlin.Function1 origin=null + FUN name:testExtAsSimpleT visibility:public modality:FINAL <> (fn:kotlin.Function1) returnType:kotlin.Unit + VALUE_PARAMETER name:fn index:0 type:kotlin.Function1 + BLOCK_BODY + ERROR_CALL 'Unresolved reference: #' type=IrErrorType + GET_VAR 'fn: kotlin.Function1 declared in .testExtAsSimpleT' type=kotlin.Function1 origin=null + FUN name:testExtAsExtT visibility:public modality:FINAL <> (fn:kotlin.Function1) returnType:kotlin.Unit + VALUE_PARAMETER name:fn index:0 type:kotlin.Function1 + BLOCK_BODY + ERROR_CALL 'Unresolved reference: #' type=IrErrorType + GET_VAR 'fn: kotlin.Function1 declared in .testExtAsExtT' type=kotlin.Function1 origin=null + FUN name:testSimpleSAsSimpleT visibility:public modality:FINAL (fn:kotlin.Function1.testSimpleSAsSimpleT, kotlin.Unit>) returnType:kotlin.Unit + TYPE_PARAMETER name:S index:0 variance: superTypes:[kotlin.Any?] + VALUE_PARAMETER name:fn index:0 type:kotlin.Function1.testSimpleSAsSimpleT, kotlin.Unit> + BLOCK_BODY + ERROR_CALL 'Unresolved reference: #' type=IrErrorType + GET_VAR 'fn: kotlin.Function1.testSimpleSAsSimpleT, kotlin.Unit> declared in .testSimpleSAsSimpleT' type=kotlin.Function1.testSimpleSAsSimpleT, kotlin.Unit> origin=null + FUN name:testSimpleSAsExtT visibility:public modality:FINAL (fn:kotlin.Function1.testSimpleSAsExtT, kotlin.Unit>) returnType:kotlin.Unit + TYPE_PARAMETER name:S index:0 variance: superTypes:[kotlin.Any?] + VALUE_PARAMETER name:fn index:0 type:kotlin.Function1.testSimpleSAsExtT, kotlin.Unit> + BLOCK_BODY + ERROR_CALL 'Unresolved reference: #' type=IrErrorType + GET_VAR 'fn: kotlin.Function1.testSimpleSAsExtT, kotlin.Unit> declared in .testSimpleSAsExtT' type=kotlin.Function1.testSimpleSAsExtT, kotlin.Unit> origin=null + FUN name:testExtSAsSimpleT visibility:public modality:FINAL (fn:kotlin.Function1.testExtSAsSimpleT, kotlin.Unit>) returnType:kotlin.Unit + TYPE_PARAMETER name:S index:0 variance: superTypes:[kotlin.Any?] + VALUE_PARAMETER name:fn index:0 type:kotlin.Function1.testExtSAsSimpleT, kotlin.Unit> + BLOCK_BODY + ERROR_CALL 'Unresolved reference: #' type=IrErrorType + GET_VAR 'fn: kotlin.Function1.testExtSAsSimpleT, kotlin.Unit> declared in .testExtSAsSimpleT' type=kotlin.Function1.testExtSAsSimpleT, kotlin.Unit> origin=null + FUN name:testExtSAsExtT visibility:public modality:FINAL (fn:kotlin.Function1.testExtSAsExtT, kotlin.Unit>) returnType:kotlin.Unit + TYPE_PARAMETER name:S index:0 variance: superTypes:[kotlin.Any?] + VALUE_PARAMETER name:fn index:0 type:kotlin.Function1.testExtSAsExtT, kotlin.Unit> + BLOCK_BODY + ERROR_CALL 'Unresolved reference: #' type=IrErrorType + GET_VAR 'fn: kotlin.Function1.testExtSAsExtT, kotlin.Unit> declared in .testExtSAsExtT' type=kotlin.Function1.testExtSAsExtT, kotlin.Unit> origin=null + FUN name:testSmartCastWithSuspendConversion visibility:public modality:FINAL <> (a:kotlin.Any) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:kotlin.Any + BLOCK_BODY + TYPE_OP type=kotlin.Function0 origin=CAST typeOperand=kotlin.Function0 + GET_VAR 'a: kotlin.Any declared in .testSmartCastWithSuspendConversion' type=kotlin.Any origin=null + ERROR_CALL 'Unresolved reference: #' type=IrErrorType + TYPE_OP type=kotlin.Function0 origin=IMPLICIT_CAST typeOperand=kotlin.Function0 + GET_VAR 'a: kotlin.Any declared in .testSmartCastWithSuspendConversion' type=kotlin.Any origin=null + FUN name:testSmartCastOnVarWithSuspendConversion visibility:public modality:FINAL <> (a:kotlin.Any) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:kotlin.Any + BLOCK_BODY + VAR name:b type:kotlin.Any [var] + GET_VAR 'a: kotlin.Any declared in .testSmartCastOnVarWithSuspendConversion' type=kotlin.Any origin=null + TYPE_OP type=kotlin.Function0 origin=CAST typeOperand=kotlin.Function0 + GET_VAR 'var b: kotlin.Any [var] declared in .testSmartCastOnVarWithSuspendConversion' type=kotlin.Any origin=null + ERROR_CALL 'Unresolved reference: #' type=IrErrorType + TYPE_OP type=kotlin.Function0 origin=IMPLICIT_CAST typeOperand=kotlin.Function0 + GET_VAR 'var b: kotlin.Any [var] declared in .testSmartCastOnVarWithSuspendConversion' type=kotlin.Any origin=null + FUN name:testSmartCastVsSuspendConversion visibility:public modality:FINAL <> (a:kotlin.Function0) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:kotlin.Function0 + BLOCK_BODY + TYPE_OP type=kotlin.coroutines.SuspendFunction0 origin=CAST typeOperand=kotlin.coroutines.SuspendFunction0 + GET_VAR 'a: kotlin.Function0 declared in .testSmartCastVsSuspendConversion' type=kotlin.Function0 origin=null + CALL 'public final fun useSuspend (sfn: kotlin.coroutines.SuspendFunction0): kotlin.Unit declared in ' type=kotlin.Unit origin=null + sfn: TYPE_OP type=kotlin.coroutines.SuspendFunction0 origin=IMPLICIT_CAST typeOperand=kotlin.coroutines.SuspendFunction0 + GET_VAR 'a: kotlin.Function0 declared in .testSmartCastVsSuspendConversion' type=kotlin.Function0 origin=null + FUN name:testSmartCastOnVarVsSuspendConversion visibility:public modality:FINAL <> (a:kotlin.Function0) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:kotlin.Function0 + BLOCK_BODY + VAR name:b type:kotlin.Function0 [var] + GET_VAR 'a: kotlin.Function0 declared in .testSmartCastOnVarVsSuspendConversion' type=kotlin.Function0 origin=null + TYPE_OP type=kotlin.coroutines.SuspendFunction0 origin=CAST typeOperand=kotlin.coroutines.SuspendFunction0 + GET_VAR 'var b: kotlin.Function0 [var] declared in .testSmartCastOnVarVsSuspendConversion' type=kotlin.Function0 origin=null + CALL 'public final fun useSuspend (sfn: kotlin.coroutines.SuspendFunction0): kotlin.Unit declared in ' type=kotlin.Unit origin=null + sfn: GET_VAR 'var b: kotlin.Function0 [var] declared in .testSmartCastOnVarVsSuspendConversion' type=kotlin.Function0 origin=null + FUN name:testIntersectionVsSuspendConversion visibility:public modality:FINAL (x:T of .testIntersectionVsSuspendConversion) returnType:kotlin.Unit + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Function0; kotlin.coroutines.SuspendFunction0] + VALUE_PARAMETER name:x index:0 type:T of .testIntersectionVsSuspendConversion + BLOCK_BODY + CALL 'public final fun useSuspend (sfn: kotlin.coroutines.SuspendFunction0): kotlin.Unit declared in ' type=kotlin.Unit origin=null + sfn: GET_VAR 'x: T of .testIntersectionVsSuspendConversion declared in .testIntersectionVsSuspendConversion' type=T of .testIntersectionVsSuspendConversion origin=null diff --git a/compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.kt b/compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.kt new file mode 100644 index 00000000000..8e9bcb31fca --- /dev/null +++ b/compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.kt @@ -0,0 +1,92 @@ +// !LANGUAGE: +SuspendConversion + +fun useSuspend(sfn: suspend () -> Unit) {} + +fun useSuspendExt(sfn: suspend Int.() -> Unit) {} + +fun useSuspendArg(sfn: suspend (Int) -> Unit) {} + +fun useSuspendArgT(sfn: suspend (T) -> Unit) {} + +fun useSuspendExtT(sfn: suspend T.() -> Unit) {} + +fun produceFun(): () -> Unit = {} + +fun testSimple(fn: () -> Unit) { + useSuspend(fn) +} + +fun testSimpleNonVal() { + useSuspend(produceFun()) +} + +fun testExtAsExt(fn: Int.() -> Unit) { + useSuspendExt(fn) +} + +fun testExtAsSimple(fn: Int.() -> Unit) { + useSuspendArg(fn) +} + +fun testSimpleAsExt(fn: (Int) -> Unit) { + useSuspendExt(fn) +} + +fun testSimpleAsSimpleT(fn: (Int) -> Unit) { + useSuspendArgT(fn) +} + +fun testSimpleAsExtT(fn: (Int) -> Unit) { + useSuspendExtT(fn) +} + +fun testExtAsSimpleT(fn: Int.() -> Unit) { + useSuspendArgT(fn) +} + +fun testExtAsExtT(fn: Int.() -> Unit) { + useSuspendExtT(fn) +} + +fun testSimpleSAsSimpleT(fn: (S) -> Unit) { + useSuspendArgT(fn) +} + +fun testSimpleSAsExtT(fn: (S) -> Unit) { + useSuspendExtT(fn) +} + +fun testExtSAsSimpleT(fn: S.() -> Unit) { + useSuspendArgT(fn) +} + +fun testExtSAsExtT(fn: S.() -> Unit) { + useSuspendExtT(fn) +} + +fun testSmartCastWithSuspendConversion(a: Any) { + a as () -> Unit + useSuspend(a) +} + +fun testSmartCastOnVarWithSuspendConversion(a: Any) { + var b = a + b as () -> Unit + useSuspend(b) +} + +fun testSmartCastVsSuspendConversion(a: () -> Unit) { + a as suspend () -> Unit + useSuspend(a) +} + +fun testSmartCastOnVarVsSuspendConversion(a: () -> Unit) { + var b = a + b as suspend () -> Unit + useSuspend(b) +} + +fun testIntersectionVsSuspendConversion(x: T) + where T : () -> Unit, T : suspend () -> Unit { + useSuspend(x) +} diff --git a/compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.txt b/compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.txt new file mode 100644 index 00000000000..7fac3e36c9b --- /dev/null +++ b/compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.txt @@ -0,0 +1,249 @@ +FILE fqName: fileName:/suspendConversionOnArbitraryExpression.kt + FUN name:useSuspend visibility:public modality:FINAL <> (sfn:kotlin.coroutines.SuspendFunction0) returnType:kotlin.Unit + VALUE_PARAMETER name:sfn index:0 type:kotlin.coroutines.SuspendFunction0 + BLOCK_BODY + FUN name:useSuspendExt visibility:public modality:FINAL <> (sfn:@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1) returnType:kotlin.Unit + VALUE_PARAMETER name:sfn index:0 type:@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1 + BLOCK_BODY + FUN name:useSuspendArg visibility:public modality:FINAL <> (sfn:kotlin.coroutines.SuspendFunction1) returnType:kotlin.Unit + VALUE_PARAMETER name:sfn index:0 type:kotlin.coroutines.SuspendFunction1 + BLOCK_BODY + FUN name:useSuspendArgT visibility:public modality:FINAL (sfn:kotlin.coroutines.SuspendFunction1.useSuspendArgT, kotlin.Unit>) returnType:kotlin.Unit + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + VALUE_PARAMETER name:sfn index:0 type:kotlin.coroutines.SuspendFunction1.useSuspendArgT, kotlin.Unit> + BLOCK_BODY + FUN name:useSuspendExtT visibility:public modality:FINAL (sfn:@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit>) returnType:kotlin.Unit + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + VALUE_PARAMETER name:sfn index:0 type:@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit> + BLOCK_BODY + FUN name:produceFun visibility:public modality:FINAL <> () returnType:kotlin.Function0 + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun produceFun (): kotlin.Function0 declared in ' + FUN_EXPR type=kotlin.Function0 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.Unit + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (): kotlin.Unit declared in .produceFun' + GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit + FUN name:testSimple visibility:public modality:FINAL <> (fn:kotlin.Function0) returnType:kotlin.Unit + VALUE_PARAMETER name:fn index:0 type:kotlin.Function0 + BLOCK_BODY + CALL 'public final fun useSuspend (sfn: kotlin.coroutines.SuspendFunction0): kotlin.Unit declared in ' type=kotlin.Unit origin=null + sfn: BLOCK type=kotlin.coroutines.SuspendFunction0 origin=SUSPEND_CONVERSION + FUN_EXPR type=kotlin.coroutines.SuspendFunction0 origin=SUSPEND_CONVERSION + FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion0 visibility:local modality:FINAL <> () returnType:kotlin.Unit [suspend] + BLOCK_BODY + CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=null + $this: GET_VAR 'fn: kotlin.Function0 declared in .testSimple' type=kotlin.Function0 origin=null + FUN name:testSimpleNonVal visibility:public modality:FINAL <> () returnType:kotlin.Unit + BLOCK_BODY + CALL 'public final fun useSuspend (sfn: kotlin.coroutines.SuspendFunction0): kotlin.Unit declared in ' type=kotlin.Unit origin=null + sfn: BLOCK type=kotlin.coroutines.SuspendFunction0 origin=SUSPEND_CONVERSION + VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Function0 [val] + CALL 'public final fun produceFun (): kotlin.Function0 declared in ' type=kotlin.Function0 origin=null + FUN_EXPR type=kotlin.coroutines.SuspendFunction0 origin=SUSPEND_CONVERSION + FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion1 visibility:local modality:FINAL <> () returnType:kotlin.Unit [suspend] + BLOCK_BODY + CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=null + $this: GET_VAR 'val tmp_0: kotlin.Function0 [val] declared in .testSimpleNonVal' type=kotlin.Function0 origin=null + FUN name:testExtAsExt visibility:public modality:FINAL <> (fn:@[ExtensionFunctionType] kotlin.Function1) returnType:kotlin.Unit + VALUE_PARAMETER name:fn index:0 type:@[ExtensionFunctionType] kotlin.Function1 + BLOCK_BODY + CALL 'public final fun useSuspendExt (sfn: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1): kotlin.Unit declared in ' type=kotlin.Unit origin=null + sfn: BLOCK type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION + FUN_EXPR type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION + FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion0 visibility:local modality:FINAL <> (p0:kotlin.Int) returnType:kotlin.Unit [suspend] + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:kotlin.Int + BLOCK_BODY + CALL 'public abstract fun invoke (p1: P1 of kotlin.Function1): R of kotlin.Function1 [operator] declared in kotlin.Function1' type=kotlin.Unit origin=null + $this: GET_VAR 'fn: @[ExtensionFunctionType] kotlin.Function1 declared in .testExtAsExt' type=@[ExtensionFunctionType] kotlin.Function1 origin=null + p1: GET_VAR 'p0: kotlin.Int declared in .testExtAsExt.suspendConversion0' type=kotlin.Int origin=null + FUN name:testExtAsSimple visibility:public modality:FINAL <> (fn:@[ExtensionFunctionType] kotlin.Function1) returnType:kotlin.Unit + VALUE_PARAMETER name:fn index:0 type:@[ExtensionFunctionType] kotlin.Function1 + BLOCK_BODY + CALL 'public final fun useSuspendArg (sfn: kotlin.coroutines.SuspendFunction1): kotlin.Unit declared in ' type=kotlin.Unit origin=null + sfn: BLOCK type=kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION + FUN_EXPR type=kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION + FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion0 visibility:local modality:FINAL <> (p0:kotlin.Int) returnType:kotlin.Unit [suspend] + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:kotlin.Int + BLOCK_BODY + CALL 'public abstract fun invoke (p1: P1 of kotlin.Function1): R of kotlin.Function1 [operator] declared in kotlin.Function1' type=kotlin.Unit origin=null + $this: GET_VAR 'fn: @[ExtensionFunctionType] kotlin.Function1 declared in .testExtAsSimple' type=@[ExtensionFunctionType] kotlin.Function1 origin=null + p1: GET_VAR 'p0: kotlin.Int declared in .testExtAsSimple.suspendConversion0' type=kotlin.Int origin=null + FUN name:testSimpleAsExt visibility:public modality:FINAL <> (fn:kotlin.Function1) returnType:kotlin.Unit + VALUE_PARAMETER name:fn index:0 type:kotlin.Function1 + BLOCK_BODY + CALL 'public final fun useSuspendExt (sfn: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1): kotlin.Unit declared in ' type=kotlin.Unit origin=null + sfn: BLOCK type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION + FUN_EXPR type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION + FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion0 visibility:local modality:FINAL <> (p0:kotlin.Int) returnType:kotlin.Unit [suspend] + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:kotlin.Int + BLOCK_BODY + CALL 'public abstract fun invoke (p1: P1 of kotlin.Function1): R of kotlin.Function1 [operator] declared in kotlin.Function1' type=kotlin.Unit origin=null + $this: GET_VAR 'fn: kotlin.Function1 declared in .testSimpleAsExt' type=kotlin.Function1 origin=null + p1: GET_VAR 'p0: kotlin.Int declared in .testSimpleAsExt.suspendConversion0' type=kotlin.Int origin=null + FUN name:testSimpleAsSimpleT visibility:public modality:FINAL <> (fn:kotlin.Function1) returnType:kotlin.Unit + VALUE_PARAMETER name:fn index:0 type:kotlin.Function1 + BLOCK_BODY + CALL 'public final fun useSuspendArgT (sfn: kotlin.coroutines.SuspendFunction1.useSuspendArgT, kotlin.Unit>): kotlin.Unit declared in ' type=kotlin.Unit origin=null + : kotlin.Int + sfn: BLOCK type=kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION + FUN_EXPR type=kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION + FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion0 visibility:local modality:FINAL <> (p0:kotlin.Int) returnType:kotlin.Unit [suspend] + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:kotlin.Int + BLOCK_BODY + CALL 'public abstract fun invoke (p1: P1 of kotlin.Function1): R of kotlin.Function1 [operator] declared in kotlin.Function1' type=kotlin.Unit origin=null + $this: GET_VAR 'fn: kotlin.Function1 declared in .testSimpleAsSimpleT' type=kotlin.Function1 origin=null + p1: GET_VAR 'p0: kotlin.Int declared in .testSimpleAsSimpleT.suspendConversion0' type=kotlin.Int origin=null + FUN name:testSimpleAsExtT visibility:public modality:FINAL <> (fn:kotlin.Function1) returnType:kotlin.Unit + VALUE_PARAMETER name:fn index:0 type:kotlin.Function1 + BLOCK_BODY + CALL 'public final fun useSuspendExtT (sfn: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit>): kotlin.Unit declared in ' type=kotlin.Unit origin=null + : kotlin.Int + sfn: BLOCK type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION + FUN_EXPR type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION + FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion0 visibility:local modality:FINAL <> (p0:kotlin.Int) returnType:kotlin.Unit [suspend] + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:kotlin.Int + BLOCK_BODY + CALL 'public abstract fun invoke (p1: P1 of kotlin.Function1): R of kotlin.Function1 [operator] declared in kotlin.Function1' type=kotlin.Unit origin=null + $this: GET_VAR 'fn: kotlin.Function1 declared in .testSimpleAsExtT' type=kotlin.Function1 origin=null + p1: GET_VAR 'p0: kotlin.Int declared in .testSimpleAsExtT.suspendConversion0' type=kotlin.Int origin=null + FUN name:testExtAsSimpleT visibility:public modality:FINAL <> (fn:@[ExtensionFunctionType] kotlin.Function1) returnType:kotlin.Unit + VALUE_PARAMETER name:fn index:0 type:@[ExtensionFunctionType] kotlin.Function1 + BLOCK_BODY + CALL 'public final fun useSuspendArgT (sfn: kotlin.coroutines.SuspendFunction1.useSuspendArgT, kotlin.Unit>): kotlin.Unit declared in ' type=kotlin.Unit origin=null + : kotlin.Int + sfn: BLOCK type=kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION + FUN_EXPR type=kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION + FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion0 visibility:local modality:FINAL <> (p0:kotlin.Int) returnType:kotlin.Unit [suspend] + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:kotlin.Int + BLOCK_BODY + CALL 'public abstract fun invoke (p1: P1 of kotlin.Function1): R of kotlin.Function1 [operator] declared in kotlin.Function1' type=kotlin.Unit origin=null + $this: GET_VAR 'fn: @[ExtensionFunctionType] kotlin.Function1 declared in .testExtAsSimpleT' type=@[ExtensionFunctionType] kotlin.Function1 origin=null + p1: GET_VAR 'p0: kotlin.Int declared in .testExtAsSimpleT.suspendConversion0' type=kotlin.Int origin=null + FUN name:testExtAsExtT visibility:public modality:FINAL <> (fn:@[ExtensionFunctionType] kotlin.Function1) returnType:kotlin.Unit + VALUE_PARAMETER name:fn index:0 type:@[ExtensionFunctionType] kotlin.Function1 + BLOCK_BODY + CALL 'public final fun useSuspendExtT (sfn: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit>): kotlin.Unit declared in ' type=kotlin.Unit origin=null + : kotlin.Int + sfn: BLOCK type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION + FUN_EXPR type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1 origin=SUSPEND_CONVERSION + FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion0 visibility:local modality:FINAL <> (p0:kotlin.Int) returnType:kotlin.Unit [suspend] + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:kotlin.Int + BLOCK_BODY + CALL 'public abstract fun invoke (p1: P1 of kotlin.Function1): R of kotlin.Function1 [operator] declared in kotlin.Function1' type=kotlin.Unit origin=null + $this: GET_VAR 'fn: @[ExtensionFunctionType] kotlin.Function1 declared in .testExtAsExtT' type=@[ExtensionFunctionType] kotlin.Function1 origin=null + p1: GET_VAR 'p0: kotlin.Int declared in .testExtAsExtT.suspendConversion0' type=kotlin.Int origin=null + FUN name:testSimpleSAsSimpleT visibility:public modality:FINAL (fn:kotlin.Function1.testSimpleSAsSimpleT, kotlin.Unit>) returnType:kotlin.Unit + TYPE_PARAMETER name:S index:0 variance: superTypes:[kotlin.Any?] + VALUE_PARAMETER name:fn index:0 type:kotlin.Function1.testSimpleSAsSimpleT, kotlin.Unit> + BLOCK_BODY + CALL 'public final fun useSuspendArgT (sfn: kotlin.coroutines.SuspendFunction1.useSuspendArgT, kotlin.Unit>): kotlin.Unit declared in ' type=kotlin.Unit origin=null + : S of .testSimpleSAsSimpleT + sfn: BLOCK type=kotlin.coroutines.SuspendFunction1.testSimpleSAsSimpleT, kotlin.Unit> origin=SUSPEND_CONVERSION + FUN_EXPR type=kotlin.coroutines.SuspendFunction1.testSimpleSAsSimpleT, kotlin.Unit> origin=SUSPEND_CONVERSION + FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion0 visibility:local modality:FINAL <> (p0:S of .testSimpleSAsSimpleT) returnType:kotlin.Unit [suspend] + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:S of .testSimpleSAsSimpleT + BLOCK_BODY + CALL 'public abstract fun invoke (p1: P1 of kotlin.Function1): R of kotlin.Function1 [operator] declared in kotlin.Function1' type=kotlin.Unit origin=null + $this: GET_VAR 'fn: kotlin.Function1.testSimpleSAsSimpleT, kotlin.Unit> declared in .testSimpleSAsSimpleT' type=kotlin.Function1.testSimpleSAsSimpleT, kotlin.Unit> origin=null + p1: GET_VAR 'p0: S of .testSimpleSAsSimpleT declared in .testSimpleSAsSimpleT.suspendConversion0' type=S of .testSimpleSAsSimpleT origin=null + FUN name:testSimpleSAsExtT visibility:public modality:FINAL (fn:kotlin.Function1.testSimpleSAsExtT, kotlin.Unit>) returnType:kotlin.Unit + TYPE_PARAMETER name:S index:0 variance: superTypes:[kotlin.Any?] + VALUE_PARAMETER name:fn index:0 type:kotlin.Function1.testSimpleSAsExtT, kotlin.Unit> + BLOCK_BODY + CALL 'public final fun useSuspendExtT (sfn: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit>): kotlin.Unit declared in ' type=kotlin.Unit origin=null + : S of .testSimpleSAsExtT + sfn: BLOCK type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.testSimpleSAsExtT, kotlin.Unit> origin=SUSPEND_CONVERSION + FUN_EXPR type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.testSimpleSAsExtT, kotlin.Unit> origin=SUSPEND_CONVERSION + FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion0 visibility:local modality:FINAL <> (p0:S of .testSimpleSAsExtT) returnType:kotlin.Unit [suspend] + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:S of .testSimpleSAsExtT + BLOCK_BODY + CALL 'public abstract fun invoke (p1: P1 of kotlin.Function1): R of kotlin.Function1 [operator] declared in kotlin.Function1' type=kotlin.Unit origin=null + $this: GET_VAR 'fn: kotlin.Function1.testSimpleSAsExtT, kotlin.Unit> declared in .testSimpleSAsExtT' type=kotlin.Function1.testSimpleSAsExtT, kotlin.Unit> origin=null + p1: GET_VAR 'p0: S of .testSimpleSAsExtT declared in .testSimpleSAsExtT.suspendConversion0' type=S of .testSimpleSAsExtT origin=null + FUN name:testExtSAsSimpleT visibility:public modality:FINAL (fn:@[ExtensionFunctionType] kotlin.Function1.testExtSAsSimpleT, kotlin.Unit>) returnType:kotlin.Unit + TYPE_PARAMETER name:S index:0 variance: superTypes:[kotlin.Any?] + VALUE_PARAMETER name:fn index:0 type:@[ExtensionFunctionType] kotlin.Function1.testExtSAsSimpleT, kotlin.Unit> + BLOCK_BODY + CALL 'public final fun useSuspendArgT (sfn: kotlin.coroutines.SuspendFunction1.useSuspendArgT, kotlin.Unit>): kotlin.Unit declared in ' type=kotlin.Unit origin=null + : S of .testExtSAsSimpleT + sfn: BLOCK type=kotlin.coroutines.SuspendFunction1.testExtSAsSimpleT, kotlin.Unit> origin=SUSPEND_CONVERSION + FUN_EXPR type=kotlin.coroutines.SuspendFunction1.testExtSAsSimpleT, kotlin.Unit> origin=SUSPEND_CONVERSION + FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion0 visibility:local modality:FINAL <> (p0:S of .testExtSAsSimpleT) returnType:kotlin.Unit [suspend] + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:S of .testExtSAsSimpleT + BLOCK_BODY + CALL 'public abstract fun invoke (p1: P1 of kotlin.Function1): R of kotlin.Function1 [operator] declared in kotlin.Function1' type=kotlin.Unit origin=null + $this: GET_VAR 'fn: @[ExtensionFunctionType] kotlin.Function1.testExtSAsSimpleT, kotlin.Unit> declared in .testExtSAsSimpleT' type=@[ExtensionFunctionType] kotlin.Function1.testExtSAsSimpleT, kotlin.Unit> origin=null + p1: GET_VAR 'p0: S of .testExtSAsSimpleT declared in .testExtSAsSimpleT.suspendConversion0' type=S of .testExtSAsSimpleT origin=null + FUN name:testExtSAsExtT visibility:public modality:FINAL (fn:@[ExtensionFunctionType] kotlin.Function1.testExtSAsExtT, kotlin.Unit>) returnType:kotlin.Unit + TYPE_PARAMETER name:S index:0 variance: superTypes:[kotlin.Any?] + VALUE_PARAMETER name:fn index:0 type:@[ExtensionFunctionType] kotlin.Function1.testExtSAsExtT, kotlin.Unit> + BLOCK_BODY + CALL 'public final fun useSuspendExtT (sfn: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.useSuspendExtT, kotlin.Unit>): kotlin.Unit declared in ' type=kotlin.Unit origin=null + : S of .testExtSAsExtT + sfn: BLOCK type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.testExtSAsExtT, kotlin.Unit> origin=SUSPEND_CONVERSION + FUN_EXPR type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1.testExtSAsExtT, kotlin.Unit> origin=SUSPEND_CONVERSION + FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion0 visibility:local modality:FINAL <> (p0:S of .testExtSAsExtT) returnType:kotlin.Unit [suspend] + VALUE_PARAMETER ADAPTER_PARAMETER_FOR_SUSPEND_CONVERSION name:p0 index:0 type:S of .testExtSAsExtT + BLOCK_BODY + CALL 'public abstract fun invoke (p1: P1 of kotlin.Function1): R of kotlin.Function1 [operator] declared in kotlin.Function1' type=kotlin.Unit origin=null + $this: GET_VAR 'fn: @[ExtensionFunctionType] kotlin.Function1.testExtSAsExtT, kotlin.Unit> declared in .testExtSAsExtT' type=@[ExtensionFunctionType] kotlin.Function1.testExtSAsExtT, kotlin.Unit> origin=null + p1: GET_VAR 'p0: S of .testExtSAsExtT declared in .testExtSAsExtT.suspendConversion0' type=S of .testExtSAsExtT origin=null + FUN name:testSmartCastWithSuspendConversion visibility:public modality:FINAL <> (a:kotlin.Any) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:kotlin.Any + BLOCK_BODY + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + TYPE_OP type=kotlin.Function0 origin=CAST typeOperand=kotlin.Function0 + GET_VAR 'a: kotlin.Any declared in .testSmartCastWithSuspendConversion' type=kotlin.Any origin=null + CALL 'public final fun useSuspend (sfn: kotlin.coroutines.SuspendFunction0): kotlin.Unit declared in ' type=kotlin.Unit origin=null + sfn: BLOCK type=kotlin.coroutines.SuspendFunction0 origin=SUSPEND_CONVERSION + FUN_EXPR type=kotlin.coroutines.SuspendFunction0 origin=SUSPEND_CONVERSION + FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion0 visibility:local modality:FINAL <> () returnType:kotlin.Unit [suspend] + BLOCK_BODY + CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=null + $this: TYPE_OP type=kotlin.Function0 origin=IMPLICIT_CAST typeOperand=kotlin.Function0 + GET_VAR 'a: kotlin.Any declared in .testSmartCastWithSuspendConversion' type=kotlin.Any origin=null + FUN name:testSmartCastOnVarWithSuspendConversion visibility:public modality:FINAL <> (a:kotlin.Any) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:kotlin.Any + BLOCK_BODY + VAR name:b type:kotlin.Any [var] + GET_VAR 'a: kotlin.Any declared in .testSmartCastOnVarWithSuspendConversion' type=kotlin.Any origin=null + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + TYPE_OP type=kotlin.Function0 origin=CAST typeOperand=kotlin.Function0 + GET_VAR 'var b: kotlin.Any [var] declared in .testSmartCastOnVarWithSuspendConversion' type=kotlin.Any origin=null + CALL 'public final fun useSuspend (sfn: kotlin.coroutines.SuspendFunction0): kotlin.Unit declared in ' type=kotlin.Unit origin=null + sfn: BLOCK type=kotlin.coroutines.SuspendFunction0 origin=SUSPEND_CONVERSION + VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Function0 [val] + TYPE_OP type=kotlin.Function0 origin=IMPLICIT_CAST typeOperand=kotlin.Function0 + GET_VAR 'var b: kotlin.Any [var] declared in .testSmartCastOnVarWithSuspendConversion' type=kotlin.Any origin=null + FUN_EXPR type=kotlin.coroutines.SuspendFunction0 origin=SUSPEND_CONVERSION + FUN ADAPTER_FOR_SUSPEND_CONVERSION name:suspendConversion1 visibility:local modality:FINAL <> () returnType:kotlin.Unit [suspend] + BLOCK_BODY + CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=null + $this: GET_VAR 'val tmp_1: kotlin.Function0 [val] declared in .testSmartCastOnVarWithSuspendConversion' type=kotlin.Function0 origin=null + FUN name:testSmartCastVsSuspendConversion visibility:public modality:FINAL <> (a:kotlin.Function0) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:kotlin.Function0 + BLOCK_BODY + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + TYPE_OP type=kotlin.coroutines.SuspendFunction0 origin=CAST typeOperand=kotlin.coroutines.SuspendFunction0 + GET_VAR 'a: kotlin.Function0 declared in .testSmartCastVsSuspendConversion' type=kotlin.Function0 origin=null + CALL 'public final fun useSuspend (sfn: kotlin.coroutines.SuspendFunction0): kotlin.Unit declared in ' type=kotlin.Unit origin=null + sfn: TYPE_OP type=kotlin.coroutines.SuspendFunction0 origin=IMPLICIT_CAST typeOperand=kotlin.coroutines.SuspendFunction0 + GET_VAR 'a: kotlin.Function0 declared in .testSmartCastVsSuspendConversion' type=kotlin.Function0 origin=null + FUN name:testSmartCastOnVarVsSuspendConversion visibility:public modality:FINAL <> (a:kotlin.Function0) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:kotlin.Function0 + BLOCK_BODY + VAR name:b type:kotlin.Function0 [var] + GET_VAR 'a: kotlin.Function0 declared in .testSmartCastOnVarVsSuspendConversion' type=kotlin.Function0 origin=null + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + TYPE_OP type=kotlin.coroutines.SuspendFunction0 origin=CAST typeOperand=kotlin.coroutines.SuspendFunction0 + GET_VAR 'var b: kotlin.Function0 [var] declared in .testSmartCastOnVarVsSuspendConversion' type=kotlin.Function0 origin=null + CALL 'public final fun useSuspend (sfn: kotlin.coroutines.SuspendFunction0): kotlin.Unit declared in ' type=kotlin.Unit origin=null + sfn: TYPE_OP type=kotlin.coroutines.SuspendFunction0 origin=IMPLICIT_CAST typeOperand=kotlin.coroutines.SuspendFunction0 + GET_VAR 'var b: kotlin.Function0 [var] declared in .testSmartCastOnVarVsSuspendConversion' type=kotlin.Function0 origin=null + FUN name:testIntersectionVsSuspendConversion visibility:public modality:FINAL (x:T of .testIntersectionVsSuspendConversion) returnType:kotlin.Unit + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Function0; kotlin.coroutines.SuspendFunction0] + VALUE_PARAMETER name:x index:0 type:T of .testIntersectionVsSuspendConversion + BLOCK_BODY + CALL 'public final fun useSuspend (sfn: kotlin.coroutines.SuspendFunction0): kotlin.Unit declared in ' type=kotlin.Unit origin=null + sfn: GET_VAR 'x: T of .testIntersectionVsSuspendConversion declared in .testIntersectionVsSuspendConversion' type=T of .testIntersectionVsSuspendConversion origin=null diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index 0618cbe9124..b8a65c65017 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -1246,6 +1246,11 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { runTest("compiler/testData/ir/irText/expressions/stringTemplates.kt"); } + @TestMetadata("suspendConversionOnArbitraryExpression.kt") + public void testSuspendConversionOnArbitraryExpression() throws Exception { + runTest("compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.kt"); + } + @TestMetadata("temporaryInEnumEntryInitializer.kt") public void testTemporaryInEnumEntryInitializer() throws Exception { runTest("compiler/testData/ir/irText/expressions/temporaryInEnumEntryInitializer.kt");