From 555d8eeb25612c57b69bd508396faac65f908f6c Mon Sep 17 00:00:00 2001 From: "Denis.Zharkov" Date: Fri, 21 Apr 2023 14:41:40 +0200 Subject: [PATCH] K2: Fix false-positive DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE For explanation, see nestedPartiallyResolvedCallsSimple.k The problem was caused by "select" variable is being leaked to the inference session of delegate while it should not happen because it doesn't belong to the common system of `KotlinVal { ..` call, as we complete it with fixing `E` variable during completion for `A(select(null, fun(): Int { return 1 }))`. The root of the problem is that we were adding all the partial nested calls to the session, while in fact we only need there the top-level one. ^KT-57543 Fixed --- ...CompilerTestFE10TestdataTestGenerated.java | 12 +++++++ ...sticCompilerFE10TestDataTestGenerated.java | 12 +++++++ ...eeOldFrontendDiagnosticsTestGenerated.java | 12 +++++++ ...siOldFrontendDiagnosticsTestGenerated.java | 12 +++++++ .../fir/resolve/inference/FirCallCompleter.kt | 6 +++- .../FirDeclarationsResolveTransformer.kt | 5 +-- .../differentDelegatedExpressions.fir.kt | 4 +-- .../inference/nestedPartiallyResolvedCalls.kt | 34 +++++++++++++++++++ .../nestedPartiallyResolvedCallsSimple.kt | 16 +++++++++ .../buildListToUpperBoundInLazy.fir.kt | 2 +- ...uildListToUpperBoundInLazyForbidden.fir.kt | 2 +- .../test/runners/DiagnosticTestGenerated.java | 12 +++++++ 12 files changed, 122 insertions(+), 7 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/delegatedProperty/inference/nestedPartiallyResolvedCalls.kt create mode 100644 compiler/testData/diagnostics/tests/delegatedProperty/inference/nestedPartiallyResolvedCallsSimple.kt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java index 2871b6dfd4a..11a5f5063a5 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java @@ -8931,6 +8931,18 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/tests/delegatedProperty/inference/manyIncompleteCandidates.kt"); } + @Test + @TestMetadata("nestedPartiallyResolvedCalls.kt") + public void testNestedPartiallyResolvedCalls() throws Exception { + runTest("compiler/testData/diagnostics/tests/delegatedProperty/inference/nestedPartiallyResolvedCalls.kt"); + } + + @Test + @TestMetadata("nestedPartiallyResolvedCallsSimple.kt") + public void testNestedPartiallyResolvedCallsSimple() throws Exception { + runTest("compiler/testData/diagnostics/tests/delegatedProperty/inference/nestedPartiallyResolvedCallsSimple.kt"); + } + @Test @TestMetadata("noErrorsForImplicitConstraints.kt") public void testNoErrorsForImplicitConstraints() throws Exception { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java index 33db75dfba5..58181292055 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java @@ -8931,6 +8931,18 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/tests/delegatedProperty/inference/manyIncompleteCandidates.kt"); } + @Test + @TestMetadata("nestedPartiallyResolvedCalls.kt") + public void testNestedPartiallyResolvedCalls() throws Exception { + runTest("compiler/testData/diagnostics/tests/delegatedProperty/inference/nestedPartiallyResolvedCalls.kt"); + } + + @Test + @TestMetadata("nestedPartiallyResolvedCallsSimple.kt") + public void testNestedPartiallyResolvedCallsSimple() throws Exception { + runTest("compiler/testData/diagnostics/tests/delegatedProperty/inference/nestedPartiallyResolvedCallsSimple.kt"); + } + @Test @TestMetadata("noErrorsForImplicitConstraints.kt") public void testNoErrorsForImplicitConstraints() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java index 2fba92f8c5a..d5b4085f78a 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java @@ -8931,6 +8931,18 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/delegatedProperty/inference/manyIncompleteCandidates.kt"); } + @Test + @TestMetadata("nestedPartiallyResolvedCalls.kt") + public void testNestedPartiallyResolvedCalls() throws Exception { + runTest("compiler/testData/diagnostics/tests/delegatedProperty/inference/nestedPartiallyResolvedCalls.kt"); + } + + @Test + @TestMetadata("nestedPartiallyResolvedCallsSimple.kt") + public void testNestedPartiallyResolvedCallsSimple() throws Exception { + runTest("compiler/testData/diagnostics/tests/delegatedProperty/inference/nestedPartiallyResolvedCallsSimple.kt"); + } + @Test @TestMetadata("noErrorsForImplicitConstraints.kt") public void testNoErrorsForImplicitConstraints() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java index 8ae7f6408e0..5eda00f629f 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java @@ -8937,6 +8937,18 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/delegatedProperty/inference/manyIncompleteCandidates.kt"); } + @Test + @TestMetadata("nestedPartiallyResolvedCalls.kt") + public void testNestedPartiallyResolvedCalls() throws Exception { + runTest("compiler/testData/diagnostics/tests/delegatedProperty/inference/nestedPartiallyResolvedCalls.kt"); + } + + @Test + @TestMetadata("nestedPartiallyResolvedCallsSimple.kt") + public void testNestedPartiallyResolvedCallsSimple() throws Exception { + runTest("compiler/testData/diagnostics/tests/delegatedProperty/inference/nestedPartiallyResolvedCallsSimple.kt"); + } + @Test @TestMetadata("noErrorsForImplicitConstraints.kt") public void testNoErrorsForImplicitConstraints() throws Exception { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt index 864b14a1dc4..08f93325c94 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt @@ -111,9 +111,13 @@ class FirCallCompleter( ConstraintSystemCompletionMode.PARTIAL -> { runCompletionForCall(candidate, completionMode, call, initialType, analyzer) - if (inferenceSession !is FirBuilderInferenceSession) { + + // Add top-level delegate call as partially resolved to inference session + if (resolutionMode is ResolutionMode.ContextDependentDelegate) { + require(inferenceSession is FirDelegatedPropertyInferenceSession) inferenceSession.addPartiallyResolvedCall(call) } + CompletionResult(call, false) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt index 8aef3fdeb69..530e1e36a9c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt @@ -318,8 +318,9 @@ open class FirDeclarationsResolveTransformer( wrappedDelegateExpression: FirWrappedDelegateExpression, data: ResolutionMode, ): FirStatement { - // First, resolve delegate expression in dependent context - val delegateExpression = wrappedDelegateExpression.expression.transformSingle(transformer, ResolutionMode.ContextDependent) + // First, resolve delegate expression in dependent context, and add potentially partially resolved call to inference session + // (that is why we use ContextDependentDelegate instead of plain ContextDependent) + val delegateExpression = wrappedDelegateExpression.expression.transformSingle(transformer, ResolutionMode.ContextDependentDelegate) .transformSingle(components.integerLiteralAndOperatorApproximationTransformer, null) // Second, replace result type of delegate expression with stub type if delegate not yet resolved diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/inference/differentDelegatedExpressions.fir.kt b/compiler/testData/diagnostics/tests/delegatedProperty/inference/differentDelegatedExpressions.fir.kt index 3dc5b0fb935..082677465c2 100644 --- a/compiler/testData/diagnostics/tests/delegatedProperty/inference/differentDelegatedExpressions.fir.kt +++ b/compiler/testData/diagnostics/tests/delegatedProperty/inference/differentDelegatedExpressions.fir.kt @@ -9,8 +9,8 @@ class A(outer: Outer) { var g: String by outer.getContainer().getMyProperty() - var b: String by foo(getMyProperty()) - var r: String by foo(outer.getContainer().getMyProperty()) + var b: String by foo(getMyProperty()) + var r: String by foo(outer.getContainer().getMyProperty()) var e: String by + foo(getMyProperty()) var f: String by foo(getMyProperty()) - 1 } diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/inference/nestedPartiallyResolvedCalls.kt b/compiler/testData/diagnostics/tests/delegatedProperty/inference/nestedPartiallyResolvedCalls.kt new file mode 100644 index 00000000000..b0a2622e9a4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/delegatedProperty/inference/nestedPartiallyResolvedCalls.kt @@ -0,0 +1,34 @@ +// FIR_IDENTICAL +// WITH_STDLIB +// ISSUE: KT-57543 + +// FILE: JavaClass.java +import kotlin.jvm.functions.Function0; + +public class JavaClass { + + public static class Val { + private final Function0 initializer; + public Val(Function0 initializer) { + this.initializer = initializer; + } + public final T getValue(Object instance, Object metadata) { + return initializer.invoke(); + } + } + + public static Val lazySoft(Function0 initializer) { + return new Val(initializer); + } +} + +// FILE: main.kt + +class A( + val c: Int? = 0, + myType: (() -> Int)? = null +) { + val arguments: A by JavaClass.lazySoft { + A(myType = if (false) null else fun(): Int { return c!! }) + } +} diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/inference/nestedPartiallyResolvedCallsSimple.kt b/compiler/testData/diagnostics/tests/delegatedProperty/inference/nestedPartiallyResolvedCallsSimple.kt new file mode 100644 index 00000000000..d610b77c451 --- /dev/null +++ b/compiler/testData/diagnostics/tests/delegatedProperty/inference/nestedPartiallyResolvedCallsSimple.kt @@ -0,0 +1,16 @@ +// FIR_IDENTICAL +// ISSUE: KT-57543 + +class KotlinVal(initializer: () -> T) { + operator fun getValue(instance: Any?, metadata: Any?): T = TODO() +} + +class A( + myType: (() -> Int)? +) { + val arguments: A by KotlinVal { + A(select(null, fun(): Int { return 1 })) + } +} + +fun select(e: E, f: E): E = TODO() diff --git a/compiler/testData/diagnostics/testsWithStdLib/builderInference/buildListToUpperBoundInLazy.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/builderInference/buildListToUpperBoundInLazy.fir.kt index 56da5a43538..d919a503b59 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/builderInference/buildListToUpperBoundInLazy.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/builderInference/buildListToUpperBoundInLazy.fir.kt @@ -30,7 +30,7 @@ internal class TowerDataElementsForName2() { internal class TowerDataElementsForName3() { val reversedFilteredLocalScopes by lazy(LazyThreadSafetyMode.NONE) { @OptIn(ExperimentalStdlibApi::class) - buildList l1@ { + buildList l1@ { for (i in lastIndex downTo 0) { val reversedFilteredLocalScopes by lazy(LazyThreadSafetyMode.NONE) { @OptIn(ExperimentalStdlibApi::class) diff --git a/compiler/testData/diagnostics/testsWithStdLib/builderInference/buildListToUpperBoundInLazyForbidden.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/builderInference/buildListToUpperBoundInLazyForbidden.fir.kt index 5820fe62d73..28f32fab533 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/builderInference/buildListToUpperBoundInLazyForbidden.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/builderInference/buildListToUpperBoundInLazyForbidden.fir.kt @@ -30,7 +30,7 @@ internal class TowerDataElementsForName2() { internal class TowerDataElementsForName3() { val reversedFilteredLocalScopes by lazy(LazyThreadSafetyMode.NONE) { @OptIn(ExperimentalStdlibApi::class) - buildList l1@ { + buildList l1@ { for (i in lastIndex downTo 0) { val reversedFilteredLocalScopes by lazy(LazyThreadSafetyMode.NONE) { @OptIn(ExperimentalStdlibApi::class) 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 7be93b3b44f..81d5c305018 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 @@ -8937,6 +8937,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/delegatedProperty/inference/manyIncompleteCandidates.kt"); } + @Test + @TestMetadata("nestedPartiallyResolvedCalls.kt") + public void testNestedPartiallyResolvedCalls() throws Exception { + runTest("compiler/testData/diagnostics/tests/delegatedProperty/inference/nestedPartiallyResolvedCalls.kt"); + } + + @Test + @TestMetadata("nestedPartiallyResolvedCallsSimple.kt") + public void testNestedPartiallyResolvedCallsSimple() throws Exception { + runTest("compiler/testData/diagnostics/tests/delegatedProperty/inference/nestedPartiallyResolvedCallsSimple.kt"); + } + @Test @TestMetadata("noErrorsForImplicitConstraints.kt") public void testNoErrorsForImplicitConstraints() throws Exception {