FIR: Refine callable reference resolution in assignment position
synthetic_select<() -> T>(::foo) form allows to select better candidate than synthetic_select(::foo) with expect type `() -> T`
This commit is contained in:
+6
@@ -2603,6 +2603,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/callableReferenceAsLastExpressionInBlock.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("callableReferenceAssignmentToVar.kt")
|
||||
public void testCallableReferenceAssignmentToVar() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/callableReferenceAssignmentToVar.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classVsPackage.kt")
|
||||
public void testClassVsPackage() throws Exception {
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ package testsCase1
|
||||
class Case() {
|
||||
fun case(v: V) {
|
||||
// InitializerTypeMismatchChecker bug
|
||||
val va: () -> String = <!INITIALIZER_TYPE_MISMATCH!>(V)::a<!>
|
||||
val va: () -> String = (V)::a
|
||||
|
||||
val vb: () -> String = (V)::b
|
||||
|
||||
|
||||
+6
@@ -2603,6 +2603,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/callableReferenceAsLastExpressionInBlock.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("callableReferenceAssignmentToVar.kt")
|
||||
public void testCallableReferenceAssignmentToVar() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/callableReferenceAssignmentToVar.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classVsPackage.kt")
|
||||
public void testClassVsPackage() throws Exception {
|
||||
|
||||
+6
@@ -2603,6 +2603,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/callableReferenceAsLastExpressionInBlock.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("callableReferenceAssignmentToVar.kt")
|
||||
public void testCallableReferenceAssignmentToVar() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/callableReferenceAssignmentToVar.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classVsPackage.kt")
|
||||
public void testClassVsPackage() throws Exception {
|
||||
|
||||
@@ -80,7 +80,7 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
|
||||
|
||||
object SyntheticIdForCallableReferencesResolution : CallKind(
|
||||
MapArguments,
|
||||
NoTypeArguments,
|
||||
MapTypeArguments,
|
||||
CreateFreshTypeVariableSubstitutorStage,
|
||||
CollectTypeVariableUsagesInfo,
|
||||
CheckArguments,
|
||||
|
||||
+24
-5
@@ -151,6 +151,17 @@ class FirSyntheticCallGenerator(
|
||||
): FirCallableReferenceAccess? {
|
||||
val argumentList = buildUnaryArgumentList(callableReferenceAccess)
|
||||
|
||||
val typeArguments =
|
||||
when {
|
||||
expectedTypeRef is FirResolvedTypeRef && !expectedTypeRef.coneType.isUnitOrFlexibleUnit -> listOf(
|
||||
buildTypeProjectionWithVariance {
|
||||
variance = Variance.INVARIANT
|
||||
typeRef = expectedTypeRef
|
||||
}
|
||||
)
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
val reference =
|
||||
generateCalleeReferenceWithCandidate(
|
||||
callableReferenceAccess,
|
||||
@@ -158,7 +169,8 @@ class FirSyntheticCallGenerator(
|
||||
argumentList,
|
||||
SyntheticCallableId.ID.callableName,
|
||||
CallKind.SyntheticIdForCallableReferencesResolution,
|
||||
context
|
||||
context,
|
||||
typeArguments,
|
||||
)
|
||||
val fakeCallElement = buildFunctionCall {
|
||||
calleeReference = reference
|
||||
@@ -175,9 +187,10 @@ class FirSyntheticCallGenerator(
|
||||
argumentList: FirArgumentList,
|
||||
name: Name,
|
||||
callKind: CallKind = CallKind.SyntheticSelect,
|
||||
context: ResolutionContext
|
||||
context: ResolutionContext,
|
||||
typeArguments: List<FirTypeProjection> = emptyList()
|
||||
): FirNamedReferenceWithCandidate {
|
||||
val callInfo = generateCallInfo(callSite, name, argumentList, callKind)
|
||||
val callInfo = generateCallInfo(callSite, name, argumentList, callKind, typeArguments)
|
||||
val candidate = generateCandidate(callInfo, function, context)
|
||||
val applicability = components.resolutionStageRunner.processCandidate(candidate, context)
|
||||
if (applicability <= CandidateApplicability.INAPPLICABLE) {
|
||||
@@ -203,14 +216,20 @@ class FirSyntheticCallGenerator(
|
||||
)
|
||||
}
|
||||
|
||||
private fun generateCallInfo(callSite: FirExpression, name: Name, argumentList: FirArgumentList, callKind: CallKind) = CallInfo(
|
||||
private fun generateCallInfo(
|
||||
callSite: FirExpression,
|
||||
name: Name,
|
||||
argumentList: FirArgumentList,
|
||||
callKind: CallKind,
|
||||
typeArguments: List<FirTypeProjection> = emptyList()
|
||||
) = CallInfo(
|
||||
callSite = callSite,
|
||||
callKind = callKind,
|
||||
name = name,
|
||||
explicitReceiver = null,
|
||||
argumentList = argumentList,
|
||||
isImplicitInvoke = false,
|
||||
typeArguments = emptyList(),
|
||||
typeArguments = typeArguments,
|
||||
session = session,
|
||||
containingFile = components.file,
|
||||
containingDeclarations = components.containingDeclarations
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// FIR_IDENTICAL
|
||||
// SKIP_TXT
|
||||
|
||||
// FILE: lib.kt
|
||||
package lib
|
||||
fun foo(x: Double): Double = x
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
import lib.*
|
||||
|
||||
fun foo(): Map<Int, String> = TODO()
|
||||
|
||||
var z: (x: Double) -> Double = { it }
|
||||
|
||||
fun bar() {
|
||||
z = ::foo
|
||||
}
|
||||
|
||||
fun baz(x: (Double) -> Double) {}
|
||||
+2
-2
@@ -22,6 +22,6 @@ class A3<T> {
|
||||
fun test2(): (T) -> Unit = A3<T>()::a3
|
||||
fun test3(): (Int) -> String = A3<Int>()::a3
|
||||
|
||||
fun <R> test4(): (R) -> Unit = <!RETURN_TYPE_MISMATCH!>this::a3<!>
|
||||
fun <R> test4(): (R) -> Unit = this::<!UNRESOLVED_REFERENCE!>a3<!>
|
||||
fun <R> test5(): (T) -> R = this::a3
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -6,5 +6,5 @@ fun foo(i: Int) {}
|
||||
|
||||
val fn1: (Int) -> Unit = ::foo
|
||||
val fn2: (IntArray) -> Unit = ::foo
|
||||
val fn3: (Int, Int) -> Unit = ::foo
|
||||
val fn4: (Array<String>) -> Unit = ::foo
|
||||
val fn3: (Int, Int) -> Unit = ::<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
val fn4: (Array<String>) -> Unit = ::foo
|
||||
|
||||
Vendored
+1
-1
@@ -17,7 +17,7 @@ public class Inv<T> {
|
||||
// FILE: test.kt
|
||||
|
||||
fun test(inv: Inv<String>) {
|
||||
val m: ((String) -> String) -> Inv<String> = <!INITIALIZER_TYPE_MISMATCH!>inv::map<!>
|
||||
val m: ((String) -> String) -> Inv<String> = inv::<!UNRESOLVED_REFERENCE!>map<!>
|
||||
<!INAPPLICABLE_CANDIDATE!>take<!>(inv::<!UNRESOLVED_REFERENCE!>map<!>)
|
||||
}
|
||||
|
||||
|
||||
Generated
+6
@@ -2609,6 +2609,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/callableReferenceAsLastExpressionInBlock.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("callableReferenceAssignmentToVar.kt")
|
||||
public void testCallableReferenceAssignmentToVar() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/callableReferenceAssignmentToVar.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classVsPackage.kt")
|
||||
public void testClassVsPackage() throws Exception {
|
||||
|
||||
+6
-6
@@ -17,11 +17,11 @@ class Case1() {
|
||||
|
||||
}
|
||||
fun case1() {
|
||||
val y0: (String)-> Case1 = ::foo
|
||||
val y1: (String)-> Case1 = Case1.Companion::foo
|
||||
val y2: (String)-> Case1 = (Case1)::foo
|
||||
val y0: (String)-> Case1 = ::<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
val y1: (String)-> Case1 = Case1.Companion::<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
val y2: (String)-> Case1 = (Case1)::<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
}
|
||||
|
||||
fun case1_0() : (String)-> Case1 = ::foo
|
||||
fun case1_1() : (String)-> Case1 = (Case1)::foo
|
||||
fun case1_2(): (String)-> Case1 = Case1.Companion::foo
|
||||
fun case1_0() : (String)-> Case1 = ::<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
fun case1_1() : (String)-> Case1 = (Case1)::<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
fun case1_2(): (String)-> Case1 = Case1.Companion::<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ import libCase1.*
|
||||
import kotlin.text.format
|
||||
|
||||
fun case1() {
|
||||
val y2 : () ->String =(String)::<!UNRESOLVED_REFERENCE!>format<!>
|
||||
val y2 : () ->String =(String)::format
|
||||
}
|
||||
|
||||
// FILE: LibCase1.kt
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ package testsCase1
|
||||
class Case() {
|
||||
fun case(v: V) {
|
||||
// InitializertTypeCheckerMismatch bug
|
||||
val va: () -> String = <!INITIALIZER_TYPE_MISMATCH!>(V)::a<!>
|
||||
val va: () -> String = (V)::a
|
||||
|
||||
val vb: () -> String = (V)::b
|
||||
|
||||
|
||||
Reference in New Issue
Block a user