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 {}
}
@@ -0,0 +1,21 @@
// ISSUE: KT-58013
// WITH_REFLECT
// FIR_DUMP
import kotlin.reflect.KProperty
data class Ref<D>(val t: D)
class GenericDelegate<G>(val value: G)
operator fun <V> Ref<V>.provideDelegate(a: Any?, p: KProperty<*>): GenericDelegate<V> = GenericDelegate(this.t)
operator fun <W> GenericDelegate<W>.getValue(a: Any?, p: KProperty<*>): W = this.value
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!>!!<!>
val data2: String by list.getElement(0)
}
@@ -0,0 +1,36 @@
FILE: notNullAssertionInLocalDelegated.fir.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 class GenericDelegate<G> : R|kotlin/Any| {
public constructor<G>(value: R|G|): R|GenericDelegate<G>| {
super<R|kotlin/Any|>()
}
public final val value: R|G| = R|<local>/value|
public get(): R|G|
}
public final operator fun <V> R|Ref<V>|.provideDelegate(a: R|kotlin/Any?|, p: R|kotlin/reflect/KProperty<*>|): R|GenericDelegate<V>| {
^provideDelegate R|/GenericDelegate.GenericDelegate|<R|V|>(this@R|/provideDelegate|.R|SubstitutionOverride</Ref.t: R|V|>|)
}
public final operator fun <W> R|GenericDelegate<W>|.getValue(a: R|kotlin/Any?|, p: R|kotlin/reflect/KProperty<*>|): R|W| {
^getValue this@R|/getValue|.R|SubstitutionOverride</GenericDelegate.value: R|W|>|
}
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|/provideDelegate|<R|kotlin/String|>(Null(null), ::R|<local>/data|)
lval data2: R|kotlin/String|by R|<local>/list|.R|/getElement|<R|kotlin/String|>(Int(0)).R|/provideDelegate|<R|kotlin/String|>(Null(null), ::R|<local>/data2|)
}
@@ -0,0 +1,21 @@
// ISSUE: KT-58013
// WITH_REFLECT
// FIR_DUMP
import kotlin.reflect.KProperty
data class Ref<D>(val t: D)
class GenericDelegate<G>(val value: G)
operator fun <V> Ref<V>.provideDelegate(a: Any?, p: KProperty<*>): GenericDelegate<V> = GenericDelegate(this.t)
operator fun <W> GenericDelegate<W>.getValue(a: Any?, p: KProperty<*>): W = this.value
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 <!DELEGATE_SPECIAL_FUNCTION_MISSING, DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE!>list.getElement(0)<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!><!>
val data2: String by list.getElement(0)
}
@@ -0,0 +1,10 @@
// FIR_IDENTICAL
class C {
operator fun getValue(x: Any?, y: Any?): String = ""
}
object O {
operator fun provideDelegate(x: Any?, y: Any?): C = C()
}
val x: String by O