K2: fix handling of synthetic calls in delegate inference

This commit is intended to avoid the second resolve of delegate when
we need to consider provideDelegate() possibility in inference.
Also here we provide correct completion of synthetic calls during
delegate inference.

#KT-58013 Fixed
This commit is contained in:
Mikhail Glukhikh
2023-04-28 09:21:36 +02:00
committed by Space Team
parent 8c8ca7bb70
commit 3964ee38be
19 changed files with 457 additions and 3 deletions
@@ -0,0 +1,23 @@
FILE: elvisInDelegated.kt
public final data class Ref<D> : R|kotlin/Any| {
public constructor<D>(t: R|D|): R|Ref<D>| {
super<R|kotlin/Any|>()
}
public final val t: R|D| = R|<local>/t|
public get(): R|D|
public final operator fun component1(): R|D|
public final fun copy(t: R|D| = this@R|/Ref|.R|/Ref.t|): R|Ref<D>|
}
public final operator fun <V> R|Ref<V>|.getValue(hisRef: R|kotlin/Any?|, property: R|kotlin/reflect/KProperty<*>|): R|V| {
^getValue this@R|/getValue|.R|SubstitutionOverride</Ref.t: R|V|>|
}
public final fun <E> R|kotlin/collections/List<Ref<*>>|.getElement(i: R|kotlin/Int|): R|Ref<E>| {
^getElement (this@R|/getElement|.R|SubstitutionOverride<kotlin/collections/List.get: R|Ref<*>|>|(R|<local>/i|) as R|Ref<E>|)
}
public final fun test(list: R|kotlin/collections/List<Ref<*>>|): R|kotlin/Unit| {
lval data: R|kotlin/String|by R|<local>/list|.R|/getElement|<R|kotlin/String|>(Int(0)) ?: R|kotlin/error|(String())
}
@@ -0,0 +1,16 @@
// FIR_IDENTICAL
// ISSUE: KT-58013 (related)
// WITH_REFLECT
// FIR_DUMP
import kotlin.reflect.KProperty
data class Ref<D>(val t: D)
operator fun <V> Ref<V>.getValue(hisRef: Any?, property: KProperty<*>): V = this.t
fun <E> List<Ref<*>>.getElement(i: Int): Ref<E> = this[i] <!UNCHECKED_CAST!>as Ref<E><!>
fun test(list: List<Ref<*>>) {
val data: String by list.getElement(0) <!USELESS_ELVIS!>?: error("")<!>
}
@@ -0,0 +1,31 @@
FILE: ifInDelegated.kt
public final data class Ref<D> : R|kotlin/Any| {
public constructor<D>(t: R|D|): R|Ref<D>| {
super<R|kotlin/Any|>()
}
public final val t: R|D| = R|<local>/t|
public get(): R|D|
public final operator fun component1(): R|D|
public final fun copy(t: R|D| = this@R|/Ref|.R|/Ref.t|): R|Ref<D>|
}
public final operator fun <V> R|Ref<V>|.getValue(hisRef: R|kotlin/Any?|, property: R|kotlin/reflect/KProperty<*>|): R|V| {
^getValue this@R|/getValue|.R|SubstitutionOverride</Ref.t: R|V|>|
}
public final fun <E> R|kotlin/collections/List<Ref<*>>|.getElement(i: R|kotlin/Int|): R|Ref<E>| {
^getElement (this@R|/getElement|.R|SubstitutionOverride<kotlin/collections/List.get: R|Ref<*>|>|(R|<local>/i|) as R|Ref<E>|)
}
public final fun test(list: R|kotlin/collections/List<Ref<*>>|, arg: R|kotlin/Boolean|): R|kotlin/Unit| {
lval data: R|kotlin/String|by when () {
R|<local>/arg| -> {
R|<local>/list|.R|/getElement|<R|kotlin/String|>(Int(0))
}
else -> {
R|<local>/list|.R|/getElement|<R|kotlin/String|>(Int(1))
}
}
}
@@ -0,0 +1,16 @@
// FIR_IDENTICAL
// ISSUE: KT-58013 (related)
// WITH_REFLECT
// FIR_DUMP
import kotlin.reflect.KProperty
data class Ref<D>(val t: D)
operator fun <V> Ref<V>.getValue(hisRef: Any?, property: KProperty<*>): V = this.t
fun <E> List<Ref<*>>.getElement(i: Int): Ref<E> = this[i] <!UNCHECKED_CAST!>as Ref<E><!>
fun test(list: List<Ref<*>>, arg: Boolean) {
val data: String by if (arg) list.getElement(0) else list.getElement(1)
}
@@ -0,0 +1,23 @@
FILE: notNullAssertionInLocalDelegated.kt
public final data class Ref<D> : R|kotlin/Any| {
public constructor<D>(t: R|D|): R|Ref<D>| {
super<R|kotlin/Any|>()
}
public final val t: R|D| = R|<local>/t|
public get(): R|D|
public final operator fun component1(): R|D|
public final fun copy(t: R|D| = this@R|/Ref|.R|/Ref.t|): R|Ref<D>|
}
public final operator fun <V> R|Ref<V>|.getValue(hisRef: R|kotlin/Any?|, property: R|kotlin/reflect/KProperty<*>|): R|V| {
^getValue this@R|/getValue|.R|SubstitutionOverride</Ref.t: R|V|>|
}
public final fun <E> R|kotlin/collections/List<Ref<*>>|.getElement(i: R|kotlin/Int|): R|Ref<E>| {
^getElement (this@R|/getElement|.R|SubstitutionOverride<kotlin/collections/List.get: R|Ref<*>|>|(R|<local>/i|) as R|Ref<E>|)
}
public final fun test(list: R|kotlin/collections/List<Ref<*>>|): R|kotlin/Unit| {
lval data: R|kotlin/String|by R|<local>/list|.R|/getElement|<R|kotlin/String|>(Int(0))!!
}
@@ -0,0 +1,16 @@
// FIR_IDENTICAL
// ISSUE: KT-58013
// WITH_REFLECT
// FIR_DUMP
import kotlin.reflect.KProperty
data class Ref<D>(val t: D)
operator fun <V> Ref<V>.getValue(hisRef: Any?, property: KProperty<*>): V = this.t
fun <E> List<Ref<*>>.getElement(i: Int): Ref<E> = this[i] <!UNCHECKED_CAST!>as Ref<E><!>
fun test(list: List<Ref<*>>) {
val data: String by list.getElement(0)<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
}
@@ -0,0 +1,28 @@
FILE: tryInGenerated.kt
public final data class Ref<D> : R|kotlin/Any| {
public constructor<D>(t: R|D|): R|Ref<D>| {
super<R|kotlin/Any|>()
}
public final val t: R|D| = R|<local>/t|
public get(): R|D|
public final operator fun component1(): R|D|
public final fun copy(t: R|D| = this@R|/Ref|.R|/Ref.t|): R|Ref<D>|
}
public final operator fun <V> R|Ref<V>|.getValue(hisRef: R|kotlin/Any?|, property: R|kotlin/reflect/KProperty<*>|): R|V| {
^getValue this@R|/getValue|.R|SubstitutionOverride</Ref.t: R|V|>|
}
public final fun <E> R|kotlin/collections/List<Ref<*>>|.getElement(i: R|kotlin/Int|): R|Ref<E>| {
^getElement (this@R|/getElement|.R|SubstitutionOverride<kotlin/collections/List.get: R|Ref<*>|>|(R|<local>/i|) as R|Ref<E>|)
}
public final fun test(list: R|kotlin/collections/List<Ref<*>>|): R|kotlin/Unit| {
lval data: R|kotlin/String|by try {
R|<local>/list|.R|/getElement|<R|kotlin/String|>(Int(0))
}
finally {
}
}
@@ -0,0 +1,16 @@
// FIR_IDENTICAL
// ISSUE: KT-58013 (related)
// WITH_REFLECT
// FIR_DUMP
import kotlin.reflect.KProperty
data class Ref<D>(val t: D)
operator fun <V> Ref<V>.getValue(hisRef: Any?, property: KProperty<*>): V = this.t
fun <E> List<Ref<*>>.getElement(i: Int): Ref<E> = this[i] <!UNCHECKED_CAST!>as Ref<E><!>
fun test(list: List<Ref<*>>) {
val data: String by try { list.getElement(0) } finally {}
}