[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
This commit is contained in:
+2
-4
@@ -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<TypeConstructor, UnwrappedType> = emptyMap()
|
||||
|
||||
override fun writeOnlyStubs(): Boolean = false
|
||||
override fun callCompleted(resolvedAtom: ResolvedAtom): Boolean = false
|
||||
}
|
||||
|
||||
+4
@@ -28,6 +28,7 @@ abstract class ManyCandidatesResolver<D : CallableDescriptor>(
|
||||
) : InferenceSession {
|
||||
private val partiallyResolvedCallsInfo = arrayListOf<PSIPartialCallInfo>()
|
||||
private val errorCallsInfo = arrayListOf<PSIErrorCallInfo<D>>()
|
||||
private val completedCalls = hashSetOf<ResolvedAtom>()
|
||||
|
||||
open fun prepareForCompletion(commonSystem: NewConstraintSystem, resolvedCallsInfo: List<PSIPartialCallInfo>) {
|
||||
// do nothing
|
||||
@@ -59,6 +60,9 @@ abstract class ManyCandidatesResolver<D : CallableDescriptor>(
|
||||
return partiallyResolvedCallsInfo.lastOrNull()?.callResolutionResult?.constraintSystem ?: ConstraintStorage.Empty
|
||||
}
|
||||
|
||||
override fun callCompleted(resolvedAtom: ResolvedAtom): Boolean =
|
||||
!completedCalls.add(resolvedAtom)
|
||||
|
||||
fun resolveCandidates(resolutionCallbacks: KotlinResolutionCallbacks): List<ResolutionResultCallInfo<D>> {
|
||||
val resolvedCallsInfo = partiallyResolvedCallsInfo.toList()
|
||||
|
||||
|
||||
+4
@@ -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)
|
||||
|
||||
+2
@@ -25,6 +25,7 @@ interface InferenceSession {
|
||||
): Map<TypeConstructor, UnwrappedType> = 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<TypeConstructor, UnwrappedType>
|
||||
fun writeOnlyStubs(): Boolean
|
||||
fun callCompleted(resolvedAtom: ResolvedAtom): Boolean
|
||||
}
|
||||
|
||||
interface PartialCallInfo {
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class Inv2<T, K>
|
||||
|
||||
fun <T, K> create(g: (T) -> K): Inv2<T, K> = TODO()
|
||||
|
||||
operator fun <S1, V1> Inv2<S1, V1>.getValue(o: Sample, desc: KProperty<*>): V1 = TODO()
|
||||
operator fun <S2, V2> Inv2<S2, V2>.setValue(o: Sample, desc: KProperty<*>, value: V2) {}
|
||||
|
||||
class Version(val version: Int)
|
||||
|
||||
class Sample {
|
||||
var version: Version by create(::Version)
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ T, /*1*/ K> create(/*0*/ g: (T) -> K): Inv2<T, K>
|
||||
public operator fun </*0*/ S1, /*1*/ V1> Inv2<S1, V1>.getValue(/*0*/ o: Sample, /*1*/ desc: kotlin.reflect.KProperty<*>): V1
|
||||
public operator fun </*0*/ S2, /*1*/ V2> Inv2<S2, V2>.setValue(/*0*/ o: Sample, /*1*/ desc: kotlin.reflect.KProperty<*>, /*2*/ value: V2): kotlin.Unit
|
||||
|
||||
public final class Inv2</*0*/ T, /*1*/ K> {
|
||||
public constructor Inv2</*0*/ T, /*1*/ K>()
|
||||
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
|
||||
}
|
||||
@@ -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");
|
||||
|
||||
Generated
+5
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user