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");
|
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
|
@Test
|
||||||
@TestMetadata("classVsPackage.kt")
|
@TestMetadata("classVsPackage.kt")
|
||||||
public void testClassVsPackage() throws Exception {
|
public void testClassVsPackage() throws Exception {
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ package testsCase1
|
|||||||
class Case() {
|
class Case() {
|
||||||
fun case(v: V) {
|
fun case(v: V) {
|
||||||
// InitializerTypeMismatchChecker bug
|
// InitializerTypeMismatchChecker bug
|
||||||
val va: () -> String = <!INITIALIZER_TYPE_MISMATCH!>(V)::a<!>
|
val va: () -> String = (V)::a
|
||||||
|
|
||||||
val vb: () -> String = (V)::b
|
val vb: () -> String = (V)::b
|
||||||
|
|
||||||
|
|||||||
+6
@@ -2603,6 +2603,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
runTest("compiler/testData/diagnostics/tests/callableReference/callableReferenceAsLastExpressionInBlock.kt");
|
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
|
@Test
|
||||||
@TestMetadata("classVsPackage.kt")
|
@TestMetadata("classVsPackage.kt")
|
||||||
public void testClassVsPackage() throws Exception {
|
public void testClassVsPackage() throws Exception {
|
||||||
|
|||||||
+6
@@ -2603,6 +2603,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
runTest("compiler/testData/diagnostics/tests/callableReference/callableReferenceAsLastExpressionInBlock.kt");
|
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
|
@Test
|
||||||
@TestMetadata("classVsPackage.kt")
|
@TestMetadata("classVsPackage.kt")
|
||||||
public void testClassVsPackage() throws Exception {
|
public void testClassVsPackage() throws Exception {
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
|
|||||||
|
|
||||||
object SyntheticIdForCallableReferencesResolution : CallKind(
|
object SyntheticIdForCallableReferencesResolution : CallKind(
|
||||||
MapArguments,
|
MapArguments,
|
||||||
NoTypeArguments,
|
MapTypeArguments,
|
||||||
CreateFreshTypeVariableSubstitutorStage,
|
CreateFreshTypeVariableSubstitutorStage,
|
||||||
CollectTypeVariableUsagesInfo,
|
CollectTypeVariableUsagesInfo,
|
||||||
CheckArguments,
|
CheckArguments,
|
||||||
|
|||||||
+24
-5
@@ -151,6 +151,17 @@ class FirSyntheticCallGenerator(
|
|||||||
): FirCallableReferenceAccess? {
|
): FirCallableReferenceAccess? {
|
||||||
val argumentList = buildUnaryArgumentList(callableReferenceAccess)
|
val argumentList = buildUnaryArgumentList(callableReferenceAccess)
|
||||||
|
|
||||||
|
val typeArguments =
|
||||||
|
when {
|
||||||
|
expectedTypeRef is FirResolvedTypeRef && !expectedTypeRef.coneType.isUnitOrFlexibleUnit -> listOf(
|
||||||
|
buildTypeProjectionWithVariance {
|
||||||
|
variance = Variance.INVARIANT
|
||||||
|
typeRef = expectedTypeRef
|
||||||
|
}
|
||||||
|
)
|
||||||
|
else -> emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
val reference =
|
val reference =
|
||||||
generateCalleeReferenceWithCandidate(
|
generateCalleeReferenceWithCandidate(
|
||||||
callableReferenceAccess,
|
callableReferenceAccess,
|
||||||
@@ -158,7 +169,8 @@ class FirSyntheticCallGenerator(
|
|||||||
argumentList,
|
argumentList,
|
||||||
SyntheticCallableId.ID.callableName,
|
SyntheticCallableId.ID.callableName,
|
||||||
CallKind.SyntheticIdForCallableReferencesResolution,
|
CallKind.SyntheticIdForCallableReferencesResolution,
|
||||||
context
|
context,
|
||||||
|
typeArguments,
|
||||||
)
|
)
|
||||||
val fakeCallElement = buildFunctionCall {
|
val fakeCallElement = buildFunctionCall {
|
||||||
calleeReference = reference
|
calleeReference = reference
|
||||||
@@ -175,9 +187,10 @@ class FirSyntheticCallGenerator(
|
|||||||
argumentList: FirArgumentList,
|
argumentList: FirArgumentList,
|
||||||
name: Name,
|
name: Name,
|
||||||
callKind: CallKind = CallKind.SyntheticSelect,
|
callKind: CallKind = CallKind.SyntheticSelect,
|
||||||
context: ResolutionContext
|
context: ResolutionContext,
|
||||||
|
typeArguments: List<FirTypeProjection> = emptyList()
|
||||||
): FirNamedReferenceWithCandidate {
|
): FirNamedReferenceWithCandidate {
|
||||||
val callInfo = generateCallInfo(callSite, name, argumentList, callKind)
|
val callInfo = generateCallInfo(callSite, name, argumentList, callKind, typeArguments)
|
||||||
val candidate = generateCandidate(callInfo, function, context)
|
val candidate = generateCandidate(callInfo, function, context)
|
||||||
val applicability = components.resolutionStageRunner.processCandidate(candidate, context)
|
val applicability = components.resolutionStageRunner.processCandidate(candidate, context)
|
||||||
if (applicability <= CandidateApplicability.INAPPLICABLE) {
|
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,
|
callSite = callSite,
|
||||||
callKind = callKind,
|
callKind = callKind,
|
||||||
name = name,
|
name = name,
|
||||||
explicitReceiver = null,
|
explicitReceiver = null,
|
||||||
argumentList = argumentList,
|
argumentList = argumentList,
|
||||||
isImplicitInvoke = false,
|
isImplicitInvoke = false,
|
||||||
typeArguments = emptyList(),
|
typeArguments = typeArguments,
|
||||||
session = session,
|
session = session,
|
||||||
containingFile = components.file,
|
containingFile = components.file,
|
||||||
containingDeclarations = components.containingDeclarations
|
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) {}
|
||||||
+1
-1
@@ -22,6 +22,6 @@ class A3<T> {
|
|||||||
fun test2(): (T) -> Unit = A3<T>()::a3
|
fun test2(): (T) -> Unit = A3<T>()::a3
|
||||||
fun test3(): (Int) -> String = A3<Int>()::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
|
fun <R> test5(): (T) -> R = this::a3
|
||||||
}
|
}
|
||||||
+1
-1
@@ -6,5 +6,5 @@ fun foo(i: Int) {}
|
|||||||
|
|
||||||
val fn1: (Int) -> Unit = ::foo
|
val fn1: (Int) -> Unit = ::foo
|
||||||
val fn2: (IntArray) -> Unit = ::foo
|
val fn2: (IntArray) -> Unit = ::foo
|
||||||
val fn3: (Int, Int) -> Unit = ::foo
|
val fn3: (Int, Int) -> Unit = ::<!UNRESOLVED_REFERENCE!>foo<!>
|
||||||
val fn4: (Array<String>) -> Unit = ::foo
|
val fn4: (Array<String>) -> Unit = ::foo
|
||||||
Vendored
+1
-1
@@ -17,7 +17,7 @@ public class Inv<T> {
|
|||||||
// FILE: test.kt
|
// FILE: test.kt
|
||||||
|
|
||||||
fun test(inv: Inv<String>) {
|
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<!>)
|
<!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");
|
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
|
@Test
|
||||||
@TestMetadata("classVsPackage.kt")
|
@TestMetadata("classVsPackage.kt")
|
||||||
public void testClassVsPackage() throws Exception {
|
public void testClassVsPackage() throws Exception {
|
||||||
|
|||||||
+6
-6
@@ -17,11 +17,11 @@ class Case1() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
fun case1() {
|
fun case1() {
|
||||||
val y0: (String)-> Case1 = ::foo
|
val y0: (String)-> Case1 = ::<!UNRESOLVED_REFERENCE!>foo<!>
|
||||||
val y1: (String)-> Case1 = Case1.Companion::foo
|
val y1: (String)-> Case1 = Case1.Companion::<!UNRESOLVED_REFERENCE!>foo<!>
|
||||||
val y2: (String)-> Case1 = (Case1)::foo
|
val y2: (String)-> Case1 = (Case1)::<!UNRESOLVED_REFERENCE!>foo<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
fun case1_0() : (String)-> Case1 = ::foo
|
fun case1_0() : (String)-> Case1 = ::<!UNRESOLVED_REFERENCE!>foo<!>
|
||||||
fun case1_1() : (String)-> Case1 = (Case1)::foo
|
fun case1_1() : (String)-> Case1 = (Case1)::<!UNRESOLVED_REFERENCE!>foo<!>
|
||||||
fun case1_2(): (String)-> Case1 = Case1.Companion::foo
|
fun case1_2(): (String)-> Case1 = Case1.Companion::<!UNRESOLVED_REFERENCE!>foo<!>
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ import libCase1.*
|
|||||||
import kotlin.text.format
|
import kotlin.text.format
|
||||||
|
|
||||||
fun case1() {
|
fun case1() {
|
||||||
val y2 : () ->String =(String)::<!UNRESOLVED_REFERENCE!>format<!>
|
val y2 : () ->String =(String)::format
|
||||||
}
|
}
|
||||||
|
|
||||||
// FILE: LibCase1.kt
|
// FILE: LibCase1.kt
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ package testsCase1
|
|||||||
class Case() {
|
class Case() {
|
||||||
fun case(v: V) {
|
fun case(v: V) {
|
||||||
// InitializertTypeCheckerMismatch bug
|
// InitializertTypeCheckerMismatch bug
|
||||||
val va: () -> String = <!INITIALIZER_TYPE_MISMATCH!>(V)::a<!>
|
val va: () -> String = (V)::a
|
||||||
|
|
||||||
val vb: () -> String = (V)::b
|
val vb: () -> String = (V)::b
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user