From 9182f2c796328090aa968b3627696e35dfdee887 Mon Sep 17 00:00:00 2001 From: pyos Date: Fri, 15 Nov 2019 14:14:01 +0100 Subject: [PATCH] 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. --- .../ir/util/ExpectDeclarationRemover.kt | 27 +++++++++++-------- ...annotationsViaActualTypeAliasFromBinary.kt | 1 - .../expectClassActualTypeAlias.kt | 12 +++++++++ ...mpileKotlinAgainstKotlinTestGenerated.java | 5 ++++ ...mpileKotlinAgainstKotlinTestGenerated.java | 5 ++++ 5 files changed, 38 insertions(+), 12 deletions(-) create mode 100644 compiler/testData/compileKotlinAgainstKotlin/expectClassActualTypeAlias.kt diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExpectDeclarationRemover.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExpectDeclarationRemover.kt index 1c05b6318f4..36a507c7631 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExpectDeclarationRemover.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExpectDeclarationRemover.kt @@ -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 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] } } diff --git a/compiler/testData/codegen/boxAgainstJava/multiplatform/annotationsViaActualTypeAliasFromBinary.kt b/compiler/testData/codegen/boxAgainstJava/multiplatform/annotationsViaActualTypeAliasFromBinary.kt index 37a619d9caa..635fb7d069a 100644 --- a/compiler/testData/codegen/boxAgainstJava/multiplatform/annotationsViaActualTypeAliasFromBinary.kt +++ b/compiler/testData/codegen/boxAgainstJava/multiplatform/annotationsViaActualTypeAliasFromBinary.kt @@ -1,5 +1,4 @@ // !LANGUAGE: +MultiPlatformProjects -// IGNORE_BACKEND: JVM_IR // WITH_REFLECT // FILE: main.kt diff --git a/compiler/testData/compileKotlinAgainstKotlin/expectClassActualTypeAlias.kt b/compiler/testData/compileKotlinAgainstKotlin/expectClassActualTypeAlias.kt new file mode 100644 index 00000000000..3403bcc23f0 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstKotlin/expectClassActualTypeAlias.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 +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java index 565bc8398f2..befc0040d17 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstKotlinTestGenerated.java index 2e08ff5b94a..fcfa7d7944c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstKotlinTestGenerated.java @@ -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");