diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 9d55cf9411b..3d60102ef85 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -9795,6 +9795,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInlineClass.kt"); } + @Test + @TestMetadata("overrideInInnerClass.kt") + public void testOverrideInInnerClass() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInnerClass.kt"); + } + @Test @TestMetadata("safeCallOnTwoReceivers.kt") public void testSafeCallOnTwoReceivers() throws Exception { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AddContinuationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AddContinuationLowering.kt index efe84944121..4511e16dfc6 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AddContinuationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AddContinuationLowering.kt @@ -226,6 +226,44 @@ private class AddContinuationLowering(context: JvmBackendContext) : SuspendLower copyMetadata = false ) static.body = irFunction.moveBodyTo(static) + // Fixup dispatch parameter to outer class + if (irFunction.parentAsClass.isInner) { + val movedDispatchParameter = static.valueParameters[0] + assert(movedDispatchParameter.origin == IrDeclarationOrigin.MOVED_DISPATCH_RECEIVER) { + "MOVED_DISPATCH_RECEIVER should be the first parameter in ${static.render()}" + } + static.body!!.transformChildrenVoid(object : IrElementTransformerVoid() { + override fun visitGetValue(expression: IrGetValue): IrExpression { + val owner = expression.symbol.owner + if (owner is IrValueParameter && isInstanceReceiverOfOuterClass(owner)) { + // If inner class has inner classes, we need to traverse this$0 chain to get to captured dispatch receivers + var cursor = irFunction.parentAsClass + var value: IrExpression = IrGetValueImpl(expression.startOffset, expression.endOffset, movedDispatchParameter.symbol) + while (cursor != owner.parent) { + val outerThisField = context.innerClassesSupport.getOuterThisField(cursor) + value = IrGetFieldImpl( + expression.startOffset, expression.endOffset, outerThisField.symbol, outerThisField.type, value + ) + cursor = cursor.parentAsClass + } + return value + } + return super.visitGetValue(expression) + } + + private fun isInstanceReceiverOfOuterClass(param: IrValueParameter): Boolean { + if (param.origin != IrDeclarationOrigin.INSTANCE_RECEIVER) return false + if (param.parent !is IrClass) return false + + var cursor = irFunction.parentAsClass.parent + while (cursor is IrClass) { + if (cursor == param.parent) return true + cursor = (cursor as IrClass).parent + } + return false + } + }) + } static.copyAttributes(irFunction) // Rewrite the body of the original suspend method to forward to the new static method. irFunction.body = context.createIrBuilder(irFunction.symbol).irBlockBody { diff --git a/compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInnerClass.kt b/compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInnerClass.kt new file mode 100644 index 00000000000..9ee59ba5dfe --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInnerClass.kt @@ -0,0 +1,47 @@ +// WITH_RUNTIME + +import kotlin.coroutines.* + +class B { + val value: Long = 10L + + open inner class C : A { + override suspend fun getTotalFrames(): Long? = this@B.value + + open inner class D : A { + override suspend fun getTotalFrames(): Long? = this@B.value + } + + suspend fun getInnerTotalFrames(): Long? = D().getTotalFrames() + } + + suspend fun get1(): Long? { + return C().getTotalFrames() + } + + suspend fun get2(): Long? = C().getInnerTotalFrames() +} + +interface A { + suspend fun getTotalFrames(): Long? = null +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(Continuation(EmptyCoroutineContext) { + it.getOrThrow() + }) +} + +fun box(): String { + var res = "FAIL" + builder { + res = if (B().get1() == 10L) "OK" else "FAIL 1 ${B().get1()}" + } + if (res != "OK") return res + + res = "FAIL 2" + builder { + res = if (B().get2() == 10L) "OK" else "FAIL 2 ${B().get2()}" + } + return res +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index c4a18c418be..9885a35d822 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -9795,6 +9795,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInlineClass.kt"); } + @Test + @TestMetadata("overrideInInnerClass.kt") + public void testOverrideInInnerClass() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInnerClass.kt"); + } + @Test @TestMetadata("safeCallOnTwoReceivers.kt") public void testSafeCallOnTwoReceivers() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 1e7c041a16d..083309a475a 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -9795,6 +9795,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInlineClass.kt"); } + @Test + @TestMetadata("overrideInInnerClass.kt") + public void testOverrideInInnerClass() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInnerClass.kt"); + } + @Test @TestMetadata("safeCallOnTwoReceivers.kt") public void testSafeCallOnTwoReceivers() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 3bf1d321e38..c38102b815b 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -7695,6 +7695,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInlineClass.kt"); } + @TestMetadata("overrideInInnerClass.kt") + public void testOverrideInInnerClass() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInnerClass.kt"); + } + @TestMetadata("safeCallOnTwoReceivers.kt") public void testSafeCallOnTwoReceivers() throws Exception { runTest("compiler/testData/codegen/box/coroutines/featureIntersection/safeCallOnTwoReceivers.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 22cdbf80bf9..99eddeb7630 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -6879,6 +6879,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInlineClass.kt"); } + @TestMetadata("overrideInInnerClass.kt") + public void testOverrideInInnerClass() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInnerClass.kt"); + } + @TestMetadata("safeCallOnTwoReceivers.kt") public void testSafeCallOnTwoReceivers() throws Exception { runTest("compiler/testData/codegen/box/coroutines/featureIntersection/safeCallOnTwoReceivers.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 9d4c9726b2c..4f651ed923e 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -6290,6 +6290,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInlineClass.kt"); } + @TestMetadata("overrideInInnerClass.kt") + public void testOverrideInInnerClass() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInnerClass.kt"); + } + @TestMetadata("safeCallOnTwoReceivers.kt") public void testSafeCallOnTwoReceivers() throws Exception { runTest("compiler/testData/codegen/box/coroutines/featureIntersection/safeCallOnTwoReceivers.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 444c18b4adc..24806287aa2 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -6290,6 +6290,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInlineClass.kt"); } + @TestMetadata("overrideInInnerClass.kt") + public void testOverrideInInnerClass() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInnerClass.kt"); + } + @TestMetadata("safeCallOnTwoReceivers.kt") public void testSafeCallOnTwoReceivers() throws Exception { runTest("compiler/testData/codegen/box/coroutines/featureIntersection/safeCallOnTwoReceivers.kt");