[IR] Fix copying of default argument from expect to actual with type parameter
^KT-45866 fixed
This commit is contained in:
committed by
TeamCityServer
parent
d870876822
commit
b82c9225c8
+6
@@ -25182,6 +25182,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
public void testTypeAlias() throws Exception {
|
public void testTypeAlias() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt");
|
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
|
@Nested
|
||||||
|
|||||||
+20
-2
@@ -26,6 +26,8 @@ import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
|||||||
// `doRemove` means should expect-declaration be removed from IR
|
// `doRemove` means should expect-declaration be removed from IR
|
||||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||||
class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, private val doRemove: Boolean) : IrElementVisitorVoid {
|
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) {
|
override fun visitElement(element: IrElement) {
|
||||||
element.acceptChildrenVoid(this)
|
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.
|
// the `actual fun` or `actual constructor` for this may be in a different module.
|
||||||
// Nothing we can do with those.
|
// Nothing we can do with those.
|
||||||
// TODO they may not actually have the defaults though -- may be a frontend bug.
|
// 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 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 ->
|
defaultValue.let { originalDefault ->
|
||||||
declaration.defaultValue = declaration.factory.createExpressionBody(originalDefault.startOffset, originalDefault.endOffset) {
|
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)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-13
@@ -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 =
|
private fun createStaticBodilessMethod(function: IrFunction): IrSimpleFunction =
|
||||||
context.irFactory.createStaticFunctionWithReceivers(
|
context.irFactory.createStaticFunctionWithReceivers(
|
||||||
function.parent,
|
function.parent,
|
||||||
|
|||||||
@@ -603,3 +603,19 @@ internal fun <T> IrConst<T>.shallowCopy() = IrConstImpl(
|
|||||||
kind,
|
kind,
|
||||||
value
|
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
|
||||||
|
}
|
||||||
+59
@@ -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"
|
||||||
|
}
|
||||||
+6
@@ -25164,6 +25164,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
public void testTypeAlias() throws Exception {
|
public void testTypeAlias() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt");
|
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
|
@Nested
|
||||||
|
|||||||
+6
@@ -25182,6 +25182,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
public void testTypeAlias() throws Exception {
|
public void testTypeAlias() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt");
|
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
|
@Nested
|
||||||
|
|||||||
+5
@@ -21301,6 +21301,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
public void testTypeAlias() throws Exception {
|
public void testTypeAlias() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/box/multiplatform/exhaustiveness")
|
||||||
|
|||||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java
Generated
+5
@@ -16745,6 +16745,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
|||||||
public void testTypeAlias() throws Exception {
|
public void testTypeAlias() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/box/multiplatform/exhaustiveness")
|
||||||
|
|||||||
Generated
+5
@@ -16166,6 +16166,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
public void testTypeAlias() throws Exception {
|
public void testTypeAlias() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/box/multiplatform/exhaustiveness")
|
||||||
|
|||||||
Generated
+5
@@ -16231,6 +16231,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
public void testTypeAlias() throws Exception {
|
public void testTypeAlias() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/box/multiplatform/exhaustiveness")
|
||||||
|
|||||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java
Generated
+5
@@ -9977,6 +9977,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
|||||||
public void testTypeAlias() throws Exception {
|
public void testTypeAlias() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/typeAlias.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/box/multiplatform/exhaustiveness")
|
||||||
|
|||||||
Reference in New Issue
Block a user