IR: don't attempt to move defaults to actual in another module
May happen when a function in an `expect` class is aliased through an `actual typealias`; the matching declaration is filtered out in `ExpectedActualResolver.findActualForExpected` as it has no source.
This commit is contained in:
@@ -63,7 +63,12 @@ class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, private va
|
||||
return
|
||||
}
|
||||
|
||||
val actualParameter = function.findActualForExpected().valueParameters[index]
|
||||
// If the containing declaration is an `expect class` that matches an `actual typealias`,
|
||||
// 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 actualFunction = function.findActualForExpected() ?: return
|
||||
val actualParameter = actualFunction.valueParameters[index]
|
||||
|
||||
// Keep actual default value if present. They are generally not allowed but can be suppressed with
|
||||
// @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
|
||||
@@ -79,19 +84,19 @@ class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, private va
|
||||
})
|
||||
}
|
||||
|
||||
private fun IrFunction.findActualForExpected(): IrFunction =
|
||||
symbolTable.referenceFunction(descriptor.findActualForExpect()).owner
|
||||
private fun IrFunction.findActualForExpected(): IrFunction? =
|
||||
descriptor.findActualForExpect()?.let { symbolTable.referenceFunction(it).owner }
|
||||
|
||||
private fun IrClass.findActualForExpected(): IrClass =
|
||||
symbolTable.referenceClass(descriptor.findActualForExpect()).owner
|
||||
private fun IrClass.findActualForExpected(): IrClass? =
|
||||
descriptor.findActualForExpect()?.let { symbolTable.referenceClass(it).owner }
|
||||
|
||||
private inline fun <reified T : MemberDescriptor> T.findActualForExpect() = with(ExpectedActualResolver) {
|
||||
val descriptor = this@findActualForExpect
|
||||
|
||||
if (!descriptor.isExpect) error(this)
|
||||
|
||||
findCompatibleActualForExpected(descriptor.module).singleOrNull() ?: error(descriptor)
|
||||
} as T
|
||||
findCompatibleActualForExpected(descriptor.module).singleOrNull()
|
||||
} as T?
|
||||
|
||||
private fun IrExpression.remapExpectValueSymbols(): IrExpression {
|
||||
return this.transform(object : IrElementTransformerVoid() {
|
||||
@@ -123,17 +128,17 @@ class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, private va
|
||||
return when (parent) {
|
||||
is IrClass -> {
|
||||
assert(parameter == parent.thisReceiver)
|
||||
parent.findActualForExpected().thisReceiver!!
|
||||
parent.findActualForExpected()!!.thisReceiver!!
|
||||
}
|
||||
|
||||
is IrFunction -> when (parameter) {
|
||||
parent.dispatchReceiverParameter ->
|
||||
parent.findActualForExpected().dispatchReceiverParameter!!
|
||||
parent.findActualForExpected()!!.dispatchReceiverParameter!!
|
||||
parent.extensionReceiverParameter ->
|
||||
parent.findActualForExpected().extensionReceiverParameter!!
|
||||
parent.findActualForExpected()!!.extensionReceiverParameter!!
|
||||
else -> {
|
||||
assert(parent.valueParameters[parameter.index] == parameter)
|
||||
parent.findActualForExpected().valueParameters[parameter.index]
|
||||
parent.findActualForExpected()!!.valueParameters[parameter.index]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vendored
-1
@@ -1,5 +1,4 @@
|
||||
// !LANGUAGE: +MultiPlatformProjects
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// WITH_REFLECT
|
||||
// FILE: main.kt
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// !LANGUAGE: +MultiPlatformProjects
|
||||
// FILE: impl.kt
|
||||
class A(val result: String = "OK")
|
||||
|
||||
// FILE: multiplatform.kt
|
||||
expect class B(result: String = "FAIL")
|
||||
|
||||
actual typealias B = A
|
||||
|
||||
fun box(): String {
|
||||
return B().result
|
||||
}
|
||||
+5
@@ -128,6 +128,11 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/enum.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("expectClassActualTypeAlias.kt")
|
||||
public void testExpectClassActualTypeAlias() throws Exception {
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/expectClassActualTypeAlias.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClassFromBinaryDependencies.kt")
|
||||
public void testInlineClassFromBinaryDependencies() throws Exception {
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassFromBinaryDependencies.kt");
|
||||
|
||||
Generated
+5
@@ -123,6 +123,11 @@ public class IrCompileKotlinAgainstKotlinTestGenerated extends AbstractIrCompile
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/enum.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("expectClassActualTypeAlias.kt")
|
||||
public void testExpectClassActualTypeAlias() throws Exception {
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/expectClassActualTypeAlias.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClassFromBinaryDependencies.kt")
|
||||
public void testInlineClassFromBinaryDependencies() throws Exception {
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassFromBinaryDependencies.kt");
|
||||
|
||||
Reference in New Issue
Block a user