FIR: Rework receivers processing in resolution

- Put extensionReceiver to candidate even if it's explicit (for sake of clarity)
- Split CheckReceiver (dispatch part should only check nullability)
This commit is contained in:
Denis Zharkov
2020-11-15 13:10:54 +03:00
parent e2099a0307
commit f97cc0b62d
40 changed files with 194 additions and 213 deletions
@@ -1,6 +1,5 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_LIGHT_ANALYSIS
inline class IC(val x: String)
@@ -7,8 +7,8 @@ public interface J {
// FILE: test.kt
fun f1(x: Int?): Any = <!UNRESOLVED_REFERENCE!>x::hashCode<!>
fun <T> f2(t: T): Any = t::hashCode
fun <S : String?> f3(s: S): Any = s::hashCode
fun <T> f2(t: T): Any = <!UNRESOLVED_REFERENCE!>t::hashCode<!>
fun <S : String?> f3(s: S): Any = <!UNRESOLVED_REFERENCE!>s::hashCode<!>
fun <U : Any> f4(u: U?): Any = <!UNRESOLVED_REFERENCE!>u::hashCode<!>
fun f5(c: List<*>): Any = <!UNRESOLVED_REFERENCE!>c[0]::hashCode<!>
@@ -14,11 +14,11 @@ fun test() {
}
fun check() {
[1, 2] checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Array<Int>>() }
[""] checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Array<String>>() }
[1, 2] <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Array<Int>>() }
[""] <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Array<String>>() }
val f: IntArray = [1]
[f] checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Array<IntArray>>() }
[f] <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Array<IntArray>>() }
[1, ""] checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Array<Any>>() }
}
[1, ""] <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Array<Any>>() }
}
@@ -11,7 +11,7 @@ fun test() {
const val <T> a3 = 0
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit val <T> a4 = 0<!>
val <T> a5 by Delegate<Int>()
val <T> a6 by Delegate<<!UNRESOLVED_REFERENCE!>T<!>>()
val <T> a6 by <!INAPPLICABLE_CANDIDATE!>Delegate<<!UNRESOLVED_REFERENCE!>T<!>>()<!>
}
class Delegate<F> {
@@ -11,7 +11,7 @@ fun test() {
const val <T> a3 = 0
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit val <T> a4 = 0<!>
val <T> a5 by Delegate<Int>()
val <T> a6 by Delegate<<!UNRESOLVED_REFERENCE!>T<!>>()
val <T> a6 by <!INAPPLICABLE_CANDIDATE!>Delegate<<!UNRESOLVED_REFERENCE!>T<!>>()<!>
}
class Delegate<F> {
@@ -5,7 +5,7 @@
import kotlin.reflect.KProperty
class B {
val c by <!INAPPLICABLE_CANDIDATE!>Delegate<!>(<!UNRESOLVED_REFERENCE!>ag<!>)
val c by <!INAPPLICABLE_CANDIDATE!><!INAPPLICABLE_CANDIDATE!>Delegate<!>(<!UNRESOLVED_REFERENCE!>ag<!>)<!>
}
class Delegate<T: Any>(val init: T) {
@@ -5,5 +5,5 @@ fun interface Bar {
operator fun Bar.plus(b: Bar): String = invoke() + b.invoke()
fun box(): String {
return { "O" } + { "K" }
return { "O" } <!INAPPLICABLE_CANDIDATE!>+<!> { "K" }
}
@@ -7,4 +7,4 @@ object Z {
infix fun add(b : Foo.() -> Unit) : Z = Z
}
val t2 = Z <!INAPPLICABLE_CANDIDATE!>add<!> { } { }
val t2 = Z <!INAPPLICABLE_CANDIDATE!>add<!> <!INAPPLICABLE_CANDIDATE!>{ } { }<!>
@@ -1,6 +1,6 @@
fun <E : String?, T : ((CharSequence) -> Unit)?> foo(x: E, y: T) {
if (x != null) {
y(x)
<!INAPPLICABLE_CANDIDATE!>y<!>(x)
}
if (y != null) {
@@ -10,4 +10,4 @@ fun <E : String?, T : ((CharSequence) -> Unit)?> foo(x: E, y: T) {
if (x != null && y != null) {
y(x)
}
}
}
@@ -1,6 +1,6 @@
fun <T : Any?> foo(x: T) {
if (x is String?) {
x.length
x.<!INAPPLICABLE_CANDIDATE!>length<!>
if (x != null) {
x.length
@@ -24,7 +24,7 @@ fun <T : CharSequence?> foo(x: T) {
x?.bar1()
}
x.length
x.<!INAPPLICABLE_CANDIDATE!>length<!>
if (x is String) {
x.length
@@ -23,7 +23,7 @@ fun <T : String?> T.foo() {
this?.bar1()
}
length
<!INAPPLICABLE_CANDIDATE!>length<!>
if (this is String) {
length
@@ -33,4 +33,4 @@ fun <T : String?> T.foo() {
bar2()
bar3()
}
}
}
@@ -7,7 +7,7 @@ fun CharSequence?.bar2() {}
fun <T : CharSequence> T.bar3() {}
fun <T : String?> foo(x: T) {
x.length
x.<!INAPPLICABLE_CANDIDATE!>length<!>
x?.length
if (1 == 1) {
@@ -14,14 +14,14 @@ class A<T> {
fun foo2(a: A<out CharSequence>, b: A<in CharSequence>) {
a.<!INAPPLICABLE_CANDIDATE!>foo1<!>(Out<CharSequence>())
a.foo1<<!UPPER_BOUND_VIOLATED!>Out<CharSequence><!>>(Out())
a.<!INAPPLICABLE_CANDIDATE!>foo1<!><Out<CharSequence>>(Out())
a.foo1(Out())
a.foo1(Out<Nothing>())
a.foo2(Inv())
a.<!INAPPLICABLE_CANDIDATE!>foo2<!>(Inv<CharSequence>())
a.foo2<<!UPPER_BOUND_VIOLATED!>Inv<CharSequence><!>>(Inv())
a.<!INAPPLICABLE_CANDIDATE!>foo2<!><Inv<CharSequence>>(Inv())
a.foo3(In())
a.foo3(In<CharSequence>())
@@ -33,11 +33,11 @@ fun foo2(a: A<out CharSequence>, b: A<in CharSequence>) {
b.foo2(Inv())
b.<!INAPPLICABLE_CANDIDATE!>foo2<!>(Inv<CharSequence>())
b.foo2<<!UPPER_BOUND_VIOLATED!>Inv<CharSequence><!>>(Inv())
b.<!INAPPLICABLE_CANDIDATE!>foo2<!><Inv<CharSequence>>(Inv())
b.<!INAPPLICABLE_CANDIDATE!>foo3<!>(In<CharSequence>())
b.foo3<<!UPPER_BOUND_VIOLATED!>In<CharSequence><!>>(In())
b.<!INAPPLICABLE_CANDIDATE!>foo3<!><In<CharSequence>>(In())
b.foo3(In<Any?>())
b.foo3(In())
@@ -30,7 +30,7 @@ fun A.test2() {
}
fun A?.test3() {
foo() // error
<!INAPPLICABLE_CANDIDATE!>foo<!>() // error
<!INAPPLICABLE_CANDIDATE!>bar<!>() // error
buzz()
@@ -32,7 +32,7 @@ fun test() {
foo()
}
with(platformN) {
foo()
<!INAPPLICABLE_CANDIDATE!>foo<!>()
}
with(platformJ) {
foo()
@@ -15,5 +15,5 @@ val test5: List<TNString?> = TODO()
val test6: () -> List<TNString> = TODO()
fun test(x: TNString) {
x.hashCode()
x.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
}
@@ -17,7 +17,7 @@ fun CharSequence?.isNullOrEmpty(): Boolean {
fun smartcastOnReceiver(s: String?) {
with(s) {
if (isNullOrEmpty()) {
length
<!INAPPLICABLE_CANDIDATE!>length<!>
}
else {
length
@@ -32,7 +32,7 @@ fun mixedReceiver(s: String?) {
}
} else {
with(s) {
length
<!INAPPLICABLE_CANDIDATE!>length<!>
}
}
}
}
@@ -17,7 +17,7 @@ fun CharSequence?.isNullOrEmpty(): Boolean {
fun smartcastOnReceiver(s: String?) {
with(s) {
if (isNullOrEmpty()) {
length
<!INAPPLICABLE_CANDIDATE!>length<!>
}
else {
length
@@ -32,7 +32,7 @@ fun mixedReceiver(s: String?) {
}
} else {
with(s) {
length
<!INAPPLICABLE_CANDIDATE!>length<!>
}
}
}
}