[IR] Fix copying of default argument from expect to actual with type parameter

^KT-45866 fixed
This commit is contained in:
Ilya Goncharov
2021-04-05 15:11:49 +03:00
committed by TeamCityServer
parent d870876822
commit b82c9225c8
12 changed files with 139 additions and 16 deletions
@@ -25182,6 +25182,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
public void testTypeAlias() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt");
}
@Test
@TestMetadata("withTypeParameter.kt")
public void testWithTypeParameter() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/withTypeParameter.kt");
}
}
@Nested
@@ -26,6 +26,8 @@ import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
// `doRemove` means should expect-declaration be removed from IR
@OptIn(ObsoleteDescriptorBasedAPI::class)
class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, private val doRemove: Boolean) : IrElementVisitorVoid {
private val typeParameterSubstitutionMap = mutableMapOf<Pair<IrFunction, IrFunction>, Map<IrTypeParameter, IrTypeParameter>>()
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
@@ -97,13 +99,29 @@ class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, private va
// the `actual fun` or `actual constructor` for this may be in a different module.
// Nothing we can do with those.
// TODO they may not actually have the defaults though -- may be a frontend bug.
val expectParameter = function.findExpectForActual()?.valueParameters?.get(index) ?: return
val expectFunction = function.findExpectForActual()
val expectParameter = expectFunction?.valueParameters?.get(index) ?: return
val defaultValue = expectParameter.defaultValue ?: return
val expectToActual = expectFunction to function
if (expectToActual !in typeParameterSubstitutionMap) {
val functionTypeParameters = collectTypeParameters(function)
val expectFunctionTypeParameters = collectTypeParameters(expectFunction)
expectFunctionTypeParameters.zip(functionTypeParameters).let { typeParametersMapping ->
typeParameterSubstitutionMap[expectToActual] = typeParametersMapping.toMap()
}
}
defaultValue.let { originalDefault ->
declaration.defaultValue = declaration.factory.createExpressionBody(originalDefault.startOffset, originalDefault.endOffset) {
expression = originalDefault.expression.deepCopyWithSymbols(function).remapExpectValueSymbols()
expression = originalDefault.expression
.deepCopyWithSymbols(function)
.remapExpectValueSymbols()
.apply {
remapTypes(IrTypeParameterRemapper(typeParameterSubstitutionMap.getValue(expectToActual)))
}
}
}
}
@@ -345,19 +345,6 @@ class InlineClassLowering(val context: CommonBackendContext) {
}
}
private fun collectTypeParameters(declaration: IrTypeParametersContainer): List<IrTypeParameter> {
val result = mutableListOf<IrTypeParameter>()
fun collectImpl(declaration: IrDeclaration) {
if (declaration is IrTypeParametersContainer) result.addAll(declaration.typeParameters)
if (declaration is IrClass && declaration.isInner) collectImpl(declaration.parent as IrDeclaration)
}
collectImpl(declaration)
return result
}
private fun createStaticBodilessMethod(function: IrFunction): IrSimpleFunction =
context.irFactory.createStaticFunctionWithReceivers(
function.parent,
@@ -602,4 +602,20 @@ internal fun <T> IrConst<T>.shallowCopy() = IrConstImpl(
type,
kind,
value
)
)
fun collectTypeParameters(declaration: IrTypeParametersContainer): List<IrTypeParameter> {
val result = mutableListOf<IrTypeParameter>()
fun collectImpl(declaration: IrDeclaration) {
if (declaration is IrTypeParametersContainer) {
result.addAll(declaration.typeParameters)
declaration.parentClassOrNull?.let { collectImpl(it) }
}
if (declaration is IrClass && declaration.isInner) collectImpl(declaration.parent as IrDeclaration)
}
collectImpl(declaration)
return result
}
@@ -0,0 +1,59 @@
// !LANGUAGE: +MultiPlatformProjects
// MODULE: lib
// FILE: common.kt
expect fun <T> topLevel(a: T, b: (T) -> Int = { 1 }): String
actual fun <T> topLevel(a: T, b: (T) -> Int): String = b(a).toString()
expect class Foo() {
fun <T> member(a: T, b: (T) -> Int = { 2 }): String
}
actual class Foo actual constructor() {
actual fun <T> member(a: T, b: (T) -> Int): String = b(a).toString()
}
expect class Bar<T>() {
fun member(a: T, b: (T) -> Int = { 3 }): String
}
actual class Bar<T> actual constructor() {
actual fun member(a: T, b: (T) -> Int): String = b(a).toString()
}
expect class A<T> {
inner class B<N> {
fun <H> foo(t: T, n: N, h: H, a: (T, N, H) -> Int = { _, _, _ -> 4 }): String
}
}
actual class A<T> {
actual inner class B<N> {
actual fun <H> foo(t: T, n: N, h: H, a: (T, N, H) -> Int) = a(t, n, h).toString()
}
}
// MODULE: main(lib)
// FILE: main.kt
import kotlin.test.assertEquals
fun box(): String {
assertEquals("1", topLevel("OK"))
assertEquals("73", topLevel("OK") { 73 })
val foo = Foo()
assertEquals("2", foo.member("OK"))
assertEquals("42", foo.member("OK") { 42 })
val bar = Bar<String>()
assertEquals("3", bar.member("OK"))
assertEquals("37", bar.member("OK") { 37 })
val b = A<Int>().B<Double>()
assertEquals("4", b.foo<Int>(1, 2.0, 3))
assertEquals("6", b.foo<Int>(1, 2.0, 3) { t, n, h -> t + n.toInt() + h })
return "OK"
}
@@ -25164,6 +25164,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
public void testTypeAlias() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt");
}
@Test
@TestMetadata("withTypeParameter.kt")
public void testWithTypeParameter() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/withTypeParameter.kt");
}
}
@Nested
@@ -25182,6 +25182,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
public void testTypeAlias() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt");
}
@Test
@TestMetadata("withTypeParameter.kt")
public void testWithTypeParameter() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/withTypeParameter.kt");
}
}
@Nested
@@ -21301,6 +21301,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
public void testTypeAlias() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt");
}
@TestMetadata("withTypeParameter.kt")
public void testWithTypeParameter() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/withTypeParameter.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/multiplatform/exhaustiveness")
@@ -16745,6 +16745,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
public void testTypeAlias() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt");
}
@TestMetadata("withTypeParameter.kt")
public void testWithTypeParameter() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/withTypeParameter.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/multiplatform/exhaustiveness")
@@ -16166,6 +16166,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
public void testTypeAlias() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt");
}
@TestMetadata("withTypeParameter.kt")
public void testWithTypeParameter() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/withTypeParameter.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/multiplatform/exhaustiveness")
@@ -16231,6 +16231,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
public void testTypeAlias() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt");
}
@TestMetadata("withTypeParameter.kt")
public void testWithTypeParameter() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/withTypeParameter.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/multiplatform/exhaustiveness")
@@ -9977,6 +9977,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
public void testTypeAlias() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt");
}
@TestMetadata("withTypeParameter.kt")
public void testWithTypeParameter() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/withTypeParameter.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/multiplatform/exhaustiveness")