diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SingleAbstractMethodLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SingleAbstractMethodLowering.kt index c05c9f19f9d..611ebb77411 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SingleAbstractMethodLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SingleAbstractMethodLowering.kt @@ -21,11 +21,9 @@ import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.declarations.* import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrGetValue -import org.jetbrains.kotlin.ir.expressions.IrTypeOperator -import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall +import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl +import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.types.isNullable @@ -58,9 +56,9 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) : // Coming from the frontend, every SAM interface is associated with exactly one function type // (see SamType.getKotlinFunctionType). This is why we can cache implementations just based on // the superType. - private val cachedImplementations = mutableMapOf() - private val inlineCachedImplementations = mutableMapOf() - private var enclosingContainer: IrDeclarationContainer? = null + protected val cachedImplementations = mutableMapOf() + protected val inlineCachedImplementations = mutableMapOf() + protected var enclosingContainer: IrDeclarationContainer? = null abstract fun getWrapperVisibility(expression: IrTypeOperatorCall, scopes: List): Visibility @@ -81,6 +79,10 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) : } } + protected open fun currentScopeSymbol(): IrSymbol? { + return currentScope?.scope?.scopeOwnerSymbol + } + override fun visitClassNew(declaration: IrClass): IrStatement { val prevContainer = enclosingContainer if (prevContainer == null || prevContainer is IrFile) @@ -99,7 +101,7 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) : val erasedSuperType = getSuperTypeForWrapper(expression.typeOperand) val superType = if (expression.typeOperand.isNullable()) erasedSuperType.makeNullable() else erasedSuperType val invokable = expression.argument.transform(this, null) - context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol).apply { + context.createIrBuilder(currentScopeSymbol()!!).apply { // Do not generate a wrapper class for null, it has no invoke() anyway. if (invokable.isNullConst()) return invokable diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt index 8b7bfe650b3..ebde00d7df1 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt @@ -521,11 +521,11 @@ private val bridgesConstructionPhase = makeDeclarationTransformerPhase( prerequisite = setOf(suspendFunctionsLoweringPhase) ) -private val singleAbstractMethodPhase = makeJsModulePhase( +private val singleAbstractMethodPhase = makeBodyLoweringPhase( ::JsSingleAbstractMethodLowering, name = "SingleAbstractMethod", description = "Replace SAM conversions with instances of interface-implementing classes" -).toModuleLowering() +) private val typeOperatorLoweringPhase = makeBodyLoweringPhase( ::TypeOperatorLowering, diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsSingleAbstractMethodLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsSingleAbstractMethodLowering.kt index 2a1b3d6d148..5f30c6d3ff9 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsSingleAbstractMethodLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsSingleAbstractMethodLowering.kt @@ -5,22 +5,55 @@ package org.jetbrains.kotlin.ir.backend.js.lower -import org.jetbrains.kotlin.backend.common.ScopeWithIr +import org.jetbrains.kotlin.backend.common.BodyLoweringPass import org.jetbrains.kotlin.backend.common.lower.SingleAbstractMethodLowering +import org.jetbrains.kotlin.backend.common.ScopeWithIr import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.IrBody +import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.types.defaultType +import org.jetbrains.kotlin.ir.util.file +import org.jetbrains.kotlin.ir.util.parentClassOrNull import org.jetbrains.kotlin.ir.util.render -class JsSingleAbstractMethodLowering(context: JsIrBackendContext) : SingleAbstractMethodLowering(context) { +class JsSingleAbstractMethodLowering(context: JsIrBackendContext) : SingleAbstractMethodLowering(context), BodyLoweringPass { + override fun getWrapperVisibility(expression: IrTypeOperatorCall, scopes: List): Visibility { return Visibilities.PRIVATE } + private var enclosingBodyContainer: IrDeclaration? = null + + override fun lower(irFile: IrFile) { + super.lower(irFile) + } + + override fun lower(irBody: IrBody, container: IrDeclaration) { + cachedImplementations.clear() + inlineCachedImplementations.clear() + enclosingContainer = container.parentClassOrNull ?: container.file + enclosingBodyContainer = container + + irBody.transformChildrenVoid() + + for (wrapper in cachedImplementations.values + inlineCachedImplementations.values) { + val parentClass = wrapper.parent as IrDeclarationContainer + stageController.unrestrictDeclarationListsAccess { + parentClass.declarations += wrapper + } + } + } + + override fun currentScopeSymbol(): IrSymbol? { + return super.currentScopeSymbol() ?: (enclosingBodyContainer as? IrSymbolOwner)?.symbol + } + override fun getSuperTypeForWrapper(typeOperand: IrType): IrType { // FE doesn't allow type parameters for now. // And since there is a to-do in common SingleAbstractMethodLowering (at function visitTypeOperator), diff --git a/compiler/testData/codegen/box/funInterface/basicFunInterfaceConversion.kt b/compiler/testData/codegen/box/funInterface/basicFunInterfaceConversion.kt index 8baf88358f2..b13d2bb2e25 100644 --- a/compiler/testData/codegen/box/funInterface/basicFunInterfaceConversion.kt +++ b/compiler/testData/codegen/box/funInterface/basicFunInterfaceConversion.kt @@ -1,5 +1,4 @@ // !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions -// SKIP_DCE_DRIVEN fun interface Foo { fun invoke(): String diff --git a/compiler/testData/codegen/box/funInterface/basicFunInterfaceConversionClash.kt b/compiler/testData/codegen/box/funInterface/basicFunInterfaceConversionClash.kt index accf83cdd5b..ea1368517af 100644 --- a/compiler/testData/codegen/box/funInterface/basicFunInterfaceConversionClash.kt +++ b/compiler/testData/codegen/box/funInterface/basicFunInterfaceConversionClash.kt @@ -1,5 +1,4 @@ // !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions -// SKIP_DCE_DRIVEN // FILE: lib.kt diff --git a/compiler/testData/codegen/box/funInterface/castFromAny.kt b/compiler/testData/codegen/box/funInterface/castFromAny.kt index 423dfdb28f9..51db56520e0 100644 --- a/compiler/testData/codegen/box/funInterface/castFromAny.kt +++ b/compiler/testData/codegen/box/funInterface/castFromAny.kt @@ -1,5 +1,4 @@ // !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions -// SKIP_DCE_DRIVEN fun interface KRunnable { diff --git a/compiler/testData/codegen/box/funInterface/equality/simpleLambdas.kt b/compiler/testData/codegen/box/funInterface/equality/simpleLambdas.kt index 1e1bd2bcdbd..f70e3d5608a 100644 --- a/compiler/testData/codegen/box/funInterface/equality/simpleLambdas.kt +++ b/compiler/testData/codegen/box/funInterface/equality/simpleLambdas.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR fun interface FunInterface { fun invoke() diff --git a/compiler/testData/codegen/box/funInterface/funConversionInVararg.kt b/compiler/testData/codegen/box/funInterface/funConversionInVararg.kt index 034ba4e0093..5741ce3e58b 100644 --- a/compiler/testData/codegen/box/funInterface/funConversionInVararg.kt +++ b/compiler/testData/codegen/box/funInterface/funConversionInVararg.kt @@ -1,6 +1,5 @@ // !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument // IGNORE_BACKEND_FIR: JVM_IR -// SKIP_DCE_DRIVEN fun interface MyRunnable { fun run() diff --git a/compiler/testData/codegen/box/funInterface/funInterfaceInheritance.kt b/compiler/testData/codegen/box/funInterface/funInterfaceInheritance.kt index cd114b5c31e..81a3e135b25 100644 --- a/compiler/testData/codegen/box/funInterface/funInterfaceInheritance.kt +++ b/compiler/testData/codegen/box/funInterface/funInterfaceInheritance.kt @@ -1,5 +1,4 @@ // !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions -// SKIP_DCE_DRIVEN fun interface Base { fun doStuff(): String @@ -27,4 +26,4 @@ fun box(): String { if (runProxy { 10 } != "10") return "fail2" return runBase { "OK" } -} +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/funInterface/funInterfaceWithReceiver.kt b/compiler/testData/codegen/box/funInterface/funInterfaceWithReceiver.kt index 3c19e4fb9fb..6b628186bef 100644 --- a/compiler/testData/codegen/box/funInterface/funInterfaceWithReceiver.kt +++ b/compiler/testData/codegen/box/funInterface/funInterfaceWithReceiver.kt @@ -1,6 +1,5 @@ // IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND: JS_IR_ES6 -// SKIP_DCE_DRIVEN fun interface FunWithReceiver { fun String.foo(): String diff --git a/compiler/testData/codegen/box/funInterface/inlinedSamWrapper.kt b/compiler/testData/codegen/box/funInterface/inlinedSamWrapper.kt index 97cd9b4ecfe..30e520ea6dc 100644 --- a/compiler/testData/codegen/box/funInterface/inlinedSamWrapper.kt +++ b/compiler/testData/codegen/box/funInterface/inlinedSamWrapper.kt @@ -1,6 +1,5 @@ // !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions // WITH_RUNTIME -// SKIP_DCE_DRIVEN fun interface MyRunnable { fun invoke() diff --git a/compiler/testData/codegen/box/funInterface/multimodule.kt b/compiler/testData/codegen/box/funInterface/multimodule.kt index c1eef7d5aac..764eb3d1e68 100644 --- a/compiler/testData/codegen/box/funInterface/multimodule.kt +++ b/compiler/testData/codegen/box/funInterface/multimodule.kt @@ -1,5 +1,4 @@ // !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions -// SKIP_DCE_DRIVEN // MODULE: m1 // FILE: m1.kt diff --git a/compiler/testData/codegen/box/funInterface/nonAbstractMethod.kt b/compiler/testData/codegen/box/funInterface/nonAbstractMethod.kt index b77615ddd35..e190edbd2dc 100644 --- a/compiler/testData/codegen/box/funInterface/nonAbstractMethod.kt +++ b/compiler/testData/codegen/box/funInterface/nonAbstractMethod.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR interface I { fun inherited(s: String): String = privateInherited(s) diff --git a/compiler/testData/codegen/box/funInterface/nullableSam.kt b/compiler/testData/codegen/box/funInterface/nullableSam.kt index 24671f1f00b..ce5456238ab 100644 --- a/compiler/testData/codegen/box/funInterface/nullableSam.kt +++ b/compiler/testData/codegen/box/funInterface/nullableSam.kt @@ -1,6 +1,5 @@ // !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions // WITH_RUNTIME -// SKIP_DCE_DRIVEN fun interface KRunnable { fun invoke() diff --git a/compiler/testData/codegen/box/funInterface/partialSam.kt b/compiler/testData/codegen/box/funInterface/partialSam.kt index 0ec67f087a0..f33c10526c2 100644 --- a/compiler/testData/codegen/box/funInterface/partialSam.kt +++ b/compiler/testData/codegen/box/funInterface/partialSam.kt @@ -1,6 +1,5 @@ // !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions // WITH_RUNTIME -// SKIP_DCE_DRIVEN fun interface Fn { fun run(s: String, i: Int, t: T): R diff --git a/compiler/testData/codegen/box/funInterface/primitiveConversions.kt b/compiler/testData/codegen/box/funInterface/primitiveConversions.kt index 6f7e7bf9d2a..5ef596ad9d8 100644 --- a/compiler/testData/codegen/box/funInterface/primitiveConversions.kt +++ b/compiler/testData/codegen/box/funInterface/primitiveConversions.kt @@ -1,7 +1,5 @@ // !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions -// SKIP_DCE_DRIVEN - // This test should check argument coercion between the SAM and the lambda. // For now it checks that Char is boxed in JS diff --git a/compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt b/compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt index 9de5c1e8b20..d23a0636950 100644 --- a/compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt +++ b/compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt @@ -1,6 +1,5 @@ // !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions // WITH_RUNTIME -// SKIP_DCE_DRIVEN fun interface KRunnable { fun invoke() diff --git a/compiler/testData/codegen/box/funInterface/samConstructorExplicitInvocation.kt b/compiler/testData/codegen/box/funInterface/samConstructorExplicitInvocation.kt index 4c896ed2de4..03b20212dd4 100644 --- a/compiler/testData/codegen/box/funInterface/samConstructorExplicitInvocation.kt +++ b/compiler/testData/codegen/box/funInterface/samConstructorExplicitInvocation.kt @@ -1,5 +1,4 @@ // !LANGUAGE: +FunctionalInterfaceConversion -// SKIP_DCE_DRIVEN fun interface S { fun invoke(): String diff --git a/compiler/testData/codegen/box/funInterface/suspendFunInterfaceConversionCodegen.kt b/compiler/testData/codegen/box/funInterface/suspendFunInterfaceConversionCodegen.kt index 124d76de391..04c6bae74a0 100644 --- a/compiler/testData/codegen/box/funInterface/suspendFunInterfaceConversionCodegen.kt +++ b/compiler/testData/codegen/box/funInterface/suspendFunInterfaceConversionCodegen.kt @@ -1,7 +1,6 @@ // !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions // WITH_COROUTINES // WITH_RUNTIME -// SKIP_DCE_DRIVEN import helpers.* import kotlin.coroutines.*