Fix attribute clash between STATIC_INLINE_CLASS_REPLACEMENT and original
Attributes are used to name continuation classes and are generated before inline classes processing. During the processing, for override functions in inlined classes, the compiler generates STATIC_INLINE_CLASS_REPLACEMENT function with body of the override. The override's body is replaced with delegating call to STATIC_INLINE_CLASS_REPLACEMENT. However, since we need to keep the name of the continuation class, we copy attributes from the override to STATIC_INLINE_CLASS_REPLACEMENT. This leads to attribute clash during AddContinuationLowering. So, to fix the issue, do not use the attribute of STATIC_INLINE_CLASS_REPLACEMENT in original->suspend map. As an optimization, do not generate continuation for the override function.
This commit is contained in:
Generated
+5
@@ -6994,6 +6994,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/interfaceMethodWithBodyGeneric.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("overrideInInlineClass.kt")
|
||||
public void testOverrideInInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("safeCallOnTwoReceiversLong.kt")
|
||||
public void testSafeCallOnTwoReceiversLong_1_3() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/safeCallOnTwoReceiversLong.kt", "kotlin.coroutines");
|
||||
|
||||
+7
-1
@@ -117,6 +117,11 @@ private fun IrFunction.isBridgeToSuspendImplMethod(): Boolean =
|
||||
it.name.asString() == name.asString() + SUSPEND_IMPL_NAME_SUFFIX && it.attributeOwnerId == attributeOwnerId
|
||||
}
|
||||
|
||||
private fun IrFunction.isStaticInlineClassReplacementDelegatingCall(): Boolean =
|
||||
this is IrAttributeContainer && origin != JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_REPLACEMENT &&
|
||||
parentAsClass.declarations.find { it is IrAttributeContainer && it.attributeOwnerId == attributeOwnerId && it !== this }
|
||||
?.origin == JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_REPLACEMENT
|
||||
|
||||
internal fun IrFunction.shouldContainSuspendMarkers(): Boolean = !isInvokeSuspendOfContinuation() &&
|
||||
// These are tail-call bridges and do not require any bytecode modifications.
|
||||
origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER &&
|
||||
@@ -129,7 +134,8 @@ internal fun IrFunction.shouldContainSuspendMarkers(): Boolean = !isInvokeSuspen
|
||||
origin != IrDeclarationOrigin.BRIDGE_SPECIAL &&
|
||||
origin != IrDeclarationOrigin.DELEGATED_MEMBER &&
|
||||
!isInvokeOfSuspendCallableReference() &&
|
||||
!isBridgeToSuspendImplMethod()
|
||||
!isBridgeToSuspendImplMethod() &&
|
||||
!isStaticInlineClassReplacementDelegatingCall()
|
||||
|
||||
internal fun IrFunction.hasContinuation(): Boolean = isSuspend && shouldContainSuspendMarkers() &&
|
||||
// This is inline-only function
|
||||
|
||||
+3
-1
@@ -640,7 +640,9 @@ private fun IrFunction.suspendFunctionViewOrStub(context: JvmBackendContext): Ir
|
||||
}
|
||||
|
||||
internal fun IrFunction.suspendFunctionOriginal(): IrFunction =
|
||||
if (this is IrSimpleFunction && isSuspend) attributeOwnerId as IrFunction else this
|
||||
if (this is IrSimpleFunction && isSuspend && origin != JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_REPLACEMENT)
|
||||
attributeOwnerId as IrFunction
|
||||
else this
|
||||
|
||||
private fun IrFunction.createSuspendFunctionStub(context: JvmBackendContext): IrFunction {
|
||||
require(this.isSuspend && this is IrSimpleFunction)
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
import kotlin.coroutines.*
|
||||
import helpers.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
class Delegate {
|
||||
fun build(): String = "OK"
|
||||
}
|
||||
|
||||
interface Digest {
|
||||
suspend fun build(): String
|
||||
}
|
||||
|
||||
inline class DigestImpl(val delegate: Delegate) : Digest {
|
||||
override suspend fun build(): String = delegate.build()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var res = "FAIL"
|
||||
val digest: Digest = DigestImpl(Delegate())
|
||||
builder {
|
||||
res = digest.build()
|
||||
}
|
||||
return res
|
||||
}
|
||||
+5
@@ -7594,6 +7594,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/interfaceMethodWithBodyGeneric.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("overrideInInlineClass.kt")
|
||||
public void testOverrideInInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("safeCallOnTwoReceiversLong.kt")
|
||||
public void testSafeCallOnTwoReceiversLong_1_2() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/safeCallOnTwoReceiversLong.kt", "kotlin.coroutines.experimental");
|
||||
|
||||
+5
@@ -7594,6 +7594,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/interfaceMethodWithBodyGeneric.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("overrideInInlineClass.kt")
|
||||
public void testOverrideInInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("safeCallOnTwoReceiversLong.kt")
|
||||
public void testSafeCallOnTwoReceiversLong_1_2() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/safeCallOnTwoReceiversLong.kt", "kotlin.coroutines.experimental");
|
||||
|
||||
+5
@@ -6994,6 +6994,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/interfaceMethodWithBodyGeneric.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("overrideInInlineClass.kt")
|
||||
public void testOverrideInInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("safeCallOnTwoReceiversLong.kt")
|
||||
public void testSafeCallOnTwoReceiversLong_1_3() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/safeCallOnTwoReceiversLong.kt", "kotlin.coroutines");
|
||||
|
||||
Generated
+5
@@ -5904,6 +5904,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/interfaceMethodWithBodyGeneric.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("overrideInInlineClass.kt")
|
||||
public void testOverrideInInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("safeCallOnTwoReceiversLong.kt")
|
||||
public void testSafeCallOnTwoReceiversLong_1_3() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/safeCallOnTwoReceiversLong.kt", "kotlin.coroutines");
|
||||
|
||||
+5
@@ -5904,6 +5904,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/interfaceMethodWithBodyGeneric.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("overrideInInlineClass.kt")
|
||||
public void testOverrideInInlineClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInlineClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("safeCallOnTwoReceiversLong.kt")
|
||||
public void testSafeCallOnTwoReceiversLong_1_3() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/safeCallOnTwoReceiversLong.kt", "kotlin.coroutines");
|
||||
|
||||
Reference in New Issue
Block a user