From 7c357c0ec0ae43291457fc5fe40a0e65699f087e Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Mon, 4 Mar 2019 17:24:27 +0300 Subject: [PATCH] [NI] Complete calls during one inference session only once The problem is that delegated properties resolve two calls together: `getValue`/`setValue` with a common receiver, which can contain callable references. For each completion new anonymous descriptor was created and caused "rewrite at slice" exceptions later. Now there is a little hack to check that during one inference session we don't complete one call more than one time. More correct fix would be to explicitly specify common receiver for inference session but it requires quite big refactoring, which will be done later with a whole refactoring of the common solver #KT-30250 Fixed --- .../DelegatedPropertyInferenceSession.kt | 6 ++-- .../calls/tower/ManyCandidatesResolver.kt | 4 +++ .../calls/tower/ResolvedAtomCompleter.kt | 4 +++ .../calls/components/InferenceSession.kt | 2 ++ ...eReferenceArgumentInDelegatedExpression.kt | 17 +++++++++++ ...ReferenceArgumentInDelegatedExpression.txt | 28 +++++++++++++++++++ .../checkers/DiagnosticsTestGenerated.java | 5 ++++ .../DiagnosticsUsingJavacTestGenerated.java | 5 ++++ 8 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/delegatedProperty/inference/callableReferenceArgumentInDelegatedExpression.kt create mode 100644 compiler/testData/diagnostics/tests/delegatedProperty/inference/callableReferenceArgumentInDelegatedExpression.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyInferenceSession.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyInferenceSession.kt index 2d8ccda57d4..6e050824ec5 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyInferenceSession.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyInferenceSession.kt @@ -15,10 +15,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.inference.model.DelegatedPropertyConstraintPosition -import org.jetbrains.kotlin.resolve.calls.model.KotlinCallComponents -import org.jetbrains.kotlin.resolve.calls.model.KotlinResolutionCandidate -import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallAtom -import org.jetbrains.kotlin.resolve.calls.model.ResolvedLambdaAtom +import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.tower.ManyCandidatesResolver import org.jetbrains.kotlin.resolve.calls.tower.PSICallResolver import org.jetbrains.kotlin.resolve.calls.tower.PSIPartialCallInfo @@ -106,4 +103,5 @@ object InferenceSessionForExistingCandidates : InferenceSession { ): Map = emptyMap() override fun writeOnlyStubs(): Boolean = false + override fun callCompleted(resolvedAtom: ResolvedAtom): Boolean = false } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ManyCandidatesResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ManyCandidatesResolver.kt index f5b7de9b60b..e3ef448a063 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ManyCandidatesResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ManyCandidatesResolver.kt @@ -28,6 +28,7 @@ abstract class ManyCandidatesResolver( ) : InferenceSession { private val partiallyResolvedCallsInfo = arrayListOf() private val errorCallsInfo = arrayListOf>() + private val completedCalls = hashSetOf() open fun prepareForCompletion(commonSystem: NewConstraintSystem, resolvedCallsInfo: List) { // do nothing @@ -59,6 +60,9 @@ abstract class ManyCandidatesResolver( return partiallyResolvedCallsInfo.lastOrNull()?.callResolutionResult?.constraintSystem ?: ConstraintStorage.Empty } + override fun callCompleted(resolvedAtom: ResolvedAtom): Boolean = + !completedCalls.add(resolvedAtom) + fun resolveCandidates(resolutionCallbacks: KotlinResolutionCallbacks): List> { val resolvedCallsInfo = partiallyResolvedCallsInfo.toList() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt index 76fe7001c62..e533ca8f39c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt @@ -55,6 +55,10 @@ class ResolvedAtomCompleter( private val topLevelTrace = topLevelCallCheckerContext.trace private fun complete(resolvedAtom: ResolvedAtom) { + if (topLevelCallContext.inferenceSession.callCompleted(resolvedAtom)) { + return + } + when (resolvedAtom) { is ResolvedCollectionLiteralAtom -> completeCollectionLiteralCalls(resolvedAtom) is ResolvedCallableReferenceAtom -> completeCallableReference(resolvedAtom) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/InferenceSession.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/InferenceSession.kt index deb9f8dd9ab..df9c86a2a72 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/InferenceSession.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/InferenceSession.kt @@ -25,6 +25,7 @@ interface InferenceSession { ): Map = emptyMap() override fun writeOnlyStubs(): Boolean = false + override fun callCompleted(resolvedAtom: ResolvedAtom): Boolean = false } } @@ -35,6 +36,7 @@ interface InferenceSession { fun currentConstraintSystem(): ConstraintStorage fun inferPostponedVariables(lambda: ResolvedLambdaAtom, initialStorage: ConstraintStorage): Map fun writeOnlyStubs(): Boolean + fun callCompleted(resolvedAtom: ResolvedAtom): Boolean } interface PartialCallInfo { diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/inference/callableReferenceArgumentInDelegatedExpression.kt b/compiler/testData/diagnostics/tests/delegatedProperty/inference/callableReferenceArgumentInDelegatedExpression.kt new file mode 100644 index 00000000000..8025b9d7d9e --- /dev/null +++ b/compiler/testData/diagnostics/tests/delegatedProperty/inference/callableReferenceArgumentInDelegatedExpression.kt @@ -0,0 +1,17 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +import kotlin.reflect.KProperty + +class Inv2 + +fun create(g: (T) -> K): Inv2 = TODO() + +operator fun Inv2.getValue(o: Sample, desc: KProperty<*>): V1 = TODO() +operator fun Inv2.setValue(o: Sample, desc: KProperty<*>, value: V2) {} + +class Version(val version: Int) + +class Sample { + var version: Version by create(::Version) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/inference/callableReferenceArgumentInDelegatedExpression.txt b/compiler/testData/diagnostics/tests/delegatedProperty/inference/callableReferenceArgumentInDelegatedExpression.txt new file mode 100644 index 00000000000..9d263cb8de7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/delegatedProperty/inference/callableReferenceArgumentInDelegatedExpression.txt @@ -0,0 +1,28 @@ +package + +public fun create(/*0*/ g: (T) -> K): Inv2 +public operator fun Inv2.getValue(/*0*/ o: Sample, /*1*/ desc: kotlin.reflect.KProperty<*>): V1 +public operator fun Inv2.setValue(/*0*/ o: Sample, /*1*/ desc: kotlin.reflect.KProperty<*>, /*2*/ value: V2): kotlin.Unit + +public final class Inv2 { + public constructor Inv2() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class Sample { + public constructor Sample() + public final var version: Version + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class Version { + public constructor Version(/*0*/ version: kotlin.Int) + public final val version: kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 671325c87af..98b7ccd5d6c 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -5625,6 +5625,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/delegatedProperty/inference"), Pattern.compile("^(.*)\\.kts?$"), TargetBackend.ANY, true); } + @TestMetadata("callableReferenceArgumentInDelegatedExpression.kt") + public void testCallableReferenceArgumentInDelegatedExpression() throws Exception { + runTest("compiler/testData/diagnostics/tests/delegatedProperty/inference/callableReferenceArgumentInDelegatedExpression.kt"); + } + @TestMetadata("delegateExpressionAsLambda.kt") public void testDelegateExpressionAsLambda() throws Exception { runTest("compiler/testData/diagnostics/tests/delegatedProperty/inference/delegateExpressionAsLambda.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 2942ef9917e..7d1c2d9e990 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -5620,6 +5620,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/delegatedProperty/inference"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); } + @TestMetadata("callableReferenceArgumentInDelegatedExpression.kt") + public void testCallableReferenceArgumentInDelegatedExpression() throws Exception { + runTest("compiler/testData/diagnostics/tests/delegatedProperty/inference/callableReferenceArgumentInDelegatedExpression.kt"); + } + @TestMetadata("delegateExpressionAsLambda.kt") public void testDelegateExpressionAsLambda() throws Exception { runTest("compiler/testData/diagnostics/tests/delegatedProperty/inference/delegateExpressionAsLambda.kt");