[Wasm] Do not erase interfaces down to Any type in Wasm signature.

This enables overloading virtual methods with different interface types
This commit is contained in:
Svyatoslav Kuzmich
2021-09-20 15:41:39 +03:00
parent 6db7154876
commit a2bfcfeae8
13 changed files with 93 additions and 10 deletions
@@ -16802,6 +16802,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/functions/nothisnoclosure.kt"); runTest("compiler/testData/codegen/box/functions/nothisnoclosure.kt");
} }
@Test
@TestMetadata("overloadByInterfaceType.kt")
public void testOverloadByInterfaceType() throws Exception {
runTest("compiler/testData/codegen/box/functions/overloadByInterfaceType.kt");
}
@Test @Test
@TestMetadata("prefixRecursiveCall.kt") @TestMetadata("prefixRecursiveCall.kt")
public void testPrefixRecursiveCall() throws Exception { public void testPrefixRecursiveCall() throws Exception {
@@ -255,7 +255,7 @@ class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorV
// Processing it separately // Processing it separately
if (call.symbol == wasmSymbols.boxIntrinsic) { if (call.symbol == wasmSymbols.boxIntrinsic) {
val toType = call.getTypeArgument(0)!! val toType = call.getTypeArgument(0)!!
val klass = toType.erasedUpperBound!! val klass = toType.getRuntimeClass!!
val structTypeName = context.referenceGcType(klass.symbol) val structTypeName = context.referenceGcType(klass.symbol)
val klassId = context.referenceClassId(klass.symbol) val klassId = context.referenceClassId(klass.symbol)
@@ -332,7 +332,7 @@ class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorV
} }
private fun generateTypeRTT(type: IrType) { private fun generateTypeRTT(type: IrType) {
val rtClass = type.erasedUpperBound?.symbol ?: context.backendContext.irBuiltIns.anyClass val rtClass = type.getRuntimeClass?.symbol ?: context.backendContext.irBuiltIns.anyClass
body.buildGetGlobal(context.referenceClassRTT(rtClass)) body.buildGetGlobal(context.referenceClassRTT(rtClass))
} }
@@ -47,7 +47,7 @@ class WasmTypeTransformer(
} }
fun IrType.toWasmGcRefType(): WasmType = fun IrType.toWasmGcRefType(): WasmType =
WasmRefNullType(WasmHeapType.Type(context.referenceGcType(erasedUpperBound?.symbol ?: builtIns.anyClass))) WasmRefNullType(WasmHeapType.Type(context.referenceGcType(getRuntimeClass?.symbol ?: builtIns.anyClass)))
fun IrType.toBoxedInlineClassType(): WasmType = fun IrType.toBoxedInlineClassType(): WasmType =
toWasmGcRefType() toWasmGcRefType()
@@ -111,7 +111,7 @@ class WasmTypeTransformer(
// Return null if upper bound is Any // Return null if upper bound is Any
val IrTypeParameter.erasedUpperBound: IrClass? private val IrTypeParameter.erasedUpperBound: IrClass?
get() { get() {
// Pick the (necessarily unique) non-interface upper bound if it exists // Pick the (necessarily unique) non-interface upper bound if it exists
for (type in superTypes) { for (type in superTypes) {
@@ -126,7 +126,10 @@ val IrType.erasedUpperBound: IrClass?
is IrClassSymbol -> classifier.owner is IrClassSymbol -> classifier.owner
is IrTypeParameterSymbol -> classifier.owner.erasedUpperBound is IrTypeParameterSymbol -> classifier.owner.erasedUpperBound
else -> throw IllegalStateException() else -> throw IllegalStateException()
}.let { }
val IrType.getRuntimeClass: IrClass?
get() = erasedUpperBound.let {
if (it?.isInterface == true) null if (it?.isInterface == true) null
else it else it
} }
@@ -13,9 +13,8 @@ import org.jetbrains.kotlin.backend.common.lower.at
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irNot import org.jetbrains.kotlin.backend.common.lower.irNot
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
import org.jetbrains.kotlin.backend.wasm.ir2wasm.erasedUpperBound import org.jetbrains.kotlin.backend.wasm.ir2wasm.getRuntimeClass
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.backend.js.utils.findUnitGetInstanceFunction
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
@@ -100,7 +99,7 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme
context.inlineClassesUtils.isTypeInlined(this) context.inlineClassesUtils.isTypeInlined(this)
private val IrType.erasedType: IrType private val IrType.erasedType: IrType
get() = this.erasedUpperBound?.defaultType ?: builtIns.anyType get() = this.getRuntimeClass?.defaultType ?: builtIns.anyType
private fun generateTypeCheck( private fun generateTypeCheck(
valueProvider: () -> IrExpression, valueProvider: () -> IrExpression,
@@ -1,5 +1,3 @@
// DONT_TARGET_EXACT_BACKEND: WASM
// WASM_MUTE_REASON: BRIDGE_ISSUES
public open class A<T> { public open class A<T> {
fun foo(x: T) = "O" fun foo(x: T) = "O"
fun foo(x: A<T>) = "K" fun foo(x: A<T>) = "K"
@@ -0,0 +1,35 @@
interface I1 {
fun o(): String
}
interface I2 {
fun k(): String
}
interface I {
fun foo(x: I1): I1
fun foo(x: I2): I2
}
open class C : I {
override fun foo(x: I1): I1 = x
override fun foo(x: I2): I2 = x
}
class C2 : C() {
override fun foo(x: I1): I1 = x
override fun foo(x: I2): I2 = x
}
fun box(): String {
val x: I = C2()
val o = x.foo(object : I1 {
override fun o(): String = "O"
}).o()
val k = x.foo(object : I2 {
override fun k(): String = "K"
}).k()
return o + k
}
@@ -16682,6 +16682,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/functions/nothisnoclosure.kt"); runTest("compiler/testData/codegen/box/functions/nothisnoclosure.kt");
} }
@Test
@TestMetadata("overloadByInterfaceType.kt")
public void testOverloadByInterfaceType() throws Exception {
runTest("compiler/testData/codegen/box/functions/overloadByInterfaceType.kt");
}
@Test @Test
@TestMetadata("prefixRecursiveCall.kt") @TestMetadata("prefixRecursiveCall.kt")
public void testPrefixRecursiveCall() throws Exception { public void testPrefixRecursiveCall() throws Exception {
@@ -16802,6 +16802,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/functions/nothisnoclosure.kt"); runTest("compiler/testData/codegen/box/functions/nothisnoclosure.kt");
} }
@Test
@TestMetadata("overloadByInterfaceType.kt")
public void testOverloadByInterfaceType() throws Exception {
runTest("compiler/testData/codegen/box/functions/overloadByInterfaceType.kt");
}
@Test @Test
@TestMetadata("prefixRecursiveCall.kt") @TestMetadata("prefixRecursiveCall.kt")
public void testPrefixRecursiveCall() throws Exception { public void testPrefixRecursiveCall() throws Exception {
@@ -13774,6 +13774,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/functions/nothisnoclosure.kt"); runTest("compiler/testData/codegen/box/functions/nothisnoclosure.kt");
} }
@TestMetadata("overloadByInterfaceType.kt")
public void testOverloadByInterfaceType() throws Exception {
runTest("compiler/testData/codegen/box/functions/overloadByInterfaceType.kt");
}
@TestMetadata("prefixRecursiveCall.kt") @TestMetadata("prefixRecursiveCall.kt")
public void testPrefixRecursiveCall() throws Exception { public void testPrefixRecursiveCall() throws Exception {
runTest("compiler/testData/codegen/box/functions/prefixRecursiveCall.kt"); runTest("compiler/testData/codegen/box/functions/prefixRecursiveCall.kt");
@@ -12153,6 +12153,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
runTest("compiler/testData/codegen/box/functions/nothisnoclosure.kt"); runTest("compiler/testData/codegen/box/functions/nothisnoclosure.kt");
} }
@TestMetadata("overloadByInterfaceType.kt")
public void testOverloadByInterfaceType() throws Exception {
runTest("compiler/testData/codegen/box/functions/overloadByInterfaceType.kt");
}
@TestMetadata("prefixRecursiveCall.kt") @TestMetadata("prefixRecursiveCall.kt")
public void testPrefixRecursiveCall() throws Exception { public void testPrefixRecursiveCall() throws Exception {
runTest("compiler/testData/codegen/box/functions/prefixRecursiveCall.kt"); runTest("compiler/testData/codegen/box/functions/prefixRecursiveCall.kt");
@@ -11559,6 +11559,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/functions/nothisnoclosure.kt"); runTest("compiler/testData/codegen/box/functions/nothisnoclosure.kt");
} }
@TestMetadata("overloadByInterfaceType.kt")
public void testOverloadByInterfaceType() throws Exception {
runTest("compiler/testData/codegen/box/functions/overloadByInterfaceType.kt");
}
@TestMetadata("prefixRecursiveCall.kt") @TestMetadata("prefixRecursiveCall.kt")
public void testPrefixRecursiveCall() throws Exception { public void testPrefixRecursiveCall() throws Exception {
runTest("compiler/testData/codegen/box/functions/prefixRecursiveCall.kt"); runTest("compiler/testData/codegen/box/functions/prefixRecursiveCall.kt");
@@ -11539,6 +11539,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/functions/nothisnoclosure.kt"); runTest("compiler/testData/codegen/box/functions/nothisnoclosure.kt");
} }
@TestMetadata("overloadByInterfaceType.kt")
public void testOverloadByInterfaceType() throws Exception {
runTest("compiler/testData/codegen/box/functions/overloadByInterfaceType.kt");
}
@TestMetadata("prefixRecursiveCall.kt") @TestMetadata("prefixRecursiveCall.kt")
public void testPrefixRecursiveCall() throws Exception { public void testPrefixRecursiveCall() throws Exception {
runTest("compiler/testData/codegen/box/functions/prefixRecursiveCall.kt"); runTest("compiler/testData/codegen/box/functions/prefixRecursiveCall.kt");
@@ -1295,6 +1295,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/bridges/substitutionInSuperClass/differentErasureInSuperClass.kt"); runTest("compiler/testData/codegen/box/bridges/substitutionInSuperClass/differentErasureInSuperClass.kt");
} }
@TestMetadata("differentErasureInSuperClassComplex.kt")
public void testDifferentErasureInSuperClassComplex() throws Exception {
runTest("compiler/testData/codegen/box/bridges/substitutionInSuperClass/differentErasureInSuperClassComplex.kt");
}
@TestMetadata("enum.kt") @TestMetadata("enum.kt")
public void testEnum() throws Exception { public void testEnum() throws Exception {
runTest("compiler/testData/codegen/box/bridges/substitutionInSuperClass/enum.kt"); runTest("compiler/testData/codegen/box/bridges/substitutionInSuperClass/enum.kt");
@@ -6628,6 +6633,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/functions/nothisnoclosure.kt"); runTest("compiler/testData/codegen/box/functions/nothisnoclosure.kt");
} }
@TestMetadata("overloadByInterfaceType.kt")
public void testOverloadByInterfaceType() throws Exception {
runTest("compiler/testData/codegen/box/functions/overloadByInterfaceType.kt");
}
@TestMetadata("prefixRecursiveCall.kt") @TestMetadata("prefixRecursiveCall.kt")
public void testPrefixRecursiveCall() throws Exception { public void testPrefixRecursiveCall() throws Exception {
runTest("compiler/testData/codegen/box/functions/prefixRecursiveCall.kt"); runTest("compiler/testData/codegen/box/functions/prefixRecursiveCall.kt");