From 6e15ee8fea36659480a1295acde37ae3ecd1d341 Mon Sep 17 00:00:00 2001 From: "Denis.Zharkov" Date: Mon, 8 Nov 2021 12:00:19 +0300 Subject: [PATCH] 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` --- ...CompilerTestFE10TestdataTestGenerated.java | 6 ++++ .../functionType.kt | 2 +- ...irOldFrontendDiagnosticsTestGenerated.java | 6 ++++ ...DiagnosticsWithLightTreeTestGenerated.java | 6 ++++ .../kotlin/fir/resolve/calls/CallKind.kt | 2 +- .../transformers/FirSyntheticCallGenerator.kt | 29 +++++++++++++++---- .../callableReferenceAssignmentToVar.kt | 20 +++++++++++++ .../generic/expectedFunctionType.fir.kt | 4 +-- .../resolve/withVararg.fir.kt | 4 +-- ...nceToSamFunctionAgainstExpectedType.fir.kt | 2 +- .../test/runners/DiagnosticTestGenerated.java | 6 ++++ .../p-1/neg/1.1.fir.kt | 12 ++++---- .../p-1/pos/1.2.fir.kt | 2 +- .../p-1/pos/1.3.fir.kt | 2 +- 14 files changed, 83 insertions(+), 20 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/callableReference/callableReferenceAssignmentToVar.kt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index 083ed2c8bfb..3a157e686e4 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -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 { diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/initializerTypeMismatchChecker/functionType.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/initializerTypeMismatchChecker/functionType.kt index bdc2368580d..135ea2c5edb 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/initializerTypeMismatchChecker/functionType.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/initializerTypeMismatchChecker/functionType.kt @@ -11,7 +11,7 @@ package testsCase1 class Case() { fun case(v: V) { // InitializerTypeMismatchChecker bug - val va: () -> String = (V)::a + val va: () -> String = (V)::a val vb: () -> String = (V)::b diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index b8d6bc775e5..2ef9f7b92bd 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -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 { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index c78bbd28dac..767f8d451e3 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -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 { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallKind.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallKind.kt index e14c01e5268..3f0914800d8 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallKind.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallKind.kt @@ -80,7 +80,7 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) { object SyntheticIdForCallableReferencesResolution : CallKind( MapArguments, - NoTypeArguments, + MapTypeArguments, CreateFreshTypeVariableSubstitutorStage, CollectTypeVariableUsagesInfo, CheckArguments, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt index 84ff5a9250b..081b86e3e00 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt @@ -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 = 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 = 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 diff --git a/compiler/testData/diagnostics/tests/callableReference/callableReferenceAssignmentToVar.kt b/compiler/testData/diagnostics/tests/callableReference/callableReferenceAssignmentToVar.kt new file mode 100644 index 00000000000..08c5148cea1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/callableReferenceAssignmentToVar.kt @@ -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 = TODO() + +var z: (x: Double) -> Double = { it } + +fun bar() { + z = ::foo +} + +fun baz(x: (Double) -> Double) {} diff --git a/compiler/testData/diagnostics/tests/callableReference/generic/expectedFunctionType.fir.kt b/compiler/testData/diagnostics/tests/callableReference/generic/expectedFunctionType.fir.kt index 9b5ea7e7276..4c5574d96c3 100644 --- a/compiler/testData/diagnostics/tests/callableReference/generic/expectedFunctionType.fir.kt +++ b/compiler/testData/diagnostics/tests/callableReference/generic/expectedFunctionType.fir.kt @@ -22,6 +22,6 @@ class A3 { fun test2(): (T) -> Unit = A3()::a3 fun test3(): (Int) -> String = A3()::a3 - fun test4(): (R) -> Unit = this::a3 + fun test4(): (R) -> Unit = this::a3 fun test5(): (T) -> R = this::a3 -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/callableReference/resolve/withVararg.fir.kt b/compiler/testData/diagnostics/tests/callableReference/resolve/withVararg.fir.kt index 25fc9de9f5d..c31d3da2ec2 100644 --- a/compiler/testData/diagnostics/tests/callableReference/resolve/withVararg.fir.kt +++ b/compiler/testData/diagnostics/tests/callableReference/resolve/withVararg.fir.kt @@ -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) -> Unit = ::foo \ No newline at end of file +val fn3: (Int, Int) -> Unit = ::foo +val fn4: (Array) -> Unit = ::foo diff --git a/compiler/testData/diagnostics/tests/j+k/sam/referenceToSamFunctionAgainstExpectedType.fir.kt b/compiler/testData/diagnostics/tests/j+k/sam/referenceToSamFunctionAgainstExpectedType.fir.kt index 881ef99228e..9e6142013b8 100644 --- a/compiler/testData/diagnostics/tests/j+k/sam/referenceToSamFunctionAgainstExpectedType.fir.kt +++ b/compiler/testData/diagnostics/tests/j+k/sam/referenceToSamFunctionAgainstExpectedType.fir.kt @@ -17,7 +17,7 @@ public class Inv { // FILE: test.kt fun test(inv: Inv) { - val m: ((String) -> String) -> Inv = inv::map + val m: ((String) -> String) -> Inv = inv::map take(inv::map) } diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 3999e6818d6..58d258e2b4c 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -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 { diff --git a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/resolving-callable-references/resolving-callable-references-not-used-as-arguments-to-a-call/p-1/neg/1.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/resolving-callable-references/resolving-callable-references-not-used-as-arguments-to-a-call/p-1/neg/1.1.fir.kt index 9cf4dad56ea..de21a863b5e 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/resolving-callable-references/resolving-callable-references-not-used-as-arguments-to-a-call/p-1/neg/1.1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/resolving-callable-references/resolving-callable-references-not-used-as-arguments-to-a-call/p-1/neg/1.1.fir.kt @@ -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 = ::foo + val y1: (String)-> Case1 = Case1.Companion::foo + val y2: (String)-> Case1 = (Case1)::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 = ::foo +fun case1_1() : (String)-> Case1 = (Case1)::foo +fun case1_2(): (String)-> Case1 = Case1.Companion::foo diff --git a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/resolving-callable-references/resolving-callable-references-not-used-as-arguments-to-a-call/p-1/pos/1.2.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/resolving-callable-references/resolving-callable-references-not-used-as-arguments-to-a-call/p-1/pos/1.2.fir.kt index e5e9f7e214d..4b17a42c762 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/resolving-callable-references/resolving-callable-references-not-used-as-arguments-to-a-call/p-1/pos/1.2.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/resolving-callable-references/resolving-callable-references-not-used-as-arguments-to-a-call/p-1/pos/1.2.fir.kt @@ -11,7 +11,7 @@ import libCase1.* import kotlin.text.format fun case1() { - val y2 : () ->String =(String)::format + val y2 : () ->String =(String)::format } // FILE: LibCase1.kt diff --git a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/resolving-callable-references/resolving-callable-references-not-used-as-arguments-to-a-call/p-1/pos/1.3.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/resolving-callable-references/resolving-callable-references-not-used-as-arguments-to-a-call/p-1/pos/1.3.fir.kt index b0c7e2e933c..b74108dae1c 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/resolving-callable-references/resolving-callable-references-not-used-as-arguments-to-a-call/p-1/pos/1.3.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/resolving-callable-references/resolving-callable-references-not-used-as-arguments-to-a-call/p-1/pos/1.3.fir.kt @@ -11,7 +11,7 @@ package testsCase1 class Case() { fun case(v: V) { // InitializertTypeCheckerMismatch bug - val va: () -> String = (V)::a + val va: () -> String = (V)::a val vb: () -> String = (V)::b