diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/FunctionInlining.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/FunctionInlining.kt index 286868b79f6..7d2c6270051 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/FunctionInlining.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/FunctionInlining.kt @@ -258,7 +258,7 @@ class FunctionInlining( if (!isLambdaCall(expression)) return super.visitCall(expression) - val dispatchReceiver = expression.dispatchReceiver as IrGetValue + val dispatchReceiver = expression.dispatchReceiver?.unwrapAdditionalImplicitCastsIfNeeded() as IrGetValue val functionArgument = substituteMap[dispatchReceiver.symbol.owner] ?: return super.visitCall(expression) if ((dispatchReceiver.symbol.owner as? IrValueParameter)?.isNoinline == true) return super.visitCall(expression) @@ -414,6 +414,16 @@ class FunctionInlining( else IrTypeOperatorCallImpl(startOffset, endOffset, type, IrTypeOperator.IMPLICIT_CAST, type, this) + // With `insertAdditionalImplicitCasts` flag we sometimes insert + // casts to inline lambda parameters before calling `invoke` on them. + // Unwrapping these casts helps us satisfy inline lambda call detection logic. + private fun IrExpression.unwrapAdditionalImplicitCastsIfNeeded(): IrExpression { + if (insertAdditionalImplicitCasts && this is IrTypeOperatorCall && this.operator == IrTypeOperator.IMPLICIT_CAST) { + return this.argument.unwrapAdditionalImplicitCastsIfNeeded() + } + return this + } + private fun isLambdaCall(irCall: IrCall): Boolean { val callee = irCall.symbol.owner val dispatchReceiver = callee.dispatchReceiverParameter ?: return false @@ -421,7 +431,7 @@ class FunctionInlining( return (dispatchReceiver.type.isFunction() || dispatchReceiver.type.isSuspendFunction()) && callee.name == OperatorNameConventions.INVOKE - && irCall.dispatchReceiver is IrGetValue + && irCall.dispatchReceiver?.unwrapAdditionalImplicitCastsIfNeeded() is IrGetValue } private inner class ParameterToArgument( diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt index 537d4d75933..043a937fbc8 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt @@ -10,6 +10,9 @@ import org.jetbrains.kotlin.backend.common.lower import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.common.lower.coroutines.AddContinuationToNonLocalSuspendFunctionsLowering import org.jetbrains.kotlin.backend.common.lower.inline.FunctionInlining +import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesExtractionFromInlineFunctionsLowering +import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesInInlineFunctionsLowering +import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesInInlineLambdasLowering import org.jetbrains.kotlin.backend.common.lower.loops.ForLoopsLowering import org.jetbrains.kotlin.backend.common.lower.optimizations.PropertyAccessorInlineLowering import org.jetbrains.kotlin.backend.common.phaser.* @@ -110,6 +113,36 @@ private val lateinitUsageLoweringPhase = makeWasmModulePhase( description = "Insert checks for lateinit field references" ) +private val sharedVariablesLoweringPhase = makeWasmModulePhase( + ::SharedVariablesLowering, + name = "SharedVariablesLowering", + description = "Box captured mutable variables", + prerequisite = setOf( + lateinitDeclarationLoweringPhase, + lateinitUsageLoweringPhase + ) +) + +private val localClassesInInlineLambdasPhase = makeWasmModulePhase( + ::LocalClassesInInlineLambdasLowering, + name = "LocalClassesInInlineLambdasPhase", + description = "Extract local classes from inline lambdas", +) + +private val localClassesInInlineFunctionsPhase = makeWasmModulePhase( + ::LocalClassesInInlineFunctionsLowering, + name = "LocalClassesInInlineFunctionsPhase", + description = "Extract local classes from inline functions", +) + +private val localClassesExtractionFromInlineFunctionsPhase = makeWasmModulePhase( + { context -> LocalClassesExtractionFromInlineFunctionsLowering(context) }, + name = "localClassesExtractionFromInlineFunctionsPhase", + description = "Move local classes from inline functions into nearest declaration container", + prerequisite = setOf(localClassesInInlineFunctionsPhase) +) + + private val wrapInlineDeclarationsWithReifiedTypeParametersPhase = makeWasmModulePhase( ::WrapInlineDeclarationsWithReifiedTypeParametersLowering, name = "WrapInlineDeclarationsWithReifiedTypeParametersPhase", @@ -118,14 +151,20 @@ private val wrapInlineDeclarationsWithReifiedTypeParametersPhase = makeWasmModul private val functionInliningPhase = makeCustomWasmModulePhase( { context, module -> - FunctionInlining(context, null, true).inline(module) + FunctionInlining( + context = context, + innerClassesSupport = context.innerClassesSupport, + insertAdditionalImplicitCasts = true, + ).inline(module) module.patchDeclarationParents() }, name = "FunctionInliningPhase", description = "Perform function inlining", prerequisite = setOf( expectDeclarationsRemovingPhase, - wrapInlineDeclarationsWithReifiedTypeParametersPhase + wrapInlineDeclarationsWithReifiedTypeParametersPhase, + localClassesInInlineLambdasPhase, + localClassesInInlineFunctionsPhase, ) ) @@ -238,12 +277,6 @@ private val enumEntryRemovalLoweringPhase = makeWasmModulePhase( ) -private val sharedVariablesLoweringPhase = makeWasmModulePhase( - ::SharedVariablesLowering, - name = "SharedVariablesLowering", - description = "Box captured mutable variables" -) - private val propertyReferenceLowering = makeWasmModulePhase( ::WasmPropertyReferenceLowering, name = "WasmPropertyReferenceLowering", @@ -563,6 +596,14 @@ val wasmPhases = SameTypeNamedCompilerPhase( excludeDeclarationsFromCodegenPhase then expectDeclarationsRemovingPhase then + lateinitNullableFieldsPhase then + lateinitDeclarationLoweringPhase then + lateinitUsageLoweringPhase then + sharedVariablesLoweringPhase then + localClassesInInlineLambdasPhase then + localClassesInInlineFunctionsPhase then + localClassesExtractionFromInlineFunctionsPhase then + // TODO: Need some helpers from stdlib // arrayConstructorPhase then wrapInlineDeclarationsWithReifiedTypeParametersPhase then @@ -570,9 +611,6 @@ val wasmPhases = SameTypeNamedCompilerPhase( functionInliningPhase then removeInlineDeclarationsWithReifiedTypeParametersLoweringPhase then - lateinitNullableFieldsPhase then - lateinitDeclarationLoweringPhase then - lateinitUsageLoweringPhase then tailrecLoweringPhase then enumClassConstructorLoweringPhase then @@ -583,7 +621,6 @@ val wasmPhases = SameTypeNamedCompilerPhase( enumEntryCreateGetInstancesFunsLoweringPhase then enumSyntheticFunsLoweringPhase then - sharedVariablesLoweringPhase then propertyReferenceLowering then callableReferencePhase then singleAbstractMethodPhase then diff --git a/compiler/testData/codegen/box/objects/kt32351.kt b/compiler/testData/codegen/box/objects/kt32351.kt index e2c129f27a3..2f39f5b7608 100644 --- a/compiler/testData/codegen/box/objects/kt32351.kt +++ b/compiler/testData/codegen/box/objects/kt32351.kt @@ -1,6 +1,4 @@ // IGNORE_BACKEND: JVM -// IGNORE_BACKEND: WASM -// WASM_MUTE_REASON: UNKNOWN // WITH_STDLIB interface Runnable { diff --git a/compiler/testData/codegen/box/objects/kt52540.kt b/compiler/testData/codegen/box/objects/kt52540.kt index f0060f026c8..fac08aee6d6 100644 --- a/compiler/testData/codegen/box/objects/kt52540.kt +++ b/compiler/testData/codegen/box/objects/kt52540.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: WASM // MODULE: lib // FILE: lib.kt interface I { diff --git a/compiler/testData/codegen/box/reflection/classLiterals/lambdaClass.kt b/compiler/testData/codegen/box/reflection/classLiterals/lambdaClass.kt index f6123042efa..b2f1785f59a 100644 --- a/compiler/testData/codegen/box/reflection/classLiterals/lambdaClass.kt +++ b/compiler/testData/codegen/box/reflection/classLiterals/lambdaClass.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: WASM // KT-33992 class P(val a: T, val b: T) diff --git a/compiler/testData/codegen/boxInline/anonymousObject/anonymousObjectInCallChildren.kt b/compiler/testData/codegen/boxInline/anonymousObject/anonymousObjectInCallChildren.kt index 3964167098f..b75da6cf8f1 100644 --- a/compiler/testData/codegen/boxInline/anonymousObject/anonymousObjectInCallChildren.kt +++ b/compiler/testData/codegen/boxInline/anonymousObject/anonymousObjectInCallChildren.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: WASM // NO_CHECK_LAMBDA_INLINING // FILE: utils.kt diff --git a/compiler/testData/codegen/boxInline/anonymousObject/anonymousObjectInDefault.kt b/compiler/testData/codegen/boxInline/anonymousObject/anonymousObjectInDefault.kt index efd791a96c9..8fcee73bf0f 100644 --- a/compiler/testData/codegen/boxInline/anonymousObject/anonymousObjectInDefault.kt +++ b/compiler/testData/codegen/boxInline/anonymousObject/anonymousObjectInDefault.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: WASM // IGNORE_BACKEND: JVM // IGNORE_BACKEND_MULTI_MODULE: JVM, JVM_MULTI_MODULE_OLD_AGAINST_IR // NO_CHECK_LAMBDA_INLINING diff --git a/compiler/testData/codegen/boxInline/anonymousObject/capturedLocalFun.kt b/compiler/testData/codegen/boxInline/anonymousObject/capturedLocalFun.kt index 75418eeb1a4..8d1bc6618d3 100644 --- a/compiler/testData/codegen/boxInline/anonymousObject/capturedLocalFun.kt +++ b/compiler/testData/codegen/boxInline/anonymousObject/capturedLocalFun.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: WASM // IGNORE_BACKEND: JVM // IGNORE_BACKEND_MULTI_MODULE: JVM, JVM_MULTI_MODULE_OLD_AGAINST_IR // NO_CHECK_LAMBDA_INLINING diff --git a/compiler/testData/codegen/boxInline/anonymousObject/capturedLocalFunRef.kt b/compiler/testData/codegen/boxInline/anonymousObject/capturedLocalFunRef.kt index 0e93a978ddc..2599fdc2b95 100644 --- a/compiler/testData/codegen/boxInline/anonymousObject/capturedLocalFunRef.kt +++ b/compiler/testData/codegen/boxInline/anonymousObject/capturedLocalFunRef.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: WASM // NO_CHECK_LAMBDA_INLINING // FILE: 1.kt diff --git a/compiler/testData/codegen/boxInline/anonymousObject/kt52795_2.kt b/compiler/testData/codegen/boxInline/anonymousObject/kt52795_2.kt index 0fb81aa3735..7996a93eafa 100644 --- a/compiler/testData/codegen/boxInline/anonymousObject/kt52795_2.kt +++ b/compiler/testData/codegen/boxInline/anonymousObject/kt52795_2.kt @@ -1,5 +1,5 @@ // NO_CHECK_LAMBDA_INLINING -// IGNORE_BACKEND: JVM, WASM +// IGNORE_BACKEND: JVM // IGNORE_BACKEND_MULTI_MODULE: JVM, JVM_MULTI_MODULE_OLD_AGAINST_IR import kotlin.IllegalStateException diff --git a/compiler/testData/codegen/boxInline/anonymousObject/kt52795_3.kt b/compiler/testData/codegen/boxInline/anonymousObject/kt52795_3.kt index 65e4cf62cca..7939a5b219a 100644 --- a/compiler/testData/codegen/boxInline/anonymousObject/kt52795_3.kt +++ b/compiler/testData/codegen/boxInline/anonymousObject/kt52795_3.kt @@ -1,5 +1,5 @@ // NO_CHECK_LAMBDA_INLINING -// IGNORE_BACKEND: JVM, WASM +// IGNORE_BACKEND: JVM // IGNORE_BACKEND_MULTI_MODULE: JVM, JVM_MULTI_MODULE_OLD_AGAINST_IR import kotlin.IllegalStateException diff --git a/compiler/testData/codegen/boxInline/anonymousObject/kt52795_4.kt b/compiler/testData/codegen/boxInline/anonymousObject/kt52795_4.kt index 7f13d2f3304..a323475c098 100644 --- a/compiler/testData/codegen/boxInline/anonymousObject/kt52795_4.kt +++ b/compiler/testData/codegen/boxInline/anonymousObject/kt52795_4.kt @@ -1,5 +1,5 @@ // NO_CHECK_LAMBDA_INLINING -// IGNORE_BACKEND: JVM, WASM +// IGNORE_BACKEND: JVM // IGNORE_BACKEND_MULTI_MODULE: JVM, JVM_MULTI_MODULE_OLD_AGAINST_IR import kotlin.IllegalStateException diff --git a/compiler/testData/codegen/boxInline/anonymousObject/kt6007.kt b/compiler/testData/codegen/boxInline/anonymousObject/kt6007.kt index d353270a163..e944f22b853 100644 --- a/compiler/testData/codegen/boxInline/anonymousObject/kt6007.kt +++ b/compiler/testData/codegen/boxInline/anonymousObject/kt6007.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: WASM // NO_CHECK_LAMBDA_INLINING // IGNORE_BACKEND: JVM // IGNORE_BACKEND_MULTI_MODULE: JVM, JVM_MULTI_MODULE_OLD_AGAINST_IR diff --git a/compiler/testData/codegen/boxInline/anonymousObject/kt8133.kt b/compiler/testData/codegen/boxInline/anonymousObject/kt8133.kt index 379a2f9f1ac..afbe87298a7 100644 --- a/compiler/testData/codegen/boxInline/anonymousObject/kt8133.kt +++ b/compiler/testData/codegen/boxInline/anonymousObject/kt8133.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: WASM // NO_CHECK_LAMBDA_INLINING // FILE: 1.kt diff --git a/compiler/testData/codegen/boxInline/anonymousObject/typeInfo.kt b/compiler/testData/codegen/boxInline/anonymousObject/typeInfo.kt index 3f75a8b0bb8..caabd70e017 100644 --- a/compiler/testData/codegen/boxInline/anonymousObject/typeInfo.kt +++ b/compiler/testData/codegen/boxInline/anonymousObject/typeInfo.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: WASM // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/innerClasses/innerInlineFunCapturesOuter.kt b/compiler/testData/codegen/boxInline/innerClasses/innerInlineFunCapturesOuter.kt index 1388bd8190f..0c27a51a8f9 100644 --- a/compiler/testData/codegen/boxInline/innerClasses/innerInlineFunCapturesOuter.kt +++ b/compiler/testData/codegen/boxInline/innerClasses/innerInlineFunCapturesOuter.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: WASM // FILE: 1.kt class E(val x: String) { inner class Inner { diff --git a/compiler/testData/codegen/boxInline/innerClasses/innerInlineFunCapturesOuterDeep.kt b/compiler/testData/codegen/boxInline/innerClasses/innerInlineFunCapturesOuterDeep.kt index 70a2434cd65..ee8d7ee9a13 100644 --- a/compiler/testData/codegen/boxInline/innerClasses/innerInlineFunCapturesOuterDeep.kt +++ b/compiler/testData/codegen/boxInline/innerClasses/innerInlineFunCapturesOuterDeep.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: WASM // FILE: 1.kt class O(val a: String) { inner class I1(val b: String) { diff --git a/compiler/testData/codegen/boxInline/innerClasses/innerInlineFunCapturesOuterFunRef.kt b/compiler/testData/codegen/boxInline/innerClasses/innerInlineFunCapturesOuterFunRef.kt index cd11db25a6b..bd0777c6030 100644 --- a/compiler/testData/codegen/boxInline/innerClasses/innerInlineFunCapturesOuterFunRef.kt +++ b/compiler/testData/codegen/boxInline/innerClasses/innerInlineFunCapturesOuterFunRef.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: WASM // FILE: 1.kt class E(val x: String) { fun bar() = x diff --git a/compiler/testData/codegen/boxInline/innerClasses/innerInlineFunCapturesOuterWithInlineClass.kt b/compiler/testData/codegen/boxInline/innerClasses/innerInlineFunCapturesOuterWithInlineClass.kt index eff243614f5..97741615816 100644 --- a/compiler/testData/codegen/boxInline/innerClasses/innerInlineFunCapturesOuterWithInlineClass.kt +++ b/compiler/testData/codegen/boxInline/innerClasses/innerInlineFunCapturesOuterWithInlineClass.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: WASM // FILE: 1.kt class E(val x: T) { inner class Inner { diff --git a/compiler/testData/codegen/boxInline/innerClasses/kt12126.kt b/compiler/testData/codegen/boxInline/innerClasses/kt12126.kt index a9c29bb72dd..aec5d0eec7c 100644 --- a/compiler/testData/codegen/boxInline/innerClasses/kt12126.kt +++ b/compiler/testData/codegen/boxInline/innerClasses/kt12126.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: WASM // IGNORE_BACKEND: JVM // IGNORE_BACKEND_MULTI_MODULE: JVM, JVM_MULTI_MODULE_IR_AGAINST_OLD // FILE: a.kt diff --git a/compiler/testData/codegen/boxInline/localFunInLambda/defaultParam.kt b/compiler/testData/codegen/boxInline/localFunInLambda/defaultParam.kt index d3d17ed1c76..6b7933fb1db 100644 --- a/compiler/testData/codegen/boxInline/localFunInLambda/defaultParam.kt +++ b/compiler/testData/codegen/boxInline/localFunInLambda/defaultParam.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: WASM // NO_CHECK_LAMBDA_INLINING // FILE: 1.kt