diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt index 719d0c944b9..8603555cb98 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt @@ -199,12 +199,19 @@ internal val copyDefaultValuesToActualPhase = konanUnitPhase( */ internal val checkSamSuperTypesPhase = konanUnitPhase( op = { + // Handling types in current module not recursively: + // psi2ir can produce SAM conversions with variances in type arguments of type arguments. + // See https://youtrack.jetbrains.com/issue/KT-49384. + // So don't go deeper than top-level arguments to avoid the compiler emitting false-positive errors. + // Lowerings can handle this. + // Also such variances are allowed in the language for manual implementations of interfaces. irModule!!.files - .forEach { SamSuperTypesChecker(this, it, mode = SamSuperTypesChecker.Mode.THROW).run() } + .forEach { SamSuperTypesChecker(this, it, mode = SamSuperTypesChecker.Mode.THROW, recurse = false).run() } // TODO: This is temporary for handling klibs produced with earlier compiler versions. + // Handling types in dependencies recursively, just to be extra safe: don't change something that works. irModules.values .flatMap { it.files } - .forEach { SamSuperTypesChecker(this, it, mode = SamSuperTypesChecker.Mode.ERASE).run() } + .forEach { SamSuperTypesChecker(this, it, mode = SamSuperTypesChecker.Mode.ERASE, recurse = true).run() } }, name = "CheckSamSuperTypes", description = "Check SAM conversions super types" diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SamSuperTypesChecker.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SamSuperTypesChecker.kt index 7ed908b2f37..720c7c3ea21 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SamSuperTypesChecker.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SamSuperTypesChecker.kt @@ -23,7 +23,8 @@ import org.jetbrains.kotlin.types.Variance internal class SamSuperTypesChecker(private val context: Context, private val irFile: IrFile, - private val mode: Mode) { + private val mode: Mode, + private val recurse: Boolean) { enum class Mode { ERASE, THROW @@ -43,7 +44,13 @@ internal class SamSuperTypesChecker(private val context: Context, context.reportCompilationError( "Unexpected variance in super type argument: ${argument.variance} @$index", irFile, owner) } - makeTypeProjection(argument.type.eraseProjections(owner), Variance.INVARIANT) + val newArgumentType = if (recurse) { + argument.type.eraseProjections(owner) + } else { + // See the explanation at the SamSuperTypesChecker constructor call sites. + argument.type + } + makeTypeProjection(newArgumentType, Variance.INVARIANT) } } } diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index 573f90b4a4a..e691ca1d4f2 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -3181,6 +3181,10 @@ task funInterface_kt43887(type: KonanLocalTest) { source = "codegen/funInterface/kt43887.kt" } +task funInterface_kt49384(type: KonanLocalTest) { + source = "codegen/funInterface/kt49384.kt" +} + task objectExpression1(type: KonanLocalTest) { useGoldenData = true source = "codegen/objectExpression/expr1.kt" diff --git a/kotlin-native/backend.native/tests/codegen/funInterface/kt49384.kt b/kotlin-native/backend.native/tests/codegen/funInterface/kt49384.kt new file mode 100644 index 00000000000..15d46218f90 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/funInterface/kt49384.kt @@ -0,0 +1,36 @@ +/* + * 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.kt49384 + +import kotlin.test.* + +interface A + +// https://youtrack.jetbrains.com/issue/KT-49384 +class B { + init { + mutableListOf>() + .sortWith { _, _ -> 1 } + } +} + +@Test +fun test1() { + val b = B() + assertEquals(b, b) // Just to ensure B is not deleted by DCE +} + +fun interface Foo { + fun same(obj: T): T +} + +fun getSame(obj: A, foo: Foo>) = foo.same(obj) + +@Test +fun test2() { + val obj = object : A {} + assertSame(obj, getSame(obj) { it }) +}