IR: fix SAM conversion for types with contravariant intersection argument type
In the added test, the problem was that the SAM type as computed by
`SamTypeFactory.createByValueParameter` was `Consumer<{BaseClass &
BaseInterface}>`, which was latter approximated in psi2ir during the
KotlinType->IrType conversion to `Consumer<out Any?>` (here:
https://github.com/JetBrains/kotlin/blob/3034d9d791cf1f9033104e12448e0d262d3bc3ce/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt#L606),
because intersection type argument is approximated to `out Any?`.
To avoid this, replace intersection type in immediate arguments of a SAM
type with the common supertype of its components at the same place where
we're getting rid of projections.
#KT-45945 Fixed
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
// IGNORE_BACKEND: WASM
|
||||
// WASM_MUTE_REASON: SAM_CONVERSIONS
|
||||
|
||||
// CHECK_BYTECODE_TEXT
|
||||
// 0 java/lang/invoke/LambdaMetafactory
|
||||
|
||||
abstract class BaseClass
|
||||
interface BaseInterface
|
||||
|
||||
class ConcreteType : BaseClass(), BaseInterface
|
||||
class ConcreteType2 : BaseClass(), BaseInterface
|
||||
|
||||
fun box(): String {
|
||||
example(0)
|
||||
return "OK"
|
||||
}
|
||||
|
||||
fun example(input: Int) {
|
||||
val instance = when (input) {
|
||||
0 -> GenericHolder<ConcreteType>()
|
||||
else -> GenericHolder<ConcreteType2>()
|
||||
}
|
||||
|
||||
instance.doOnSuccess {}
|
||||
instance.doOnSuccess(::functionReference)
|
||||
}
|
||||
|
||||
fun functionReference(x: Any) {}
|
||||
|
||||
class GenericHolder<T> {
|
||||
fun doOnSuccess(onSuccess: Consumer<in T>) {
|
||||
onSuccess.accept(object : BaseClass() {} as T)
|
||||
}
|
||||
}
|
||||
|
||||
fun interface Consumer<T> {
|
||||
fun accept(t: T)
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
// IGNORE_BACKEND: WASM
|
||||
// WASM_MUTE_REASON: SAM_CONVERSIONS
|
||||
|
||||
// CHECK_BYTECODE_TEXT
|
||||
// 0 java/lang/invoke/LambdaMetafactory
|
||||
|
||||
interface Top
|
||||
|
||||
interface Common : Top
|
||||
|
||||
abstract class BaseClass : Common
|
||||
interface BaseInterface : Common
|
||||
|
||||
class ConcreteType : BaseClass(), BaseInterface
|
||||
class ConcreteType2 : BaseClass(), BaseInterface
|
||||
|
||||
fun box(): String {
|
||||
example(0)
|
||||
return "OK"
|
||||
}
|
||||
|
||||
fun example(input: Int) {
|
||||
val instance = when (input) {
|
||||
0 -> GenericHolder<ConcreteType>()
|
||||
else -> GenericHolder<ConcreteType2>()
|
||||
}
|
||||
|
||||
instance.doOnSuccess {}
|
||||
instance.doOnSuccess(::functionReference)
|
||||
}
|
||||
|
||||
fun functionReference(x: Any) {}
|
||||
|
||||
class GenericHolder<T : Top> {
|
||||
fun doOnSuccess(onSuccess: Consumer<in T>) {
|
||||
onSuccess.accept(object : BaseClass() {} as T)
|
||||
}
|
||||
}
|
||||
|
||||
fun interface Consumer<T : Top> {
|
||||
fun accept(t: T)
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
// IGNORE_BACKEND: WASM
|
||||
// WASM_MUTE_REASON: SAM_CONVERSIONS
|
||||
|
||||
// CHECK_BYTECODE_TEXT
|
||||
// 0 java/lang/invoke/LambdaMetafactory
|
||||
|
||||
interface Top
|
||||
interface Unrelated
|
||||
|
||||
interface A : Top, Unrelated
|
||||
interface B : Top, Unrelated
|
||||
|
||||
fun box(): String {
|
||||
val g = when ("".length) {
|
||||
0 -> G<A>()
|
||||
else -> G<B>()
|
||||
}
|
||||
|
||||
g.check {}
|
||||
g.check(::functionReference)
|
||||
return "OK"
|
||||
}
|
||||
|
||||
fun functionReference(x: Any) {}
|
||||
|
||||
class G<T : Top> {
|
||||
fun check(x: IFoo<in T>) {
|
||||
x.accept(object : A {} as T)
|
||||
}
|
||||
}
|
||||
|
||||
fun interface IFoo<T : Top> {
|
||||
fun accept(t: T)
|
||||
}
|
||||
Reference in New Issue
Block a user