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:
Denis.Zharkov
2021-11-08 12:00:19 +03:00
committed by teamcity
parent 65d7da122f
commit 6e15ee8fea
14 changed files with 83 additions and 20 deletions
@@ -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 {
@@ -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
@@ -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 {
@@ -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,
@@ -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
@@ -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) {}
@@ -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
}
}
@@ -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
@@ -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<!>)
}
@@ -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 {
@@ -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<!>
@@ -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
@@ -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