JVM IR: IC coroutines: return boxed type from suspend function if

the function overrides function, returning type argument
 #KT-45451 Fixed
This commit is contained in:
Ilmir Usmanov
2021-03-23 20:49:08 +01:00
parent 0aca68e7c7
commit 5e6f52009f
11 changed files with 250 additions and 10 deletions
@@ -9978,6 +9978,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/boxReturnValueOfSuspendLambda.kt");
}
@Test
@TestMetadata("boxTypeParameterOfSuperType.kt")
public void testBoxTypeParameterOfSuperType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/boxTypeParameterOfSuperType.kt");
}
@Test
@TestMetadata("boxUnboxInsideCoroutine.kt")
public void testBoxUnboxInsideCoroutine() throws Exception {
@@ -10246,6 +10252,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/boxReturnValueOfSuspendLambda.kt");
}
@Test
@TestMetadata("boxTypeParameterOfSuperType.kt")
public void testBoxTypeParameterOfSuperType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/boxTypeParameterOfSuperType.kt");
}
@Test
@TestMetadata("boxUnboxInsideCoroutine.kt")
public void testBoxUnboxInsideCoroutine() throws Exception {
@@ -10514,6 +10526,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException/boxReturnValueOfSuspendLambda.kt");
}
@Test
@TestMetadata("boxTypeParameterOfSuperType.kt")
public void testBoxTypeParameterOfSuperType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException/boxTypeParameterOfSuperType.kt");
}
@Test
@TestMetadata("boxUnboxInsideCoroutine.kt")
public void testBoxUnboxInsideCoroutine() throws Exception {
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.ir.allOverridden
import org.jetbrains.kotlin.backend.common.lower.LocalDeclarationsLowering
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
import org.jetbrains.kotlin.backend.jvm.ir.isStaticInlineClassReplacement
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass
import org.jetbrains.kotlin.backend.jvm.lower.isMultifileBridge
@@ -28,10 +29,7 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.file
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.isSuspend
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.org.objectweb.asm.MethodVisitor
@@ -193,12 +191,33 @@ internal fun IrFunction.originalReturnTypeOfSuspendFunctionReturningUnboxedInlin
// Force boxing for nullable inline class types with nullable underlying type
if (returnType.isNullable() && unboxedReturnType.isNullable()) return null
// Force boxing if the function overrides function with different type modulo nullability ignoring type parameters
if ((this as? IrSimpleFunction)?.let {
it.overriddenSymbols.any { overridden ->
(overridden.owner.returnType.isNullable() && overridden.owner.returnType.makeNotNull().unboxInlineClass().isNullable()) ||
overridden.owner.returnType.makeNotNull().classOrNull != returnType.makeNotNull().classOrNull
}
} != false) return null
if ((this as? IrSimpleFunction)?.overridesReturningDifferentType(returnType) != false) return null
// Don't box other inline classes
return returnType
}
private fun IrSimpleFunction.overridesReturningDifferentType(returnType: IrType): Boolean {
val visited = hashSetOf<IrSimpleFunction>()
fun dfs(function: IrSimpleFunction): Boolean {
if (!visited.add(function)) return false
for (overridden in function.overriddenSymbols) {
val owner = overridden.owner
val overriddenReturnType = owner.returnType
if (!overriddenReturnType.erasedUpperBound.isInline) return true
if (overriddenReturnType.isNullable() &&
overriddenReturnType.makeNotNull().unboxInlineClass().isNullable()
) return true
if (overriddenReturnType.classOrNull != returnType.classOrNull) return true
if (dfs(owner)) return true
}
return false
}
return dfs(this)
}
@@ -0,0 +1,35 @@
// WITH_RUNTIME
// IGNORE_BACKEND: JVM
import kotlin.coroutines.*
interface EntityBase<out ID> {
suspend fun id(): ID
}
inline class EntityId(val value: String)
interface Entity : EntityBase<EntityId>
class EntityStub : Entity {
override suspend fun id(): EntityId = EntityId("OK")
}
suspend fun test(): EntityId {
val entity: Entity = EntityStub()
return entity.id()
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(Continuation(EmptyCoroutineContext) {
it.getOrThrow()
})
}
fun box(): String {
var res = "FAIL"
builder {
res = test().value
}
return res
}
@@ -0,0 +1,37 @@
// WITH_RUNTIME
import kotlin.coroutines.*
interface EntityBase<out ID> {
suspend fun id(): ID
}
inline class EntityId(val value: String)
interface Entity : EntityBase<EntityId>
var c: Continuation<EntityId>? = null
class EntityStub : Entity {
override suspend fun id(): EntityId = suspendCoroutine { c = it }
}
suspend fun test(): EntityId {
val entity: Entity = EntityStub()
return entity.id()
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(Continuation(EmptyCoroutineContext) {
it.getOrThrow()
})
}
fun box(): String {
var res = "FAIL"
builder {
res = test().value
}
c?.resume(EntityId("OK"))
return res
}
@@ -0,0 +1,35 @@
// WITH_RUNTIME
import kotlin.coroutines.*
interface EntityBase<out ID> {
suspend fun id(): ID
}
inline class EntityId(val value: String)
interface Entity : EntityBase<EntityId>
var res = "FAIL"
class EntityStub : Entity {
override suspend fun id(): EntityId = error("OK")
}
suspend fun test(): EntityId {
val entity: Entity = EntityStub()
return entity.id()
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(Continuation(EmptyCoroutineContext) {
res = it.exceptionOrNull()!!.message!!
})
}
fun box(): String {
builder {
test().value
}
return res
}
@@ -9978,6 +9978,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/boxReturnValueOfSuspendLambda.kt");
}
@Test
@TestMetadata("boxTypeParameterOfSuperType.kt")
public void testBoxTypeParameterOfSuperType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/boxTypeParameterOfSuperType.kt");
}
@Test
@TestMetadata("boxUnboxInsideCoroutine.kt")
public void testBoxUnboxInsideCoroutine() throws Exception {
@@ -10246,6 +10252,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/boxReturnValueOfSuspendLambda.kt");
}
@Test
@TestMetadata("boxTypeParameterOfSuperType.kt")
public void testBoxTypeParameterOfSuperType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/boxTypeParameterOfSuperType.kt");
}
@Test
@TestMetadata("boxUnboxInsideCoroutine.kt")
public void testBoxUnboxInsideCoroutine() throws Exception {
@@ -10514,6 +10526,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException/boxReturnValueOfSuspendLambda.kt");
}
@Test
@TestMetadata("boxTypeParameterOfSuperType.kt")
public void testBoxTypeParameterOfSuperType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException/boxTypeParameterOfSuperType.kt");
}
@Test
@TestMetadata("boxUnboxInsideCoroutine.kt")
public void testBoxUnboxInsideCoroutine() throws Exception {
@@ -9978,6 +9978,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/boxReturnValueOfSuspendLambda.kt");
}
@Test
@TestMetadata("boxTypeParameterOfSuperType.kt")
public void testBoxTypeParameterOfSuperType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/boxTypeParameterOfSuperType.kt");
}
@Test
@TestMetadata("boxUnboxInsideCoroutine.kt")
public void testBoxUnboxInsideCoroutine() throws Exception {
@@ -10246,6 +10252,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/boxReturnValueOfSuspendLambda.kt");
}
@Test
@TestMetadata("boxTypeParameterOfSuperType.kt")
public void testBoxTypeParameterOfSuperType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/boxTypeParameterOfSuperType.kt");
}
@Test
@TestMetadata("boxUnboxInsideCoroutine.kt")
public void testBoxUnboxInsideCoroutine() throws Exception {
@@ -10514,6 +10526,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException/boxReturnValueOfSuspendLambda.kt");
}
@Test
@TestMetadata("boxTypeParameterOfSuperType.kt")
public void testBoxTypeParameterOfSuperType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException/boxTypeParameterOfSuperType.kt");
}
@Test
@TestMetadata("boxUnboxInsideCoroutine.kt")
public void testBoxUnboxInsideCoroutine() throws Exception {
@@ -7872,6 +7872,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Direct extends AbstractLightAnalysisModeTest {
@TestMetadata("boxTypeParameterOfSuperType.kt")
public void ignoreBoxTypeParameterOfSuperType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/boxTypeParameterOfSuperType.kt");
}
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
@@ -8100,6 +8105,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Resume extends AbstractLightAnalysisModeTest {
@TestMetadata("boxTypeParameterOfSuperType.kt")
public void ignoreBoxTypeParameterOfSuperType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/boxTypeParameterOfSuperType.kt");
}
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
@@ -8328,6 +8338,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ResumeWithException extends AbstractLightAnalysisModeTest {
@TestMetadata("boxTypeParameterOfSuperType.kt")
public void ignoreBoxTypeParameterOfSuperType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException/boxTypeParameterOfSuperType.kt");
}
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
@@ -7054,6 +7054,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/boxReturnValueOfSuspendLambda.kt");
}
@TestMetadata("boxTypeParameterOfSuperType.kt")
public void testBoxTypeParameterOfSuperType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/boxTypeParameterOfSuperType.kt");
}
@TestMetadata("boxUnboxInsideCoroutine.kt")
public void testBoxUnboxInsideCoroutine() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/boxUnboxInsideCoroutine.kt");
@@ -7282,6 +7287,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/boxReturnValueOfSuspendLambda.kt");
}
@TestMetadata("boxTypeParameterOfSuperType.kt")
public void testBoxTypeParameterOfSuperType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/boxTypeParameterOfSuperType.kt");
}
@TestMetadata("boxUnboxInsideCoroutine.kt")
public void testBoxUnboxInsideCoroutine() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/boxUnboxInsideCoroutine.kt");
@@ -7510,6 +7520,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException/boxReturnValueOfSuspendLambda.kt");
}
@TestMetadata("boxTypeParameterOfSuperType.kt")
public void testBoxTypeParameterOfSuperType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException/boxTypeParameterOfSuperType.kt");
}
@TestMetadata("boxUnboxInsideCoroutine.kt")
public void testBoxUnboxInsideCoroutine() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException/boxUnboxInsideCoroutine.kt");
@@ -6475,6 +6475,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/boxReturnValueOfSuspendLambda.kt");
}
@TestMetadata("boxTypeParameterOfSuperType.kt")
public void testBoxTypeParameterOfSuperType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/boxTypeParameterOfSuperType.kt");
}
@TestMetadata("boxUnboxInsideCoroutine.kt")
public void testBoxUnboxInsideCoroutine() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/boxUnboxInsideCoroutine.kt");
@@ -6703,6 +6708,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/boxReturnValueOfSuspendLambda.kt");
}
@TestMetadata("boxTypeParameterOfSuperType.kt")
public void testBoxTypeParameterOfSuperType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/boxTypeParameterOfSuperType.kt");
}
@TestMetadata("boxUnboxInsideCoroutine.kt")
public void testBoxUnboxInsideCoroutine() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/boxUnboxInsideCoroutine.kt");
@@ -6931,6 +6941,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException/boxReturnValueOfSuspendLambda.kt");
}
@TestMetadata("boxTypeParameterOfSuperType.kt")
public void testBoxTypeParameterOfSuperType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException/boxTypeParameterOfSuperType.kt");
}
@TestMetadata("boxUnboxInsideCoroutine.kt")
public void testBoxUnboxInsideCoroutine() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException/boxUnboxInsideCoroutine.kt");
@@ -6475,6 +6475,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/boxReturnValueOfSuspendLambda.kt");
}
@TestMetadata("boxTypeParameterOfSuperType.kt")
public void testBoxTypeParameterOfSuperType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/boxTypeParameterOfSuperType.kt");
}
@TestMetadata("boxUnboxInsideCoroutine.kt")
public void testBoxUnboxInsideCoroutine() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/direct/boxUnboxInsideCoroutine.kt");
@@ -6703,6 +6708,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/boxReturnValueOfSuspendLambda.kt");
}
@TestMetadata("boxTypeParameterOfSuperType.kt")
public void testBoxTypeParameterOfSuperType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/boxTypeParameterOfSuperType.kt");
}
@TestMetadata("boxUnboxInsideCoroutine.kt")
public void testBoxUnboxInsideCoroutine() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/boxUnboxInsideCoroutine.kt");
@@ -6931,6 +6941,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException/boxReturnValueOfSuspendLambda.kt");
}
@TestMetadata("boxTypeParameterOfSuperType.kt")
public void testBoxTypeParameterOfSuperType() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException/boxTypeParameterOfSuperType.kt");
}
@TestMetadata("boxUnboxInsideCoroutine.kt")
public void testBoxUnboxInsideCoroutine() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException/boxUnboxInsideCoroutine.kt");