K2: Rewrite delegate inference
The main idea is getting rid of stub types and using just type variables See more detailed description at docs/fir/delegated_property_inference.md The problem with stub types is that they need really special treatment in many places, and on the other hand, there are no clear contracts on how they should work (that regularly leads to bugs like KT-59529) ^KT-61060 Fixed ^KT-61075 Fixed ^KT-61077 Fixed ^KT-59529 Fixed ^KT-61633 Related ^KT-61618 Related ^KT-61740 Related ^KT-59107 Related ^KT-61747 Related ^KT-61077 Related ^KT-61781 Related
This commit is contained in:
committed by
Space Team
parent
cd5105c133
commit
a02cb16fb2
@@ -0,0 +1,17 @@
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_K1: JVM_IR
|
||||
// ISSUE: KT-61633
|
||||
|
||||
class C<T3>(val p: T3)
|
||||
class D<T4>(val p: T4)
|
||||
|
||||
val <X3> C<X3>.getValue: D<X3> get() = D(p)
|
||||
operator fun <X4> D<X4>.invoke(x: Any?, y: Any?): X4 = p
|
||||
|
||||
fun foo(c: C<String>): String {
|
||||
val y1 by c
|
||||
|
||||
return y1
|
||||
}
|
||||
|
||||
fun box(): String = foo(C("OK"))
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// FIR_IDENTICAL
|
||||
// ISSUE: KT-61075
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
|
||||
open class BaseState
|
||||
interface CustomComparable<T>
|
||||
annotation class XCollection
|
||||
|
||||
fun <E> treeSet(): ReadWriteProperty<Any?, E> where E: BaseState, E: CustomComparable<E> = TODO()
|
||||
|
||||
internal class VisibleTreeState {
|
||||
internal class State: BaseState(), CustomComparable<State>
|
||||
|
||||
// K1: ok
|
||||
// K2: NEW_INFERENCE_ERROR
|
||||
@get:XCollection var expandedNodes: State by treeSet()
|
||||
|
||||
// K1: ok
|
||||
// K2: NEW_INFERENCE_ERROR
|
||||
@set:XCollection var selectedNodes: State by treeSet()
|
||||
}
|
||||
compiler/testData/diagnostics/tests/delegatedProperty/inference/fullyCompleteDelegateWhenPossible.kt
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
// FIR_IDENTICAL
|
||||
// WITH_STDLIB
|
||||
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class Cached<T>(val f: () -> T) {
|
||||
operator fun getValue(thisRef: Any?, property: KProperty<*>): T = TODO()
|
||||
}
|
||||
|
||||
private val map: MutableMap<String, Cached<String>> = TODO()
|
||||
|
||||
fun foo() {
|
||||
val bar by map.getOrPut("A") {
|
||||
Cached { "B" }
|
||||
}
|
||||
}
|
||||
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
// FIR_IDENTICAL
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
fun <X> myEmptyList1(): List<X> = TODO()
|
||||
fun <Y> myEmptyList2(): List<Y> = TODO()
|
||||
|
||||
var b: Boolean = false
|
||||
|
||||
val foo: List<String> by myLazy {
|
||||
if (b) return@myLazy myEmptyList1()
|
||||
|
||||
myEmptyList2()
|
||||
}
|
||||
|
||||
private fun <T> myLazy(initialValue: () -> T): ReadProperty<T> = TODO()
|
||||
|
||||
class ReadProperty<V>(val v: V) {
|
||||
operator fun getValue(thisRef: Any?, property: KProperty<*>): V = v
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// FIR_IDENTICAL
|
||||
// WITH_STDLIB
|
||||
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class DelegateProvider {
|
||||
operator fun provideDelegate(
|
||||
thisRef: Nothing?,
|
||||
prop: KProperty<*>
|
||||
): RDelegate = TODO()
|
||||
}
|
||||
|
||||
class RDelegate {
|
||||
operator fun getValue(thisRef: Nothing?, property: KProperty<*>): String = ""
|
||||
}
|
||||
|
||||
fun builder(name: String? = null, block: () -> Unit): DelegateProvider = TODO()
|
||||
val x by builder {}
|
||||
|
||||
fun main() {
|
||||
x.length
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// FIR_IDENTICAL
|
||||
|
||||
interface A<T> {
|
||||
operator fun getValue(x: Any?, y: Any?): T = TODO()
|
||||
}
|
||||
|
||||
fun <T> foo(): A<T> = TODO()
|
||||
|
||||
fun bar1() {
|
||||
val x: String by foo()
|
||||
}
|
||||
|
||||
fun bar2() {
|
||||
operator fun <F : A<E>, E> A<E>.provideDelegate(x: Any?, y: Any?): F = TODO()
|
||||
|
||||
val x: String by foo()
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// ISSUE: KT-61747
|
||||
|
||||
interface A {
|
||||
operator fun getValue(x: Any?, y: Any?): String = ""
|
||||
}
|
||||
|
||||
fun <T> foo(x: (T) -> Unit): T = TODO()
|
||||
|
||||
fun bar1(a: A) {
|
||||
val x by <!DELEGATE_SPECIAL_FUNCTION_MISSING!>foo { x: A -> }<!>
|
||||
}
|
||||
|
||||
fun bar2(a: A) {
|
||||
operator fun <F> F.provideDelegate(x: Any?, y: Any?): F {
|
||||
return this
|
||||
}
|
||||
|
||||
val x by <!DELEGATE_SPECIAL_FUNCTION_MISSING!>foo { x: A -> }<!>
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// ISSUE: KT-61747
|
||||
|
||||
interface A {
|
||||
operator fun getValue(x: Any?, y: Any?): String = ""
|
||||
}
|
||||
|
||||
fun <T> foo(x: (T) -> Unit): T = TODO()
|
||||
|
||||
fun bar1(a: A) {
|
||||
val x by <!DELEGATE_SPECIAL_FUNCTION_MISSING!>foo { x: A -> }<!>
|
||||
}
|
||||
|
||||
fun bar2(a: A) {
|
||||
operator fun <F> F.provideDelegate(x: Any?, y: Any?): F {
|
||||
return this
|
||||
}
|
||||
|
||||
val x by foo { x: A -> }
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// ISSUE: KT-61077
|
||||
|
||||
val test: Int by <!DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE, INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION!>materializeDelegate()<!>
|
||||
|
||||
fun <T: CharSequence> materializeDelegate(): Box<T> = TODO()
|
||||
|
||||
operator fun <K: Comparable<K>> Box<K>.provideDelegate(receiver: Any?, property: kotlin.reflect.KProperty<*>): K = TODO()
|
||||
|
||||
operator fun <Q: Comparable<Q>> Q.getValue(thisRef: Any?, property: kotlin.reflect.KProperty<*>): Q = TODO()
|
||||
|
||||
class Box<V> {}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// ISSUE: KT-61077
|
||||
|
||||
val test: Int by <!DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE!><!TYPE_MISMATCH!>materializeDelegate<!>()<!>
|
||||
|
||||
fun <T: CharSequence> materializeDelegate(): Box<T> = TODO()
|
||||
|
||||
operator fun <K: Comparable<K>> Box<K>.provideDelegate(receiver: Any?, property: kotlin.reflect.KProperty<*>): K = TODO()
|
||||
|
||||
operator fun <Q: Comparable<Q>> Q.getValue(thisRef: Any?, property: kotlin.reflect.KProperty<*>): Q = TODO()
|
||||
|
||||
class Box<V> {}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// FIR_IDENTICAL
|
||||
// ISSUE: KT-59529
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
interface Out<out F> {
|
||||
val x: F
|
||||
}
|
||||
interface Out2<out E> {
|
||||
val x: E
|
||||
}
|
||||
interface Inv<U> {
|
||||
val u: U
|
||||
}
|
||||
|
||||
val outString: Out<String> = TODO()
|
||||
|
||||
val invOut2String by foo(outString)
|
||||
|
||||
operator fun <X> Inv<X>.getValue(
|
||||
thisRef: Any?,
|
||||
property: KProperty<*>
|
||||
): Inv<X> = TODO()
|
||||
|
||||
fun <M> foo(other: Out<M>): Inv<Out2<M>> = TODO()
|
||||
|
||||
fun main() {
|
||||
invOut2String.u.x.length
|
||||
}
|
||||
Vendored
+37
@@ -0,0 +1,37 @@
|
||||
// FIR_IDENTICAL
|
||||
// WITH_STDLIB
|
||||
// !CHECK_TYPE
|
||||
// ISSUE: KT-59529
|
||||
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
val ows: IgnoringParser = IgnoringParser()
|
||||
|
||||
class MyParser<T> {
|
||||
|
||||
private val booleanLiteral: Parser<String> = TODO()
|
||||
|
||||
val topLevel by ows + booleanLiteral
|
||||
|
||||
fun main() {
|
||||
topLevel checkType { _<TransformParser<Pair<Unit, String>, String>>() }
|
||||
}
|
||||
|
||||
operator fun <T, R> TransformParser<T, R>.provideDelegate(
|
||||
thisRef: MyParser<*>,
|
||||
property: KProperty<*>
|
||||
): TransformParser<T, R> = TODO()
|
||||
|
||||
operator fun <T, R> TransformParser<T, R>.getValue(
|
||||
thisRef: MyParser<*>,
|
||||
property: KProperty<*>
|
||||
): TransformParser<T, R> = TODO()
|
||||
}
|
||||
|
||||
abstract class Parser<out T>
|
||||
|
||||
class TransformParser<T, R> : Parser<R>()
|
||||
class IgnoringParser : Parser<Unit>()
|
||||
|
||||
operator fun <T> IgnoringParser.plus(other: Parser<T>): TransformParser<Pair<Unit, T>, T> =
|
||||
TODO()
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// FIR_IDENTICAL
|
||||
val test: String by materializeDelegate()
|
||||
|
||||
fun <T> materializeDelegate(): Delegate<T> = Delegate()
|
||||
|
||||
operator fun <K> K.provideDelegate(receiver: Any?, property: kotlin.reflect.KProperty<*>): K = this
|
||||
|
||||
operator fun <X> Delegate<X>.getValue(thisRef: Any?, property: kotlin.reflect.KProperty<*>): X = TODO()
|
||||
|
||||
class Delegate<V>
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
// ISSUE: KT-61077
|
||||
class Delegate<T>
|
||||
|
||||
operator fun Delegate<*>.getValue(receiver: Any?, p: Any): String = ""
|
||||
@@ -10,7 +10,7 @@ operator fun <T> String.provideDelegate(receiver: Any?, p: Any) = Delegate<T>()
|
||||
var test1: String by Delegate()
|
||||
var test2: String by Delegate<String>()
|
||||
|
||||
var test3: String by <!DELEGATE_SPECIAL_FUNCTION_MISSING, DELEGATE_SPECIAL_FUNCTION_MISSING!>"OK"<!>
|
||||
var test3: String by "OK"
|
||||
|
||||
var test4: String by "OK".provideDelegate(null, "")
|
||||
var test5: String by "OK".provideDelegate<String>(null, "")
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
// ISSUE: KT-61077
|
||||
class Delegate<T>
|
||||
|
||||
operator fun Delegate<*>.getValue(receiver: Any?, p: Any): String = ""
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
// ISSUE: KT-61633
|
||||
|
||||
interface A<T1>
|
||||
interface B<T2>
|
||||
interface C<T3>
|
||||
interface D<T4>
|
||||
|
||||
val <X1> A<X1>.provideDelegate: B<X1> get() = TODO()
|
||||
operator fun <X2> B<X2>.invoke(x: Any?, y: Any?): C<X2> = TODO()
|
||||
|
||||
val <X3> C<X3>.getValue: D<X3> get() = TODO()
|
||||
operator fun <X4> D<X4>.invoke(x: Any?, y: Any?): X4 = TODO()
|
||||
|
||||
fun foo(a: A<String>, c: C<String>) {
|
||||
val x1 by a
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>x1<!>
|
||||
x1.length
|
||||
|
||||
val y1 by c
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>y1<!>
|
||||
y1.length
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// ISSUE: KT-61633
|
||||
|
||||
interface A<T1>
|
||||
interface B<T2>
|
||||
interface C<T3>
|
||||
interface D<T4>
|
||||
|
||||
val <X1> A<X1>.provideDelegate: B<X1> get() = TODO()
|
||||
operator fun <X2> B<X2>.invoke(x: Any?, y: Any?): C<X2> = TODO()
|
||||
|
||||
val <X3> C<X3>.getValue: D<X3> get() = TODO()
|
||||
operator fun <X4> D<X4>.invoke(x: Any?, y: Any?): X4 = TODO()
|
||||
|
||||
fun foo(a: A<String>, c: C<String>) {
|
||||
val x1 by a
|
||||
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, DEBUG_INFO_EXPRESSION_TYPE("[Error type: Error delegation type for a]")!>x1<!>
|
||||
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>x1<!>.<!DEBUG_INFO_MISSING_UNRESOLVED!>length<!>
|
||||
|
||||
val y1 by c
|
||||
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, DEBUG_INFO_EXPRESSION_TYPE("[Error type: Error delegation type for c]")!>y1<!>
|
||||
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>y1<!>.<!DEBUG_INFO_MISSING_UNRESOLVED!>length<!>
|
||||
}
|
||||
Reference in New Issue
Block a user