Support overload ambiguity resolution for callable references by expected type.

Resolve callable references taking into account expected callable types.

This affects call resolution procedure (resolve 'foo' in for 'foo(::bar)') similar to the approach used for function literals:

* During "shape arguments" phase of call resolution, callable references are resolved in independent context without expected type. If the callable reference is ambiguous, its shape type is a function placeholder type without parameter types and return type information. Otherwise, it is a reflection type for the resolved function or property. Upper-level call is resolved without taking into account ambiguous callable references.

* During "complete call" phase of call resolution, resolve callable reference arguments to actual descriptors (if possible), and update constraint system for the given call accordingly.

 #KT-6982 Fixed
 #KT-5780 Fixed
This commit is contained in:
Dmitry Petrov
2015-07-14 17:53:12 +03:00
parent b3a2ee2148
commit 6437a4bdc6
51 changed files with 1057 additions and 247 deletions
@@ -0,0 +1,10 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun foo() {}
fun foo(s: String) {}
fun fn(f: () -> Unit) {}
fun test() {
fn(::foo)
}
@@ -0,0 +1,6 @@
package
internal fun fn(/*0*/ f: () -> kotlin.Unit): kotlin.Unit
internal fun foo(): kotlin.Unit
internal fun foo(/*0*/ s: kotlin.String): kotlin.Unit
internal fun test(): kotlin.Unit
@@ -0,0 +1,10 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun <T> ofType(x: T): T = x
fun foo() {}
fun foo(s: String) {}
val x1 = ofType<() -> Unit>(::foo)
val x2 = ofType<(String) -> Unit>(::foo)
val x3 = ofType<(Int) -> Unit>(::<!NONE_APPLICABLE!>foo<!>)
@@ -0,0 +1,8 @@
package
internal val x1: () -> kotlin.Unit
internal val x2: (kotlin.String) -> kotlin.Unit
internal val x3: (kotlin.Int) -> kotlin.Unit
internal fun foo(): kotlin.Unit
internal fun foo(/*0*/ s: kotlin.String): kotlin.Unit
internal fun </*0*/ T> ofType(/*0*/ x: T): T
@@ -0,0 +1,9 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun foo() {}
fun foo(s: String) {}
val x1 = ::<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>
val x2: () -> Unit = ::foo
val x3: (String) -> Unit = ::foo
val x4: (Int) -> Unit = ::<!NONE_APPLICABLE!>foo<!>
@@ -0,0 +1,8 @@
package
internal val x1: [ERROR : Type for ::foo]
internal val x2: () -> kotlin.Unit
internal val x3: (kotlin.String) -> kotlin.Unit
internal val x4: (kotlin.Int) -> kotlin.Unit
internal fun foo(): kotlin.Unit
internal fun foo(/*0*/ s: kotlin.String): kotlin.Unit
@@ -0,0 +1,12 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class Klass {
constructor(a: Int) {}
constructor(a: String) {}
}
fun user(f: (Int) -> Klass) {}
fun fn() {
user(::Klass)
}
@@ -0,0 +1,12 @@
package
internal fun fn(): kotlin.Unit
internal fun user(/*0*/ f: (kotlin.Int) -> Klass): kotlin.Unit
internal final class Klass {
public constructor Klass(/*0*/ a: kotlin.Int)
public constructor Klass(/*0*/ a: kotlin.String)
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,11 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
import kotlin.reflect.*
class A {
val x = 1
fun x() {}
}
fun f1(): KProperty<Int> = A::x // ok, property
fun f2(): (A) -> Unit = A::x // ok, function
@@ -0,0 +1,13 @@
package
internal fun f1(): kotlin.reflect.KProperty<kotlin.Int>
internal fun f2(): (A) -> kotlin.Unit
internal final class A {
public constructor A()
internal final val x: kotlin.Int = 1
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
internal final fun x(): kotlin.Unit
}
@@ -0,0 +1,10 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun foo() {}
fun foo(s: String) {}
fun bar(f: () -> Unit) = 1
fun bar(f: (String) -> Unit) = 2
val x1 = ::<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!> as () -> Unit
val x2 = bar(::<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!> as (String) -> Unit)
@@ -0,0 +1,8 @@
package
internal val x1: () -> kotlin.Unit
internal val x2: kotlin.Int
internal fun bar(/*0*/ f: () -> kotlin.Unit): kotlin.Int
internal fun bar(/*0*/ f: (kotlin.String) -> kotlin.Unit): kotlin.Int
internal fun foo(): kotlin.Unit
internal fun foo(/*0*/ s: kotlin.String): kotlin.Unit
@@ -0,0 +1,28 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
import kotlin.reflect.*
fun <T> ofType(x: T): T = x
class A {
val foo: Int = 0
fun foo() {}
fun bar() {}
val bar: Int = 0
}
fun A.foo(): String = "A"
val x0 = A::foo // function A::foo wins by default
val userOfX0 = x0(A())
val x1 = ofType<(A) -> Unit>(A::foo)
val x2 = ofType<KProperty1<A, Int>>(A::foo)
val x3: KProperty1<A, Int> = A::foo
val x4: (A) -> String = A::foo
val y0 = A::bar
val y1 = ofType<(A) -> Unit>(A::bar)
val y2 = ofType<KProperty1<A, Int>>(A::bar)
val y3: KProperty1<A, Int> = A::bar
@@ -0,0 +1,25 @@
package
internal val userOfX0: kotlin.Unit
internal val x0: kotlin.reflect.KFunction1<A, kotlin.Unit>
internal val x1: (A) -> kotlin.Unit
internal val x2: kotlin.reflect.KProperty1<A, kotlin.Int>
internal val x3: kotlin.reflect.KProperty1<A, kotlin.Int>
internal val x4: (A) -> kotlin.String
internal val y0: kotlin.reflect.KFunction1<A, kotlin.Unit>
internal val y1: (A) -> kotlin.Unit
internal val y2: kotlin.reflect.KProperty1<A, kotlin.Int>
internal val y3: kotlin.reflect.KProperty1<A, kotlin.Int>
internal fun </*0*/ T> ofType(/*0*/ x: T): T
internal fun A.foo(): kotlin.String
internal final class A {
public constructor A()
internal final val bar: kotlin.Int = 0
internal final val foo: kotlin.Int = 0
internal final fun bar(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
internal final fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,10 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun <T, R> apply(x: T, f: (T) -> R): R = f(x)
fun foo(i: Int) {}
fun foo(s: String) {}
val x1 = apply(1, ::foo)
val x2 = apply("hello", ::foo)
val x3 = apply(true, ::<!NONE_APPLICABLE!>foo<!>)
@@ -0,0 +1,8 @@
package
internal val x1: kotlin.Unit
internal val x2: kotlin.Unit
internal val x3: [ERROR : Type for apply(true, ::foo)]
internal fun </*0*/ T, /*1*/ R> apply(/*0*/ x: T, /*1*/ f: (T) -> R): R
internal fun foo(/*0*/ i: kotlin.Int): kotlin.Unit
internal fun foo(/*0*/ s: kotlin.String): kotlin.Unit
@@ -0,0 +1,26 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER,-CONFLICTING_JVM_DECLARATIONS
fun foo(i: Int) = "$i"
fun foo(s: String) = s
fun bar(s: String) = s
fun qux(i: Int, j: Int, k: Int): Int = i + j + k
fun qux(a: String, b: String, c: String, d: String) {}
fun fn1(x: Int, f1: (Int) -> String, f2: (String) -> String) = f2(f1(x))
fun fn2(f1: (Int) -> String, f2: (String) -> String ) = f2(f1(0))
fun fn2(f1: (Int) -> Int, f2: (Int) -> String ) = f2(f1(0))
fun fn2(f1: (String) -> String, f2: (String) -> String ) = f2(f1(""))
fun fn3(i: Int, f: (Int, Int, Int) -> Int): Int = f(i, i, i)
val x1 = fn1(1, ::foo, ::foo)
val x2 = fn1(1, ::foo, ::bar)
val x3 = fn2(::bar, ::foo)
val x4 = fn2(::<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>, ::bar)
val x5 = fn2(::<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>, ::<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>)
val x6 = fn3(1, ::qux)
@@ -0,0 +1,18 @@
package
internal val x1: kotlin.String
internal val x2: kotlin.String
internal val x3: kotlin.String
internal val x4: [ERROR : Type for fn2(::foo, ::bar)]
internal val x5: [ERROR : Type for fn2(::foo, ::foo)]
internal val x6: kotlin.Int
internal fun bar(/*0*/ s: kotlin.String): kotlin.String
internal fun fn1(/*0*/ x: kotlin.Int, /*1*/ f1: (kotlin.Int) -> kotlin.String, /*2*/ f2: (kotlin.String) -> kotlin.String): kotlin.String
internal fun fn2(/*0*/ f1: (kotlin.Int) -> kotlin.Int, /*1*/ f2: (kotlin.Int) -> kotlin.String): kotlin.String
internal fun fn2(/*0*/ f1: (kotlin.Int) -> kotlin.String, /*1*/ f2: (kotlin.String) -> kotlin.String): kotlin.String
internal fun fn2(/*0*/ f1: (kotlin.String) -> kotlin.String, /*1*/ f2: (kotlin.String) -> kotlin.String): kotlin.String
internal fun fn3(/*0*/ i: kotlin.Int, /*1*/ f: (kotlin.Int, kotlin.Int, kotlin.Int) -> kotlin.Int): kotlin.Int
internal fun foo(/*0*/ i: kotlin.Int): kotlin.String
internal fun foo(/*0*/ s: kotlin.String): kotlin.String
internal fun qux(/*0*/ i: kotlin.Int, /*1*/ j: kotlin.Int, /*2*/ k: kotlin.Int): kotlin.Int
internal fun qux(/*0*/ a: kotlin.String, /*1*/ b: kotlin.String, /*2*/ c: kotlin.String, /*3*/ d: kotlin.String): kotlin.Unit
@@ -0,0 +1,10 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun foo(vararg ii: Int) {}
fun foo(vararg ss: String) {}
fun foo(i: Int) {}
val fn1: (Int) -> Unit = ::foo
val fn2: (IntArray) -> Unit = ::foo
val fn3: (Int, Int) -> Unit = <!TYPE_MISMATCH!>::foo<!>
val fn4: (Array<String>) -> Unit = ::foo
@@ -0,0 +1,9 @@
package
internal val fn1: (kotlin.Int) -> kotlin.Unit
internal val fn2: (kotlin.IntArray) -> kotlin.Unit
internal val fn3: (kotlin.Int, kotlin.Int) -> kotlin.Unit
internal val fn4: (kotlin.Array<kotlin.String>) -> kotlin.Unit
internal fun foo(/*0*/ vararg ss: kotlin.String /*kotlin.Array<out kotlin.String>*/): kotlin.Unit
internal fun foo(/*0*/ i: kotlin.Int): kotlin.Unit
internal fun foo(/*0*/ vararg ii: kotlin.Int /*kotlin.IntArray*/): kotlin.Unit