Obtain original suspend function view for inline codegen

It's necessary for generic inline suspend as a codegen
for it uses binding slice SUSPEND_FUNCTION_TO_JVM_VIEW
to generate fake continuation parameter, so all the
descriptors that are used for body generation must be
obtained from the SUSPEND_FUNCTION_TO_JVM_VIEW

 #KT-19528 Fixed
This commit is contained in:
Denis Zharkov
2017-08-23 15:30:20 +03:00
parent abb07ced6d
commit aef5911c7e
8 changed files with 129 additions and 1 deletions
@@ -2352,7 +2352,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
if (!isInline) return defaultCallGenerator;
FunctionDescriptor original =
unwrapInitialSignatureDescriptor(DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal()));
CoroutineCodegenUtilKt.getOriginalSuspendFunctionView(
unwrapInitialSignatureDescriptor(DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal())),
bindingContext
);
if (isDefaultCompilation) {
return new InlineCodegenForDefaultBody(original, this, state, new PsiSourceCompilerForInline(this, callElement));
}
@@ -291,6 +291,13 @@ fun createMethodNodeForSuspendCoroutineOrReturn(
fun <D : CallableDescriptor?> D.unwrapInitialDescriptorForSuspendFunction(): D =
this.safeAs<SimpleFunctionDescriptor>()?.getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION) as D ?: this
fun FunctionDescriptor.getOriginalSuspendFunctionView(bindingContext: BindingContext): FunctionDescriptor =
if (isSuspend)
getOrCreateJvmSuspendFunctionView(unwrapInitialDescriptorForSuspendFunction().original, bindingContext)
else
this
fun InstructionAdapter.loadCoroutineSuspendedMarker() {
invokestatic(
COROUTINES_INTRINSICS_FILE_FACADE_INTERNAL_NAME.internalName,
@@ -0,0 +1,31 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
suspend fun suspendThere(v: Any?): String = suspendCoroutineOrReturn { x ->
x.resume(v?.toString() ?: "<empty>")
COROUTINE_SUSPENDED
}
class A<T>(val arg: T) {
var result = ""
inline suspend fun foo() {
result = suspendThere(arg)
}
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
val a = A<String>("OK")
builder {
a.foo()
}
return a.result
}
@@ -0,0 +1,39 @@
// WITH_RUNTIME
// WITH_COROUTINES
// WITH_REFLECT
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
suspend fun suspendThere(v: String): String = suspendCoroutineOrReturn { x ->
x.resume(v)
COROUTINE_SUSPENDED
}
suspend fun foo(x: suspend () -> String): String = x()
abstract class A {
inline suspend fun <reified T : Any> baz(): String {
return foo {
suspendThere(T::class.simpleName!!)
}
}
}
class B : A() {
suspend fun bar(): String {
return baz<OK>()
}
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
class OK
fun box(): String {
var result = "fail"
builder {
result = B().bar()
}
return result
}
@@ -5171,6 +5171,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
doTest(fileName);
}
@TestMetadata("inlineFunInGenericClass.kt")
public void testInlineFunInGenericClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/inlineFunInGenericClass.kt");
doTest(fileName);
}
@TestMetadata("inlineGenericFunCalledFromSubclass.kt")
public void testInlineGenericFunCalledFromSubclass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/inlineGenericFunCalledFromSubclass.kt");
doTest(fileName);
}
@TestMetadata("inlineSuspendFunction.kt")
public void testInlineSuspendFunction() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/inlineSuspendFunction.kt");
@@ -5171,6 +5171,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("inlineFunInGenericClass.kt")
public void testInlineFunInGenericClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/inlineFunInGenericClass.kt");
doTest(fileName);
}
@TestMetadata("inlineGenericFunCalledFromSubclass.kt")
public void testInlineGenericFunCalledFromSubclass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/inlineGenericFunCalledFromSubclass.kt");
doTest(fileName);
}
@TestMetadata("inlineSuspendFunction.kt")
public void testInlineSuspendFunction() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/inlineSuspendFunction.kt");
@@ -5171,6 +5171,18 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
doTest(fileName);
}
@TestMetadata("inlineFunInGenericClass.kt")
public void testInlineFunInGenericClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/inlineFunInGenericClass.kt");
doTest(fileName);
}
@TestMetadata("inlineGenericFunCalledFromSubclass.kt")
public void testInlineGenericFunCalledFromSubclass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/inlineGenericFunCalledFromSubclass.kt");
doTest(fileName);
}
@TestMetadata("inlineSuspendFunction.kt")
public void testInlineSuspendFunction() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/inlineSuspendFunction.kt");
@@ -5879,6 +5879,18 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
doTest(fileName);
}
@TestMetadata("inlineFunInGenericClass.kt")
public void testInlineFunInGenericClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/inlineFunInGenericClass.kt");
doTest(fileName);
}
@TestMetadata("inlineGenericFunCalledFromSubclass.kt")
public void testInlineGenericFunCalledFromSubclass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/inlineGenericFunCalledFromSubclass.kt");
doTest(fileName);
}
@TestMetadata("inlineSuspendFunction.kt")
public void testInlineSuspendFunction() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/inlineSuspendFunction.kt");