diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionReferenceLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionReferenceLowering.kt index bf9893cc4c5..43397307ce8 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionReferenceLowering.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionReferenceLowering.kt @@ -32,10 +32,13 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.types.impl.buildSimpleType +import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.types.Variance internal class FunctionReferenceLowering(val context: Context): FileLoweringPass { @@ -89,6 +92,21 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass return result } + // TODO: Move to common IR utils. + fun IrType.eraseProjections(): IrType { + if (this !is IrSimpleType) return this + return buildSimpleType { + this.classifier = this@eraseProjections.classifier + this.hasQuestionMark = this@eraseProjections.hasQuestionMark + this.annotations = this@eraseProjections.annotations + this.arguments = this@eraseProjections.arguments.map { + if (it !is IrTypeProjection) + it + else makeTypeProjection(it.type.eraseProjections(), Variance.INVARIANT) + } + } + } + // Handle SAM conversions which wrap a function reference: // class sam$n(private val receiver: R) : Interface { override fun method(...) = receiver.target(...) } // @@ -111,7 +129,7 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass return super.visitTypeOperator(expression) } reference.transformChildrenVoid() - return transformFunctionReference(reference, expression.typeOperand) + return transformFunctionReference(reference, expression.typeOperand.eraseProjections()) } return super.visitTypeOperator(expression) } diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index fb5363322d1..651e75282ce 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -2881,6 +2881,10 @@ task funInterface_implIsNotFunction(type: KonanLocalTest) { source = "codegen/funInterface/implIsNotFunction.kt" } +task funInterface_nonTrivialProjectionInSuperType(type: KonanLocalTest) { + source = "codegen/funInterface/nonTrivialProjectionInSuperType.kt" +} + task objectExpression1(type: KonanLocalTest) { goldValue = "aabb\n" source = "codegen/objectExpression/expr1.kt" diff --git a/kotlin-native/backend.native/tests/codegen/funInterface/nonTrivialProjectionInSuperType.kt b/kotlin-native/backend.native/tests/codegen/funInterface/nonTrivialProjectionInSuperType.kt new file mode 100644 index 00000000000..29b97a9874f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/funInterface/nonTrivialProjectionInSuperType.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.funInterface.nonTrivialProjectionInSuperType + +import kotlin.test.* + +fun foo(comparator: kotlin.Comparator, a: T, b: T) = comparator.compare(a, b) + +fun bar(x: Int, y: Int) = foo ({ a, b -> a - b}, x, y) + +@Test +fun test() { + assertTrue(bar(42, 117) < 0) +} \ No newline at end of file