Fix bridge generation for inline classes over Any type

This commit is contained in:
Mikhail Zarechenskiy
2018-07-17 14:04:20 +03:00
parent 4811757d8d
commit 77959247d2
9 changed files with 262 additions and 28 deletions
@@ -195,8 +195,11 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
erasedInterfaceFunction = samType.getOriginalAbstractMethod();
}
List<KotlinType> bridgeParameterKotlinTypes = CollectionsKt.map(erasedInterfaceFunction.getValueParameters(), ValueDescriptor::getType);
generateBridge(
typeMapper.mapAsmMethod(erasedInterfaceFunction),
bridgeParameterKotlinTypes,
erasedInterfaceFunction.getReturnType(),
typeMapper.mapAsmMethod(funDescriptor),
funDescriptor.getReturnType(),
@@ -269,6 +272,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
protected void generateBridge(
@NotNull Method bridge,
@NotNull List<KotlinType> bridgeParameterKotlinTypes,
@Nullable KotlinType bridgeReturnType,
@NotNull Method delegate,
@Nullable KotlinType delegateReturnType,
@@ -287,13 +291,16 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
InstructionAdapter iv = new InstructionAdapter(mv);
MemberCodegen.markLineNumberForDescriptor(DescriptorUtils.getParentOfType(funDescriptor, ClassDescriptor.class), iv);
Type[] myParameterTypes = bridge.getArgumentTypes();
Type[] bridgeParameterTypes = bridge.getArgumentTypes();
if (isVarargInvoke) {
assert myParameterTypes.length == 1 && myParameterTypes[0].equals(AsmUtil.getArrayType(OBJECT_TYPE)) :
assert bridgeParameterTypes.length == 1 && bridgeParameterTypes[0].equals(AsmUtil.getArrayType(OBJECT_TYPE)) :
"Vararg invoke must have one parameter of type [Ljava/lang/Object;: " + bridge;
generateVarargInvokeArityAssert(iv, delegate.getArgumentTypes().length);
}
assert bridgeParameterTypes.length == bridgeParameterKotlinTypes.size() :
"Asm parameter types should be the same length as Kotlin parameter types";
iv.load(0, asmType);
List<ParameterDescriptor> calleeParameters = CollectionsKt.plus(
@@ -308,12 +315,14 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
StackValue value;
if (isVarargInvoke) {
value = StackValue.arrayElement(
OBJECT_TYPE, null, StackValue.local(1, myParameterTypes[0], parameterType), StackValue.constant(i)
OBJECT_TYPE, null,
StackValue.local(1, bridgeParameterTypes[0], bridgeParameterKotlinTypes.get(0)),
StackValue.constant(i)
);
}
else {
Type type = myParameterTypes[i];
value = StackValue.local(slot, type, parameterType);
Type type = bridgeParameterTypes[i];
value = StackValue.local(slot, type, bridgeParameterKotlinTypes.get(i));
slot += type.getSize();
}
value.put(typeMapper.mapType(calleeParameter), parameterType, iv);
@@ -224,10 +224,19 @@ class CoroutineCodegenForLambda private constructor(
if (allFunctionParameters().size <= 1) {
val delegate = typeMapper.mapSignatureSkipGeneric(createCoroutineDescriptor).asmMethod
val bridgeParameters = (1 until delegate.argumentTypes.size).map { AsmTypes.OBJECT_TYPE } + delegate.argumentTypes.last()
val bridge = Method(delegate.name, delegate.returnType, bridgeParameters.toTypedArray())
val bridgeParameterAsmTypes =
List(delegate.argumentTypes.size - 1) { AsmTypes.OBJECT_TYPE } + delegate.argumentTypes.last()
generateBridge(bridge, createCoroutineDescriptor.returnType, delegate, createCoroutineDescriptor.returnType, false)
val bridgeParameterKotlinTypes =
List(delegate.argumentTypes.size - 1) { builtIns.nullableAnyType } + createCoroutineDescriptor.valueParameters.last().type
val bridge = Method(delegate.name, delegate.returnType, bridgeParameterAsmTypes.toTypedArray())
generateBridge(
bridge, bridgeParameterKotlinTypes, createCoroutineDescriptor.returnType,
delegate, createCoroutineDescriptor.returnType,
false
)
}
}
@@ -0,0 +1,46 @@
// IGNORE_BACKEND: JS_IR, JVM_IR
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
import helpers.*
import COROUTINES_PACKAGE.*
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
@Suppress("UNSUPPORTED_FEATURE")
inline class SuccessOrFailure<T>(val a: Any?) {
fun getOrThrow(): T = a as T
}
abstract class SuccessOrFailureReceiver<T> {
abstract suspend fun receive(result: SuccessOrFailure<T>)
}
fun <T> SuccessOrFailureReceiver(f: (SuccessOrFailure<T>) -> Unit): SuccessOrFailureReceiver<T> =
object : SuccessOrFailureReceiver<T>() {
override suspend fun receive(result: SuccessOrFailure<T>) {
f(result)
}
}
fun test() {
var invoked = false
val receiver = SuccessOrFailureReceiver<Int> { result ->
val intResult = result.getOrThrow()
invoked = true
}
builder {
receiver.receive(SuccessOrFailure(42))
}
if (!invoked) {
throw RuntimeException("Fail")
}
}
fun box(): String {
test()
return "OK"
}
@@ -0,0 +1,35 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR
inline class SuccessOrFailure<T>(val a: Any?) {
fun getOrThrow(): T = a as T
}
abstract class SuccessOrFailureReceiver<T> {
abstract fun receive(result: SuccessOrFailure<T>)
}
fun <T> SuccessOrFailureReceiver(f: (SuccessOrFailure<T>) -> Unit): SuccessOrFailureReceiver<T> =
object : SuccessOrFailureReceiver<T>() {
override fun receive(result: SuccessOrFailure<T>) {
f(result)
}
}
fun test() {
var invoked = false
val receiver = SuccessOrFailureReceiver<Int> { result ->
val intResult = result.getOrThrow()
invoked = true
}
receiver.receive(SuccessOrFailure(42))
if (!invoked) {
throw RuntimeException("Fail")
}
}
fun box(): String {
test()
return "OK"
}
@@ -6578,6 +6578,33 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class InlineClasses extends AbstractIrBlackBoxCodegenTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath);
}
private void runTestWithPackageReplacement(String testDataFilePath, String packageName) throws Exception {
KotlinTestUtils.runTest(filePath -> doTestWithCoroutinesPackageReplacement(filePath, packageName), TargetBackend.JVM_IR, testDataFilePath);
}
public void testAllFilesPresentInInlineClasses() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
}
@TestMetadata("bridgeGenerationNonInline.kt")
public void testBridgeGenerationNonInline_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/inlineClasses/bridgeGenerationNonInline.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("bridgeGenerationNonInline.kt")
public void testBridgeGenerationNonInline_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/inlineClasses/bridgeGenerationNonInline.kt", "kotlin.coroutines");
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/intLikeVarSpilling")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -11069,6 +11096,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/inlineClasses/boxUnboxOfInlineClassForCapturedVars.kt");
}
@TestMetadata("bridgeGenerationWithInlineClassOverAny.kt")
public void testBridgeGenerationWithInlineClassOverAny() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/bridgeGenerationWithInlineClassOverAny.kt");
}
@TestMetadata("bridgesWhenInlineClassImplementsGenericInterface.kt")
public void testBridgesWhenInlineClassImplementsGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/bridgesWhenInlineClassImplementsGenericInterface.kt");
@@ -6578,6 +6578,33 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class InlineClasses extends AbstractBlackBoxCodegenTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
private void runTestWithPackageReplacement(String testDataFilePath, String packageName) throws Exception {
KotlinTestUtils.runTest(filePath -> doTestWithCoroutinesPackageReplacement(filePath, packageName), TargetBackend.JVM, testDataFilePath);
}
public void testAllFilesPresentInInlineClasses() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("bridgeGenerationNonInline.kt")
public void testBridgeGenerationNonInline_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/inlineClasses/bridgeGenerationNonInline.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("bridgeGenerationNonInline.kt")
public void testBridgeGenerationNonInline_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/inlineClasses/bridgeGenerationNonInline.kt", "kotlin.coroutines");
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/intLikeVarSpilling")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -11069,6 +11096,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/inlineClasses/boxUnboxOfInlineClassForCapturedVars.kt");
}
@TestMetadata("bridgeGenerationWithInlineClassOverAny.kt")
public void testBridgeGenerationWithInlineClassOverAny() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/bridgeGenerationWithInlineClassOverAny.kt");
}
@TestMetadata("bridgesWhenInlineClassImplementsGenericInterface.kt")
public void testBridgesWhenInlineClassImplementsGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/bridgesWhenInlineClassImplementsGenericInterface.kt");
@@ -6578,6 +6578,33 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class InlineClasses extends AbstractLightAnalysisModeTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
private void runTestWithPackageReplacement(String testDataFilePath, String packageName) throws Exception {
KotlinTestUtils.runTest(filePath -> doTestWithCoroutinesPackageReplacement(filePath, packageName), TargetBackend.JVM, testDataFilePath);
}
public void testAllFilesPresentInInlineClasses() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("bridgeGenerationNonInline.kt")
public void testBridgeGenerationNonInline_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/inlineClasses/bridgeGenerationNonInline.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("bridgeGenerationNonInline.kt")
public void testBridgeGenerationNonInline_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/inlineClasses/bridgeGenerationNonInline.kt", "kotlin.coroutines");
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/intLikeVarSpilling")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -11069,6 +11096,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/inlineClasses/boxUnboxOfInlineClassForCapturedVars.kt");
}
@TestMetadata("bridgeGenerationWithInlineClassOverAny.kt")
public void testBridgeGenerationWithInlineClassOverAny() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/bridgeGenerationWithInlineClassOverAny.kt");
}
@TestMetadata("bridgesWhenInlineClassImplementsGenericInterface.kt")
public void testBridgesWhenInlineClassImplementsGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/bridgesWhenInlineClassImplementsGenericInterface.kt");
@@ -1567,11 +1567,6 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/callableReference/bound/array.kt");
}
@TestMetadata("boundJvmFieldInInterfaceCompanion.kt")
public void testBoundJvmFieldInInterfaceCompanion() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/boundJvmFieldInInterfaceCompanion.kt");
}
@TestMetadata("companionObjectReceiver.kt")
public void testCompanionObjectReceiver() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/companionObjectReceiver.kt");
@@ -5693,6 +5688,28 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class InlineClasses extends AbstractIrJsCodegenBoxTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
private void runTestWithPackageReplacement(String testDataFilePath, String packageName) throws Exception {
KotlinTestUtils.runTest0(filePath -> doTestWithCoroutinesPackageReplacement(filePath, packageName), TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInInlineClasses() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("bridgeGenerationNonInline.kt")
public void testBridgeGenerationNonInline_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/inlineClasses/bridgeGenerationNonInline.kt", "kotlin.coroutines.experimental");
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/intLikeVarSpilling")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -9719,6 +9736,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/boxUnboxOfInlineClassForCapturedVars.kt");
}
@TestMetadata("bridgeGenerationWithInlineClassOverAny.kt")
public void testBridgeGenerationWithInlineClassOverAny() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/bridgeGenerationWithInlineClassOverAny.kt");
}
@TestMetadata("bridgesWhenInlineClassImplementsGenericInterface.kt")
public void testBridgesWhenInlineClassImplementsGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/bridgesWhenInlineClassImplementsGenericInterface.kt");
@@ -16561,11 +16583,6 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/reflection/properties/javaStaticField.kt");
}
@TestMetadata("jvmFieldInInterfaceCompanion.kt")
public void testJvmFieldInInterfaceCompanion() throws Exception {
runTest("compiler/testData/codegen/box/reflection/properties/jvmFieldInInterfaceCompanion.kt");
}
@TestMetadata("kotlinPropertyInheritedInJava.kt")
public void testKotlinPropertyInheritedInJava() throws Exception {
runTest("compiler/testData/codegen/box/reflection/properties/kotlinPropertyInheritedInJava.kt");
@@ -1587,11 +1587,6 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/callableReference/bound/array.kt");
}
@TestMetadata("boundJvmFieldInInterfaceCompanion.kt")
public void testBoundJvmFieldInInterfaceCompanion() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/boundJvmFieldInInterfaceCompanion.kt");
}
@TestMetadata("companionObjectReceiver.kt")
public void testCompanionObjectReceiver() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/companionObjectReceiver.kt");
@@ -6308,6 +6303,33 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class InlineClasses extends AbstractJsCodegenBoxTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
}
private void runTestWithPackageReplacement(String testDataFilePath, String packageName) throws Exception {
KotlinTestUtils.runTest0(filePath -> doTestWithCoroutinesPackageReplacement(filePath, packageName), TargetBackend.JS, testDataFilePath);
}
public void testAllFilesPresentInInlineClasses() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
}
@TestMetadata("bridgeGenerationNonInline.kt")
public void testBridgeGenerationNonInline_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/inlineClasses/bridgeGenerationNonInline.kt", "kotlin.coroutines.experimental");
}
@TestMetadata("bridgeGenerationNonInline.kt")
public void testBridgeGenerationNonInline_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/inlineClasses/bridgeGenerationNonInline.kt", "kotlin.coroutines");
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/intLikeVarSpilling")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -10714,6 +10736,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/boxUnboxOfInlineClassForCapturedVars.kt");
}
@TestMetadata("bridgeGenerationWithInlineClassOverAny.kt")
public void testBridgeGenerationWithInlineClassOverAny() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/bridgeGenerationWithInlineClassOverAny.kt");
}
@TestMetadata("bridgesWhenInlineClassImplementsGenericInterface.kt")
public void testBridgesWhenInlineClassImplementsGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/bridgesWhenInlineClassImplementsGenericInterface.kt");
@@ -17556,11 +17583,6 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/reflection/properties/javaStaticField.kt");
}
@TestMetadata("jvmFieldInInterfaceCompanion.kt")
public void testJvmFieldInInterfaceCompanion() throws Exception {
runTest("compiler/testData/codegen/box/reflection/properties/jvmFieldInInterfaceCompanion.kt");
}
@TestMetadata("kotlinPropertyInheritedInJava.kt")
public void testKotlinPropertyInheritedInJava() throws Exception {
runTest("compiler/testData/codegen/box/reflection/properties/kotlinPropertyInheritedInJava.kt");