K2: Avoid inappropriate approximation of captured type to Nothing?

There's a heuristic for approximation of a captured type that once
it has non-trivial lower bound (other than Nothing), it's worth
approximating it to sub-type even while the containing
top-level type is being approximated to super-type.

And that sounds reasonable in case the lower bound is indeed non-trivial,
but that's not the case because nullability here comes from
the nullability of captured type position.

So, the fix is basically not to treat such approximations as non-trivial.
And while that seems to be a bit of a change in the language semantics,
it still looks reasonable (see other changes in test data and KT-58087)

^KT-57958 Fixed
^KT-58087 Fixed
This commit is contained in:
Denis.Zharkov
2023-04-18 19:07:30 +02:00
committed by Space Team
parent 0a631ed8fc
commit 6651e6ed8c
10 changed files with 189 additions and 16 deletions
@@ -0,0 +1,19 @@
// FIR_IDENTICAL
interface Inv<T : CharSequence>
fun <E : CharSequence> id(i: Inv<E>): Inv<E> = i
fun foo1(x: Inv<in String>) {
val y = <!DEBUG_INFO_EXPRESSION_TYPE("Inv<in kotlin.String>")!>id(x)<!> // Should return Inv<in String>
bar1(y)
}
fun bar1(i: Inv<in String>) {}
fun foo2(x: Inv<in Nothing>) {
// Inv<out kotlin.CharSequence> is OK here, because it's still a subtype of Inv<in Nothing>
val y = <!DEBUG_INFO_EXPRESSION_TYPE("Inv<out kotlin.CharSequence>")!>id(x)<!>
bar2(y)
}
fun bar2(i: Inv<in Nothing>) {}
@@ -4,15 +4,15 @@
fun <T: Any> bar(a: Array<T>): Array<T?> = null!!
fun test1(a: Array<out Int>) {
val r: Array<out Int?> = <!INITIALIZER_TYPE_MISMATCH!>bar(a)<!>
val r: Array<out Int?> = bar(a)
val t = bar(a)
t checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><Array<out Int?>>() }
t checkType { _<Array<out Int?>>() }
}
fun <T: Any> foo(l: Array<T>): Array<Array<T?>> = null!!
fun test2(a: Array<out Int>) {
val r: Array<out Array<out Int?>> = <!INITIALIZER_TYPE_MISMATCH!>foo(a)<!>
val r: Array<out Array<out Int?>> = foo(a)
val t = foo(a)
t checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><Array<out Array<out Int?>>>() }
t checkType { _<Array<out Array<out Int?>>>() }
}
@@ -0,0 +1,18 @@
// FIR_IDENTICAL
// ISSUE: KT-57958
fun ListVM<*>.foo() {
val currentItem1: MutableProperty<out ListItemVM<*>?> = currentItem
}
interface MutableProperty<T> {
var value: T
}
interface ListItemVM<out TItem> {
val value: TItem
}
interface ListVM<TItemVM : ListItemVM<*>> {
val currentItem: MutableProperty<TItemVM?>
}
@@ -0,0 +1,14 @@
// FIR_IDENTICAL
// ISSUE: KT-57958
fun ListVM<*>.foo() {
val currentItem1: MutableProperty<out Any?> = <!DEBUG_INFO_EXPRESSION_TYPE("MutableProperty<in kotlin.Nothing?>")!>currentItem<!>
}
interface MutableProperty<T> {
var value: T
}
interface ListVM<TItemVM> {
val currentItem: MutableProperty<TItemVM?>
}