FIR: Fix callable references resolution with stub receivers
Use stubReceiver as a receiver for fake calls See issues KT-43358 KT-43359 KT-43378
This commit is contained in:
+2
-2
@@ -36,8 +36,8 @@ class NoGenericTest {
|
|||||||
fun B.extensionFun(): A = A()
|
fun B.extensionFun(): A = A()
|
||||||
|
|
||||||
fun test_1() {
|
fun test_1() {
|
||||||
val extensionValRef = <!UNRESOLVED_REFERENCE!>B::extensionVal<!>
|
val extensionValRef = B::extensionVal
|
||||||
val extensionFunRef = <!UNRESOLVED_REFERENCE!>B::extensionFun<!>
|
val extensionFunRef = B::extensionFun
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test_2() {
|
fun test_2() {
|
||||||
|
|||||||
+2
-2
@@ -81,8 +81,8 @@ FILE: referenceToExtension.kt
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final fun test_1(): R|kotlin/Unit| {
|
public final fun test_1(): R|kotlin/Unit| {
|
||||||
lval extensionValRef: <ERROR TYPE REF: No result type for initializer> = Q|NoGenericTest.B|::<Unresolved name: extensionVal>#
|
lval extensionValRef: R|kotlin/reflect/KProperty1<NoGenericTest.B, NoGenericTest.A>| = Q|NoGenericTest.B|::R|/NoGenericTest.extensionVal|
|
||||||
lval extensionFunRef: <ERROR TYPE REF: No result type for initializer> = Q|NoGenericTest.B|::<Unresolved name: extensionFun>#
|
lval extensionFunRef: R|kotlin/reflect/KFunction1<NoGenericTest.B, NoGenericTest.A>| = Q|NoGenericTest.B|::R|/NoGenericTest.extensionFun|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final fun test_2(): R|kotlin/Unit| {
|
public final fun test_2(): R|kotlin/Unit| {
|
||||||
|
|||||||
+2
-2
@@ -34,9 +34,9 @@ fun main() {
|
|||||||
<!AMBIGUITY!>foo3<!>(KotlinClass::baz)
|
<!AMBIGUITY!>foo3<!>(KotlinClass::baz)
|
||||||
|
|
||||||
// Type mismatch
|
// Type mismatch
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo1<!>(<!UNRESOLVED_REFERENCE!>KotlinClass::bar<!>)
|
foo1(KotlinClass::bar)
|
||||||
foo2(KotlinClass::bar)
|
foo2(KotlinClass::bar)
|
||||||
foo3(KotlinClass::bar)
|
<!AMBIGUITY!>foo3<!>(KotlinClass::bar)
|
||||||
|
|
||||||
foo1(KotlinClass2::bar)
|
foo1(KotlinClass2::bar)
|
||||||
// Type mismatch
|
// Type mismatch
|
||||||
|
|||||||
+5
-5
@@ -50,13 +50,13 @@ FILE: main.kt
|
|||||||
public final fun foo3(x: R|(kotlin/String) -> kotlin/Int|): R|kotlin/Unit| {
|
public final fun foo3(x: R|(kotlin/String) -> kotlin/Int|): R|kotlin/Unit| {
|
||||||
}
|
}
|
||||||
public final fun main(): R|kotlin/Unit| {
|
public final fun main(): R|kotlin/Unit| {
|
||||||
R|/foo1|(Q|KotlinClass|::R|/KotlinClass.Companion.baz|)
|
R|/foo1|(Q|KotlinClass|::R|/KotlinClass.baz|)
|
||||||
R|/foo2|(Q|KotlinClass|::R|/KotlinClass.baz|)
|
R|/foo2|(Q|KotlinClass|::R|/KotlinClass.baz|)
|
||||||
<Ambiguity: foo3, [/foo3, /foo3]>#(Q|KotlinClass|::R|/KotlinClass.baz|)
|
<Ambiguity: foo3, [/foo3, /foo3]>#(Q|KotlinClass|::R|/KotlinClass.baz|)
|
||||||
<Inapplicable(INAPPLICABLE): /foo1>#(Q|KotlinClass|::<Unresolved reference: bar>#)
|
R|/foo1|(Q|KotlinClass|::R|/JavaClass.bar|)
|
||||||
R|/foo2|(Q|KotlinClass|::R|/JavaClass.bar|)
|
R|/foo2|(Q|KotlinClass|::R|/JavaClass.bar|)
|
||||||
R|/foo3|(Q|KotlinClass|::R|/JavaClass.bar|)
|
<Ambiguity: foo3, [/foo3, /foo3]>#(Q|KotlinClass|::R|/JavaClass.bar|)
|
||||||
R|/foo1|(Q|KotlinClass2|::R|/KotlinClass2.Companion.bar|)
|
R|/foo1|(Q|KotlinClass2|::R|/KotlinClass2.bar|)
|
||||||
<Inapplicable(INAPPLICABLE): /foo2>#(Q|KotlinClass2|::<Unresolved reference: bar>#)
|
<Inapplicable(INAPPLICABLE): /foo2>#(Q|KotlinClass2|::<Unresolved reference: bar>#)
|
||||||
R|/foo3|(Q|KotlinClass2|::R|/KotlinClass2.Companion.bar|)
|
R|/foo3|(Q|KotlinClass2|::R|/KotlinClass2.bar|)
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-9
@@ -180,16 +180,15 @@ internal open class FirTowerResolveTask(
|
|||||||
|
|
||||||
if (resolvedQualifier.symbol != null) {
|
if (resolvedQualifier.symbol != null) {
|
||||||
val typeRef = resolvedQualifier.typeRef
|
val typeRef = resolvedQualifier.typeRef
|
||||||
// NB: yet built-in Unit is used for "no-value" type
|
if (info.callKind == CallKind.CallableReference && info.stubReceiver != null ) {
|
||||||
if (info.callKind == CallKind.CallableReference) {
|
runResolverForExpressionReceiver(info, info.stubReceiver, parentGroup = TowerGroup.QualifierValue)
|
||||||
if (info.stubReceiver != null || typeRef !is FirImplicitBuiltinTypeRef) {
|
|
||||||
runResolverForExpressionReceiver(info, resolvedQualifier, parentGroup = TowerGroup.QualifierValue)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (typeRef !is FirImplicitBuiltinTypeRef) {
|
|
||||||
runResolverForExpressionReceiver(info, resolvedQualifier, parentGroup = TowerGroup.QualifierValue)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NB: yet built-in Unit is used for "no-value" type
|
||||||
|
if (typeRef !is FirImplicitBuiltinTypeRef) {
|
||||||
|
runResolverForExpressionReceiver(info, resolvedQualifier, parentGroup = TowerGroup.QualifierValue)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// DONT_TARGET_EXACT_BACKEND: WASM
|
// DONT_TARGET_EXACT_BACKEND: WASM
|
||||||
// WASM_MUTE_REASON: BINDING_RECEIVERS
|
// WASM_MUTE_REASON: BINDING_RECEIVERS
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
fun <T> get(t: T): () -> String {
|
fun <T> get(t: T): () -> String {
|
||||||
return t::toString
|
return t::toString
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+2
-2
@@ -4,10 +4,10 @@ class A {
|
|||||||
fun A.extA(x: String) = x
|
fun A.extA(x: String) = x
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
<!UNRESOLVED_REFERENCE!>Int::extInt<!>
|
Int::extInt
|
||||||
A::extA
|
A::extA
|
||||||
|
|
||||||
<!INAPPLICABLE_CANDIDATE!>eat<!>(<!UNRESOLVED_REFERENCE!>Int::extInt<!>)
|
eat(Int::extInt)
|
||||||
eat(A::extA)
|
eat(A::extA)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ fun testA(a: A) {
|
|||||||
|
|
||||||
fun testB(b: B) {
|
fun testB(b: B) {
|
||||||
val call1 = call(B::foo)
|
val call1 = call(B::foo)
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>call1<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>call1<!>
|
||||||
|
|
||||||
val call2 = call(B()::foo)
|
val call2 = call(B()::foo)
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>call2<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>call2<!>
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ fun B.foo(): Double = 0.0
|
|||||||
fun call(a: Any) {}
|
fun call(a: Any) {}
|
||||||
|
|
||||||
fun testA(a: A) {
|
fun testA(a: A) {
|
||||||
call(A::foo)
|
call(<!UNRESOLVED_REFERENCE!>A::foo<!>)
|
||||||
call(A.Companion::foo)
|
call(A.Companion::foo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
@@ -186,7 +186,7 @@ fun main() {
|
|||||||
// Should be error as `A3::foo1` is `KFunction2`, but the remaining arguments are `KFuncion1` or `Function1`
|
// Should be error as `A3::foo1` is `KFunction2`, but the remaining arguments are `KFuncion1` or `Function1`
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function<kotlin.Any>")!>select(A3(), <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo1<!>, { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>a<!> }, { it -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> })<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function<kotlin.Any>")!>select(A3(), <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo1<!>, { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>a<!> }, { it -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> })<!>
|
||||||
// It's OK because `A3::foo2` is from companion of `A3`
|
// It's OK because `A3::foo2` is from companion of `A3`
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int, kotlin.Any>")!>select(A3(), <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<kotlin.Int, kotlin.Unit>")!>A3::foo2<!>, { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>a<!> }, { it -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> })<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function<kotlin.Any>")!>select(A3(), <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo2<!>, { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>a<!> }, { it -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> })<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int, kotlin.Comparable<*> & java.io.Serializable>")!>select(A4(), { x: Number -> "" })<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int, kotlin.Comparable<*> & java.io.Serializable>")!>select(A4(), { x: Number -> "" })<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function2<kotlin.Int, kotlin.Int, kotlin.Comparable<*> & java.io.Serializable>")!>select(A5<Int, Int>(), { x: Number, y: Int -> "" })<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function2<kotlin.Int, kotlin.Int, kotlin.Comparable<*> & java.io.Serializable>")!>select(A5<Int, Int>(), { x: Number, y: Int -> "" })<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function3<kotlin.Int, kotlin.String, kotlin.Float, kotlin.Float>")!>select(A2(), id { a, b, c -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>a<!>; <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>b<!>; <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>c<!> })<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function3<kotlin.Int, kotlin.String, kotlin.Float, kotlin.Float>")!>select(A2(), id { a, b, c -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>a<!>; <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>b<!>; <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>c<!> })<!>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ interface TypeConstructor
|
|||||||
|
|
||||||
class Refiner {
|
class Refiner {
|
||||||
val memoizedFunctionLambda = createMemoizedFunction { it.foo() } // error type infered, no diagnostic, BAD, backend fails
|
val memoizedFunctionLambda = createMemoizedFunction { it.foo() } // error type infered, no diagnostic, BAD, backend fails
|
||||||
val memoizedFunctionReference = <!INAPPLICABLE_CANDIDATE!>createMemoizedFunction<!>(<!UNRESOLVED_REFERENCE!>TypeConstructor::foo<!>) // EXTENSION_IN_CLASS_REFERENCE_IS_NOT_ALLOWED, fine
|
val memoizedFunctionReference = createMemoizedFunction(TypeConstructor::foo) // EXTENSION_IN_CLASS_REFERENCE_IS_NOT_ALLOWED, fine
|
||||||
val memoizedFunctionTypes = createMemoizedFunction<TypeConstructor, Boolean> { it.foo() } // works fine
|
val memoizedFunctionTypes = createMemoizedFunction<TypeConstructor, Boolean> { it.foo() } // works fine
|
||||||
|
|
||||||
private fun TypeConstructor.foo(): Boolean = true
|
private fun TypeConstructor.foo(): Boolean = true
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ import libCase1.*
|
|||||||
import kotlin.text.format
|
import kotlin.text.format
|
||||||
|
|
||||||
fun case1() {
|
fun case1() {
|
||||||
val y2 : () ->String =<!UNRESOLVED_REFERENCE!>(String)::format<!>
|
val y2 : () ->String =(String)::format
|
||||||
}
|
}
|
||||||
|
|
||||||
// FILE: LibCase1.kt
|
// FILE: LibCase1.kt
|
||||||
|
|||||||
Reference in New Issue
Block a user