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:
Ilmir Usmanov
2020-05-12 20:28:29 +02:00
parent d2a691d157
commit 0acaedef92
9 changed files with 71 additions and 2 deletions
@@ -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");
@@ -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
@@ -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)
@@ -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
}
@@ -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");
@@ -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");
@@ -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");
@@ -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");
@@ -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");