diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt index 5fc732ff529..9b470f5bb51 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt @@ -494,13 +494,27 @@ class AnonymousObjectTransformer( //For all inlined lambdas add their captured parameters //TODO: some of such parameters could be skipped - we should perform additional analysis - val capturedLambdasToInline = HashMap() //captured var of inlined parameter val allRecapturedParameters = ArrayList() - val addCapturedNotAddOuter = - parentFieldRemapper.isRoot || parentFieldRemapper is InlinedLambdaRemapper && parentFieldRemapper.parent!!.isRoot - val alreadyAdded = HashMap() - for (info in capturedLambdas) { - if (addCapturedNotAddOuter) { + if (parentFieldRemapper !is InlinedLambdaRemapper || parentFieldRemapper.parent!!.isRoot) { + // Possible cases: + // + // 1. Top-level object in an inline lambda that is *not* being inlined into another object. In this case, we + // have no choice but to add a separate field for each captured variable. `capturedLambdas` is either empty + // (already have the fields) or contains the parent lambda object (captures used to be read from it, but + // the object will be removed and its contents inlined). + // + // 2. Top-level object in a named inline function. Again, there's no option but to add separate fields. + // `capturedLambdas` contains all lambdas used by this object and nested objects. + // + // 3. Nested object, either in an inline lambda or an inline function. This case has two subcases: + // * The object's captures are passed as separate arguments (e.g. KT-28064 style object that used to be in a lambda); + // we could group them into `this$0` now, but choose not to. Lambdas are replaced by their captures. + // * The object's captures are already grouped into `this$0`; this includes captured lambda parameters (for objects in + // inline functions) and a reference to the outer object or lambda (for objects in lambdas), so `capturedLambdas` is + // empty and the choice doesn't matter. + // + val alreadyAdded = HashMap() + for (info in capturedLambdas) { for (desc in info.capturedVars) { val key = desc.fieldName + "$$$" + desc.type.className val alreadyAddedParam = alreadyAdded[key] @@ -532,11 +546,10 @@ class AnonymousObjectTransformer( } } } - capturedLambdasToInline.put(info.lambdaClassType.internalName, info) - } - - if (parentFieldRemapper is InlinedLambdaRemapper && !capturedLambdas.isEmpty() && !addCapturedNotAddOuter) { - //lambda with non InlinedLambdaRemapper already have outer + } else if (capturedLambdas.isNotEmpty()) { + // Top-level object in a lambda inlined into another object. As already said above, either `capturedLambdas` is empty + // (no captures or captures were generated as loose fields) or it contains a single entry for the parent lambda itself. + // Simply replace one `this$0` (of lambda type) with another (of destination object type). val parent = parentFieldRemapper.parent as? RegeneratedLambdaFieldRemapper ?: throw AssertionError("Expecting RegeneratedLambdaFieldRemapper, but ${parentFieldRemapper.parent}") val ownerType = Type.getObjectType(parent.originalLambdaInternalName) @@ -550,7 +563,7 @@ class AnonymousObjectTransformer( } transformationInfo.allRecapturedParameters = allRecapturedParameters - transformationInfo.capturedLambdasToInline = capturedLambdasToInline + transformationInfo.capturedLambdasToInline = capturedLambdas.associateBy { it.lambdaClassType.internalName } return constructorAdditionalFakeParams } diff --git a/compiler/testData/codegen/boxInline/anonymousObject/defineClass.kt b/compiler/testData/codegen/boxInline/anonymousObject/defineClass.kt index a8caa4d1e97..788602e4de7 100644 --- a/compiler/testData/codegen/boxInline/anonymousObject/defineClass.kt +++ b/compiler/testData/codegen/boxInline/anonymousObject/defineClass.kt @@ -1,5 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_MULTI_MODULE: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/anonymousObject/properRecapturing/inlineChain.kt b/compiler/testData/codegen/boxInline/anonymousObject/properRecapturing/inlineChain.kt index 5e29220edef..ff2504b3164 100644 --- a/compiler/testData/codegen/boxInline/anonymousObject/properRecapturing/inlineChain.kt +++ b/compiler/testData/codegen/boxInline/anonymousObject/properRecapturing/inlineChain.kt @@ -1,5 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_MULTI_MODULE: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/anonymousObject/properRecapturingInClass/inlineChain.kt b/compiler/testData/codegen/boxInline/anonymousObject/properRecapturingInClass/inlineChain.kt index ebb81f56176..324fa7fb4b2 100644 --- a/compiler/testData/codegen/boxInline/anonymousObject/properRecapturingInClass/inlineChain.kt +++ b/compiler/testData/codegen/boxInline/anonymousObject/properRecapturingInClass/inlineChain.kt @@ -1,5 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_MULTI_MODULE: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/anonymousObject/properRecapturingInClass/noCapturedThisOnCallSite.kt b/compiler/testData/codegen/boxInline/anonymousObject/properRecapturingInClass/noCapturedThisOnCallSite.kt index ef81b2b6b9f..867a8a040bb 100644 --- a/compiler/testData/codegen/boxInline/anonymousObject/properRecapturingInClass/noCapturedThisOnCallSite.kt +++ b/compiler/testData/codegen/boxInline/anonymousObject/properRecapturingInClass/noCapturedThisOnCallSite.kt @@ -1,5 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_MULTI_MODULE: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/anonymousObject/properRecapturingInClass/twoInlineLambdaComplex.kt b/compiler/testData/codegen/boxInline/anonymousObject/properRecapturingInClass/twoInlineLambdaComplex.kt index 7f672a0cdde..2459a2f67e6 100644 --- a/compiler/testData/codegen/boxInline/anonymousObject/properRecapturingInClass/twoInlineLambdaComplex.kt +++ b/compiler/testData/codegen/boxInline/anonymousObject/properRecapturingInClass/twoInlineLambdaComplex.kt @@ -1,5 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_MULTI_MODULE: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/anonymousObject/properRecapturingInClass/twoInlineLambdaComplex_2.kt b/compiler/testData/codegen/boxInline/anonymousObject/properRecapturingInClass/twoInlineLambdaComplex_2.kt index eac9babc926..472657d058b 100644 --- a/compiler/testData/codegen/boxInline/anonymousObject/properRecapturingInClass/twoInlineLambdaComplex_2.kt +++ b/compiler/testData/codegen/boxInline/anonymousObject/properRecapturingInClass/twoInlineLambdaComplex_2.kt @@ -1,5 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_MULTI_MODULE: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/builders/buildersAndLambdaCapturing.kt b/compiler/testData/codegen/boxInline/builders/buildersAndLambdaCapturing.kt index 7c10156b035..e52fd9a3e72 100644 --- a/compiler/testData/codegen/boxInline/builders/buildersAndLambdaCapturing.kt +++ b/compiler/testData/codegen/boxInline/builders/buildersAndLambdaCapturing.kt @@ -1,5 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_MULTI_MODULE: JVM_IR // TARGET_BACKEND: JVM // FILE: 1.kt // WITH_RUNTIME diff --git a/compiler/testData/codegen/boxInline/enclosingInfo/transformedConstructorWithAdditionalObject.kt b/compiler/testData/codegen/boxInline/enclosingInfo/transformedConstructorWithAdditionalObject.kt index e449650bb4e..b453fa0cf19 100644 --- a/compiler/testData/codegen/boxInline/enclosingInfo/transformedConstructorWithAdditionalObject.kt +++ b/compiler/testData/codegen/boxInline/enclosingInfo/transformedConstructorWithAdditionalObject.kt @@ -1,5 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_MULTI_MODULE: JVM_IR // TARGET_BACKEND: JVM // FILE: 1.kt // WITH_REFLECT diff --git a/compiler/testData/codegen/boxInline/noInline/noInlineLambdaChainWithCapturedInline.kt b/compiler/testData/codegen/boxInline/noInline/noInlineLambdaChainWithCapturedInline.kt index 258177f4002..133f57d8324 100644 --- a/compiler/testData/codegen/boxInline/noInline/noInlineLambdaChainWithCapturedInline.kt +++ b/compiler/testData/codegen/boxInline/noInline/noInlineLambdaChainWithCapturedInline.kt @@ -1,5 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_MULTI_MODULE: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/bytecodeText/kt10259_2.kt b/compiler/testData/codegen/bytecodeText/kt10259_2.kt index 727fe26fb55..a7bf15def8d 100644 --- a/compiler/testData/codegen/bytecodeText/kt10259_2.kt +++ b/compiler/testData/codegen/bytecodeText/kt10259_2.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR fun box(): String { var encl1 = "fail"; test {