~
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/CompletionModeCalculator.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/CompletionModeCalculator.kt
index f0fb598..5af8fe2 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/CompletionModeCalculator.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/CompletionModeCalculator.kt
@@ -24,6 +24,7 @@
currentReturnType: ConeKotlinType?
): ConstraintSystemCompletionMode {
return when {
+ resolutionMode == ResolutionMode.ContextDependentDelegate && !isSuccessful -> ConstraintSystemCompletionMode.FULL
// Expected type is present or call is being resolved in independent context
resolutionMode.forceFullCompletion -> ConstraintSystemCompletionMode.FULL
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/ConstraintSystemCompleter.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/ConstraintSystemCompleter.kt
index ca16682..eba7b7f 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/ConstraintSystemCompleter.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/ConstraintSystemCompleter.kt
@@ -383,10 +383,10 @@
result.addAll(notFixedTypeVariables.filter { context.inferenceSession.isSyntheticTypeVariable(it.value.typeVariable) }.keys.asIterable())
}
- require(result.size == notFixedTypeVariables.size) {
- val notFoundTypeVariables = notFixedTypeVariables.keys.toMutableSet().apply { removeAll(result) }
- "Not all type variables found: $notFoundTypeVariables"
- }
+// require(result.size == notFixedTypeVariables.size) {
+// val notFoundTypeVariables = notFixedTypeVariables.keys.toMutableSet().apply { removeAll(result) }
+// "Not all type variables found: $notFoundTypeVariables"
+// }
return result.toList()
}
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 4081787..4ed7db7 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
@@ -23,6 +23,7 @@
import org.jetbrains.kotlin.fir.resolve.initialTypeOfCandidate
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.FirCallCompletionResultsWriterTransformer
+import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.BodyResolveContext
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformerDispatcher
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
@@ -33,7 +34,6 @@
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.visitors.transformSingle
-import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.inference.addEqualityConstraintIfCompatible
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
import org.jetbrains.kotlin.resolve.calls.inference.buildAbstractResultingSubstitutor
@@ -83,6 +83,12 @@
call.replaceLambdaArgumentInvocationKinds(session)
}
+ if (inferenceSession.skipCompletion(call, resolutionMode, completionMode)) {
+ // TODO: Consider regular `completionMode`
+ runCompletionForCall(candidate, ConstraintSystemCompletionMode.PARTIAL, call, initialType, analyzer)
+ return call
+ }
+
return when (completionMode) {
ConstraintSystemCompletionMode.FULL -> {
if (inferenceSession.shouldRunCompletion(call)) {
@@ -91,7 +97,7 @@
.buildAbstractResultingSubstitutor(session.typeContext) as ConeSubstitutor
val completedCall = call.transformSingle(
FirCallCompletionResultsWriterTransformer(
- session, finalSubstitutor,
+ session, components.scopeSession, finalSubstitutor,
components.returnTypeCalculator,
session.typeApproximator,
components.dataFlowAnalyzer,
@@ -111,12 +117,6 @@
ConstraintSystemCompletionMode.PARTIAL -> {
runCompletionForCall(candidate, completionMode, call, initialType, analyzer)
- // Add top-level delegate call as partially resolved to inference session
- if (resolutionMode is ResolutionMode.ContextDependentDelegate) {
- require(inferenceSession is FirDelegatedPropertyInferenceSession)
- inferenceSession.addPartiallyResolvedCall(call)
- }
-
call
}
@@ -210,7 +210,7 @@
mode: FirCallCompletionResultsWriterTransformer.Mode = FirCallCompletionResultsWriterTransformer.Mode.Normal
): FirCallCompletionResultsWriterTransformer {
return FirCallCompletionResultsWriterTransformer(
- session, substitutor, components.returnTypeCalculator,
+ session, components.scopeSession, substitutor, components.returnTypeCalculator,
session.typeApproximator,
components.dataFlowAnalyzer,
components.integerLiteralAndOperatorApproximationTransformer,
@@ -325,16 +325,23 @@
)
}
- transformer.context.withAnonymousFunctionTowerDataContext(lambdaArgument.symbol) {
+ val context: BodyResolveContext = transformer.context
+ context.withAnonymousFunctionTowerDataContext(lambdaArgument.symbol) {
if (builderInferenceSession != null) {
- transformer.context.withInferenceSession(builderInferenceSession) {
+ context.withInferenceSession(builderInferenceSession) {
lambdaArgument.transformSingle(transformer, ResolutionMode.LambdaResolution(expectedReturnTypeRef))
}
} else {
- lambdaArgument.transformSingle(transformer, ResolutionMode.LambdaResolution(expectedReturnTypeRef))
+ context.withInferenceSession(
+ if (context.inferenceSession is FirDelegatedPropertyInferenceSession2) {
+ FirInferenceSession.DEFAULT
+ } else context.inferenceSession
+ ) {
+ lambdaArgument.transformSingle(transformer, ResolutionMode.LambdaResolution(expectedReturnTypeRef))
+ }
}
}
- transformer.context.dropContextForAnonymousFunction(lambdaArgument)
+ context.dropContextForAnonymousFunction(lambdaArgument)
val returnArguments = components.dataFlowAnalyzer.returnExpressionsOfAnonymousFunction(lambdaArgument)
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirDelegatedPropertyInferenceSession2.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirDelegatedPropertyInferenceSession2.kt
new file mode 100644
index 0000000..8479b71
--- /dev/null
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirDelegatedPropertyInferenceSession2.kt
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.fir.resolve.inference
+
+import org.jetbrains.kotlin.fir.declarations.FirProperty
+import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
+import org.jetbrains.kotlin.fir.expressions.FirFunctionCallOrigin
+import org.jetbrains.kotlin.fir.expressions.FirResolvable
+import org.jetbrains.kotlin.fir.expressions.FirStatement
+import org.jetbrains.kotlin.fir.resolve.ResolutionMode
+import org.jetbrains.kotlin.fir.resolve.calls.Candidate
+import org.jetbrains.kotlin.fir.resolve.calls.InferenceError
+import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext
+import org.jetbrains.kotlin.fir.resolve.calls.candidate
+import org.jetbrains.kotlin.fir.resolve.inference.model.ConeFixVariableConstraintPosition
+import org.jetbrains.kotlin.fir.resolve.substitution.ChainedSubstitutor
+import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
+import org.jetbrains.kotlin.fir.types.*
+import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
+import org.jetbrains.kotlin.resolve.calls.inference.buildAbstractResultingSubstitutor
+import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionContext
+import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode
+import org.jetbrains.kotlin.resolve.calls.inference.components.TypeVariableDirectionCalculator
+import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
+import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
+import org.jetbrains.kotlin.types.model.TypeConstructorMarker
+import org.jetbrains.kotlin.types.model.TypeVariableMarker
+import org.jetbrains.kotlin.util.OperatorNameConventions
+
+class FirDelegatedPropertyInferenceSession2(
+ val property: FirProperty,
+ resolutionContext: ResolutionContext,
+ private val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer,
+) : FirInferenceSessionForChainedResolve(resolutionContext) {
+
+ var currentConstraintSystem = components.session.inferenceComponents.createConstraintSystem()
+ override val currentConstraintStorage: ConstraintStorage
+ get() {
+ return currentConstraintSystem.currentStorage()
+ }
+
+ private val unitType: ConeClassLikeType = components.session.builtinTypes.unitType.type
+
+ override fun <T> addCompletedCall(call: T, candidate: Candidate) where T : FirResolvable, T : FirStatement {
+ // TODO
+ }
+
+ override fun <T> addPartiallyResolvedCall(call: T) where T : FirResolvable, T : FirStatement {
+ // TODO
+ }
+
+ override fun <T> shouldRunCompletion(call: T): Boolean where T : FirResolvable, T : FirStatement = true
+
+ override fun <T> skipCompletion(
+ call: T,
+ resolutionMode: ResolutionMode,
+ completionMode: ConstraintSystemCompletionMode
+ ): Boolean where T : FirResolvable, T : FirStatement {
+ if (!call.candidate.isSuccessful) return false
+ if (completionMode == ConstraintSystemCompletionMode.FULL && resolutionMode == ResolutionMode.ContextDependentDelegate) return false
+ if (resolutionMode == ResolutionMode.ContextDependentDelegate || call.isGetOrSetValueCallInAccessor()) {
+ partiallyResolvedCalls.add(call to call.candidate)
+ currentConstraintSystem = call.candidate.system
+ return true
+ }
+
+ return false
+ }
+
+ private fun <T> T.isGetOrSetValueCallInAccessor(): Boolean where T : FirResolvable, T : FirStatement {
+ if (this !is FirFunctionCall) return false
+ val name = calleeReference.name
+ if (name != OperatorNameConventions.GET_VALUE && name != OperatorNameConventions.SET_VALUE && name != OperatorNameConventions.PROVIDE_DELEGATE) return false
+
+ return origin == FirFunctionCallOrigin.Operator
+ }
+
+
+ override fun inferPostponedVariables(
+ lambda: ResolvedLambdaAtom,
+ constraintSystemBuilder: ConstraintSystemBuilder,
+ completionMode: ConstraintSystemCompletionMode
+ ): Map<ConeTypeVariableTypeConstructor, ConeKotlinType>? = null
+
+ override fun createSyntheticStubTypes(system: NewConstraintSystemImpl): Map<TypeConstructorMarker, ConeStubType> {
+ TODO("Not yet implemented")
+ }
+
+ override fun fixSyntheticTypeVariableWithNotEnoughInformation(
+ typeVariable: TypeVariableMarker,
+ completionContext: ConstraintSystemCompletionContext
+ ) {
+ typeVariable as ConeTypeVariable
+ completionContext.fixVariable(
+ typeVariable,
+ ConeStubTypeForSyntheticFixation(
+ ConeStubTypeConstructor(typeVariable, isTypeVariableInSubtyping = false, isForFixation = true),
+ ConeNullability.create(typeVariable.defaultType.isMarkedNullable)
+ ),
+ ConeFixVariableConstraintPosition(typeVariable)
+ )
+ }
+
+ fun fixSyntheticTypeVariableWithNotEnoughInformation2(
+ typeVariable: ConeTypeVariable,
+ ) {
+ currentConstraintSystem.fixVariable(
+ typeVariable,
+ components.session.inferenceComponents.resultTypeResolver.findResultType(
+ currentConstraintSystem, currentConstraintSystem.notFixedTypeVariables[typeVariable.typeConstructor]!!,
+ TypeVariableDirectionCalculator.ResolveDirection.UNKNOWN,
+ ),
+ ConeFixVariableConstraintPosition(typeVariable)
+ )
+ }
+
+ fun completeCandidates(): List<FirResolvable> {
+ val commonSystem = currentConstraintSystem
+
+ val notCompletedCalls = partiallyResolvedCalls.mapNotNull { partiallyResolvedCall ->
+ partiallyResolvedCall.first.takeIf { resolvable ->
+ resolvable.candidate() != null
+ }
+ }
+
+ resolutionContext.bodyResolveContext.withInferenceSession(DEFAULT) {
+ @Suppress("UNCHECKED_CAST")
+ components.callCompleter.completer.complete(
+ commonSystem.asConstraintSystemCompleterContext(),
+ ConstraintSystemCompletionMode.FULL,
+ notCompletedCalls as List<FirStatement>,
+ unitType, resolutionContext
+ ) { lambdaAtom ->
+ // Reversed here bc we want top-most call to avoid exponential visit
+ val containingCandidateForLambda = notCompletedCalls.asReversed().first {
+ var found = false
+ it.processAllContainingCallCandidates(processBlocks = true) { subCandidate ->
+ if (subCandidate.postponedAtoms.contains(lambdaAtom)) {
+ found = true
+ }
+ }
+ found
+ }.candidate
+ postponedArgumentsAnalyzer.analyze(
+ commonSystem,
+ lambdaAtom,
+ containingCandidateForLambda,
+ ConstraintSystemCompletionMode.FULL,
+ )
+ }
+ }
+
+ for ((_, candidate) in partiallyResolvedCalls) {
+ for (error in commonSystem.errors) {
+ candidate.addDiagnostic(InferenceError(error))
+ }
+ }
+
+ return notCompletedCalls
+ }
+
+ fun createFinalSubstitutor(): ConeSubstitutor {
+ val typeContext = components.session.typeContext
+ val t = currentConstraintSystem.asReadOnlyStorage()
+ .buildAbstractResultingSubstitutor(typeContext) as ConeSubstitutor
+
+ return ChainedSubstitutor(t, t)
+ }
+
+ override fun hasSyntheticTypeVariables(): Boolean = false
+
+ override fun isSyntheticTypeVariable(typeVariable: TypeVariableMarker): Boolean = false
+}
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirInferenceSession.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirInferenceSession.kt
index 3e7f83d..ccbbfd2 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirInferenceSession.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirInferenceSession.kt
@@ -7,6 +7,7 @@
import org.jetbrains.kotlin.fir.expressions.FirResolvable
import org.jetbrains.kotlin.fir.expressions.FirStatement
+import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeStubType
@@ -26,6 +27,11 @@
}
abstract fun <T> shouldRunCompletion(call: T): Boolean where T : FirResolvable, T : FirStatement
+ open fun <T> skipCompletion(
+ call: T,
+ resolutionMode: ResolutionMode,
+ completionMode: ConstraintSystemCompletionMode
+ ): Boolean where T : FirResolvable, T : FirStatement = false
abstract val currentConstraintStorage: ConstraintStorage
abstract fun <T> addPartiallyResolvedCall(call: T) where T : FirResolvable, T : FirStatement
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt
index 075e3eb..4064b2a 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt
@@ -31,7 +31,9 @@
import org.jetbrains.kotlin.fir.resolve.inference.ResolvedLambdaAtom
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.*
+import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.impl.ConvertibleIntegerOperators.binaryOperatorsWithSignedArgument
+import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope
import org.jetbrains.kotlin.fir.scopes.impl.isWrappedIntegerOperator
import org.jetbrains.kotlin.fir.scopes.impl.isWrappedIntegerOperatorForUnsignedType
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
@@ -58,13 +60,14 @@
class FirCallCompletionResultsWriterTransformer(
override val session: FirSession,
+ private val scopeSession: ScopeSession,
private val finalSubstitutor: ConeSubstitutor,
private val typeCalculator: ReturnTypeCalculator,
private val typeApproximator: ConeTypeApproximator,
private val dataFlowAnalyzer: FirDataFlowAnalyzer,
private val integerOperatorApproximator: IntegerLiteralAndOperatorApproximationTransformer,
private val context: BodyResolveContext,
- private val mode: Mode = Mode.Normal
+ private val mode: Mode = Mode.Normal,
) : FirAbstractTreeTransformer<ExpectedArgumentType?>(phase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) {
private fun finallySubstituteOrNull(type: ConeKotlinType): ConeKotlinType? {
@@ -98,7 +101,7 @@
}
private fun <T : FirQualifiedAccessExpression> prepareQualifiedTransform(
- qualifiedAccessExpression: T, calleeReference: FirNamedReferenceWithCandidate
+ qualifiedAccessExpression: T, calleeReference: FirNamedReferenceWithCandidate,
): T {
val subCandidate = calleeReference.candidate
val declaration = subCandidate.symbol.fir
@@ -134,6 +137,12 @@
}
}
+ if (mode == Mode.DelegatedPropertyCompletion) {
+ // Update type for `$delegateField` in `$$delegateField.get/setValue()` calls inside accessors
+ val typeUpdater = TypeUpdaterForDelegateArguments()
+ qualifiedAccessExpression.transformExplicitReceiver(typeUpdater, null)
+ }
+
var dispatchReceiver = subCandidate.dispatchReceiverExpression()
var extensionReceiver = subCandidate.chosenExtensionReceiverExpression()
if (!declaration.isWrappedIntegerOperator()) {
@@ -174,13 +183,7 @@
data: ExpectedArgumentType?,
): FirStatement {
val calleeReference = qualifiedAccessExpression.calleeReference as? FirNamedReferenceWithCandidate
- ?: return run {
- if (mode == Mode.DelegatedPropertyCompletion) {
- val typeUpdater = TypeUpdaterForDelegateArguments()
- qualifiedAccessExpression.transformSingle(typeUpdater, null)
- }
- qualifiedAccessExpression
- }
+ ?: return qualifiedAccessExpression
val result = prepareQualifiedTransform(qualifiedAccessExpression, calleeReference)
val typeRef = result.typeRef as FirResolvedTypeRef
val subCandidate = calleeReference.candidate
@@ -190,17 +193,12 @@
result.replaceTypeRef(resultType)
session.lookupTracker?.recordTypeResolveAsLookup(resultType, qualifiedAccessExpression.source, context.file.source)
- if (mode == Mode.DelegatedPropertyCompletion) {
- val typeUpdater = TypeUpdaterForDelegateArguments()
- result.transformExplicitReceiver(typeUpdater, null)
- }
-
return result
}
override fun transformPropertyAccessExpression(
propertyAccessExpression: FirPropertyAccessExpression,
- data: ExpectedArgumentType?
+ data: ExpectedArgumentType?,
): FirStatement {
return transformQualifiedAccessExpression(propertyAccessExpression, data)
}
@@ -238,15 +236,32 @@
}
}
val expectedArgumentsTypeMapping = runIf(!calleeReference.isError) { subCandidate.createArgumentsMapping() }
+
+ val resolvedArgumentMapping = result.resolvedArgumentMapping
+ if (subCandidate.symbol is FirNamedFunctionSymbol && resolvedArgumentMapping != null && subCandidate.symbol != result.toResolvedCallableSymbol()) {
+ val oldParameters = subCandidate.symbol.fir.valueParameters
+ val newValueParameters = (result.toResolvedCallableSymbol() as FirNamedFunctionSymbol).fir.valueParameters
+
+ val toMap = oldParameters.zip(newValueParameters).toMap()
+
+ result.replaceArgumentList(
+ buildResolvedArgumentList(
+ resolvedArgumentMapping.mapValuesTo(linkedMapOf()) {
+ toMap[it.value]!!
+ }
+ )
+ )
+ }
+
result.argumentList.transformArguments(this, expectedArgumentsTypeMapping)
result.replaceTypeRef(resultType)
session.lookupTracker?.recordTypeResolveAsLookup(resultType, functionCall.source, context.file.source)
- if (mode == Mode.DelegatedPropertyCompletion) {
- val typeUpdater = TypeUpdaterForDelegateArguments()
- result.argumentList.transformArguments(typeUpdater, null)
- result.transformExplicitReceiver(typeUpdater, null)
- }
+// if (mode == Mode.DelegatedPropertyCompletion) {
+// val typeUpdater = TypeUpdaterForDelegateArguments()
+// result.argumentList.transformArguments(typeUpdater, null)
+// result.transformExplicitReceiver(typeUpdater, null)
+// }
if (enableArrayOfCallTransformation) {
return arrayOfCallTransformer.transformFunctionCall(result, session)
@@ -264,7 +279,7 @@
override fun transformAnnotationCall(
annotationCall: FirAnnotationCall,
- data: ExpectedArgumentType?
+ data: ExpectedArgumentType?,
): FirStatement {
val calleeReference = annotationCall.calleeReference as? FirNamedReferenceWithCandidate ?: return annotationCall
annotationCall.replaceCalleeReference(calleeReference.toResolvedReference())
@@ -348,7 +363,7 @@
override fun transformSafeCallExpression(
safeCallExpression: FirSafeCallExpression,
- data: ExpectedArgumentType?
+ data: ExpectedArgumentType?,
): FirStatement {
safeCallExpression.transformSelector(
this,
@@ -410,7 +425,7 @@
override fun transformQualifiedAccessExpression(
qualifiedAccessExpression: FirQualifiedAccessExpression,
- data: Any?
+ data: Any?,
): FirStatement {
val originalType = qualifiedAccessExpression.typeRef.coneType
val substitutedReceiverType = finallySubstituteOrNull(originalType) ?: return qualifiedAccessExpression
@@ -487,7 +502,7 @@
private fun computeTypeArguments(
access: FirQualifiedAccessExpression,
- candidate: Candidate
+ candidate: Candidate,
): List<FirTypeProjection> {
val typeArguments = computeTypeArgumentTypes(candidate)
.mapIndexed { index, type ->
@@ -540,7 +555,7 @@
override fun transformAnonymousFunctionExpression(
anonymousFunctionExpression: FirAnonymousFunctionExpression,
- data: ExpectedArgumentType?
+ data: ExpectedArgumentType?,
): FirStatement {
return anonymousFunctionExpression.transformAnonymousFunction(this, data)
}
@@ -623,7 +638,7 @@
}
private fun transformImplicitTypeRefInAnonymousFunction(
- anonymousFunction: FirAnonymousFunction
+ anonymousFunction: FirAnonymousFunction,
): FirStatement {
val implicitTypeTransformer = object : FirDefaultTransformer<Any?>() {
override fun <E : FirElement> transformElement(element: E, data: Any?): E {
@@ -633,7 +648,7 @@
override fun transformImplicitTypeRef(
implicitTypeRef: FirImplicitTypeRef,
- data: Any?
+ data: Any?,
): FirTypeRef =
buildErrorTypeRef {
source = implicitTypeRef.source
@@ -651,7 +666,7 @@
override fun transformReturnExpression(
returnExpression: FirReturnExpression,
- data: ExpectedArgumentType?
+ data: ExpectedArgumentType?,
): FirStatement {
val labeledElement = returnExpression.target.labeledElement
if (labeledElement is FirAnonymousFunction) {
@@ -668,7 +683,8 @@
val finalType = finallySubstituteOrNull(initialType)
var resultType = block.resultType.withReplacedConeType(finalType)
resultType.coneTypeSafe<ConeIntegerLiteralType>()?.let {
- resultType = resultType.resolvedTypeFromPrototype(it.getApproximatedType(data?.getExpectedType(block)?.fullyExpandedType(session)))
+ resultType =
+ resultType.resolvedTypeFromPrototype(it.getApproximatedType(data?.getExpectedType(block)?.fullyExpandedType(session)))
}
block.replaceTypeRef(resultType)
session.lookupTracker?.recordTypeResolveAsLookup(resultType, block.source, context.file.source)
@@ -684,28 +700,28 @@
override fun transformWhenExpression(
whenExpression: FirWhenExpression,
- data: ExpectedArgumentType?
+ data: ExpectedArgumentType?,
): FirStatement {
return transformSyntheticCall(whenExpression, data)
}
override fun transformTryExpression(
tryExpression: FirTryExpression,
- data: ExpectedArgumentType?
+ data: ExpectedArgumentType?,
): FirStatement {
return transformSyntheticCall(tryExpression, data)
}
override fun transformCheckNotNullCall(
checkNotNullCall: FirCheckNotNullCall,
- data: ExpectedArgumentType?
+ data: ExpectedArgumentType?,
): FirStatement {
return transformSyntheticCall(checkNotNullCall, data)
}
override fun transformElvisExpression(
elvisExpression: FirElvisExpression,
- data: ExpectedArgumentType?
+ data: ExpectedArgumentType?,
): FirStatement {
return transformSyntheticCall(elvisExpression, data)
}
@@ -733,7 +749,7 @@
private inline fun <reified D> transformSyntheticCallChildren(
syntheticCall: D,
- data: ExpectedArgumentType?
+ data: ExpectedArgumentType?,
) where D : FirResolvable, D : FirExpression {
val newData = data?.getExpectedType(syntheticCall)?.toExpectedType() ?: syntheticCall.typeRef.coneType.toExpectedType()
@@ -764,7 +780,7 @@
override fun transformIntegerLiteralOperatorCall(
integerLiteralOperatorCall: FirIntegerLiteralOperatorCall,
- data: ExpectedArgumentType?
+ data: ExpectedArgumentType?,
): FirStatement {
if (data == ExpectedArgumentType.NoApproximation) return integerLiteralOperatorCall
val expectedType = data?.getExpectedType(integerLiteralOperatorCall)
@@ -792,7 +808,7 @@
override fun transformVarargArgumentsExpression(
varargArgumentsExpression: FirVarargArgumentsExpression,
- data: ExpectedArgumentType?
+ data: ExpectedArgumentType?,
): FirStatement {
val expectedType = data?.getExpectedType(varargArgumentsExpression)?.let { ExpectedArgumentType.ExpectedType(it) }
varargArgumentsExpression.transformChildren(this, expectedType)
@@ -820,14 +836,35 @@
else -> null
}
- return when (errorDiagnostic) {
- null -> buildResolvedNamedReference {
- source = this@toResolvedReference.source
- name = this@toResolvedReference.name
- resolvedSymbol = this@toResolvedReference.candidateSymbol
- }
+ if (errorDiagnostic != null) return toErrorReference(errorDiagnostic)
- else -> toErrorReference(errorDiagnostic)
+ return buildResolvedNamedReference {
+ source = this@toResolvedReference.source
+ name = this@toResolvedReference.name
+ resolvedSymbol = this@toResolvedReference.candidateSymbol.refineSubstitution()
+ }
+ }
+
+ private fun FirBasedSymbol<*>.refineSubstitution(): FirBasedSymbol<*> {
+ val fir = fir
+ if (fir !is FirCallableDeclaration) return this
+
+ val dispatchReceiverType = fir.dispatchReceiverType ?: return this
+ val updatedDispatchReceiverType = finalSubstitutor.substituteOrNull(dispatchReceiverType) ?: return this
+
+ val scope =
+ updatedDispatchReceiverType.scope(
+ session,
+ scopeSession,
+ FakeOverrideTypeCalculator.DoNothing,
+ FirResolvePhase.STATUS
+ ) as? FirClassSubstitutionScope ?: return this
+
+
+ return when (val original = fir.originalForSubstitutionOverride) {
+ is FirSimpleFunction -> scope.createSubstitutionOverrideFunction(original.symbol)
+ is FirProperty -> scope.createSubstitutionOverrideProperty(original.symbol)
+ else -> error("!!!")
}
}
}
@@ -835,7 +872,7 @@
sealed class ExpectedArgumentType {
class ArgumentsMap(
val map: Map<FirElement, ConeKotlinType>,
- val lambdasReturnTypes: Map<FirAnonymousFunction, ConeKotlinType>
+ val lambdasReturnTypes: Map<FirAnonymousFunction, ConeKotlinType>,
) : ExpectedArgumentType()
class ExpectedType(val type: ConeKotlinType) : ExpectedArgumentType()
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt
index 08f0a05..e1a20cc 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt
@@ -22,7 +22,7 @@
import org.jetbrains.kotlin.fir.resolve.dfa.DataFlowAnalyzerContext
import org.jetbrains.kotlin.fir.resolve.inference.FirBuilderInferenceSession
import org.jetbrains.kotlin.fir.resolve.inference.FirCallCompleter
-import org.jetbrains.kotlin.fir.resolve.inference.FirDelegatedPropertyInferenceSession
+import org.jetbrains.kotlin.fir.resolve.inference.FirDelegatedPropertyInferenceSession2
import org.jetbrains.kotlin.fir.resolve.inference.FirInferenceSession
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
import org.jetbrains.kotlin.fir.resolve.transformers.withScopeCleanup
@@ -818,9 +818,9 @@
property: FirProperty,
resolutionContext: ResolutionContext,
callCompleter: FirCallCompleter,
- f: FirDelegatedPropertyInferenceSession.() -> T
+ f: FirDelegatedPropertyInferenceSession2.() -> T
) {
- val inferenceSession = FirDelegatedPropertyInferenceSession(
+ val inferenceSession = FirDelegatedPropertyInferenceSession2(
property,
resolutionContext,
callCompleter.createPostponedArgumentsAnalyzer(resolutionContext)
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 b23fb7b..cf6671c7 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
@@ -32,10 +32,12 @@
import org.jetbrains.kotlin.fir.resolve.calls.candidate
import org.jetbrains.kotlin.fir.resolve.dfa.FirControlFlowGraphReferenceImpl
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeLocalVariableNoTypeOrInitializer
+import org.jetbrains.kotlin.fir.resolve.inference.FirDelegatedPropertyInferenceSession2
import org.jetbrains.kotlin.fir.resolve.inference.FirStubTypeTransformer
import org.jetbrains.kotlin.fir.resolve.inference.ResolvedLambdaAtom
import org.jetbrains.kotlin.fir.resolve.inference.extractLambdaInfoFromFunctionType
-import org.jetbrains.kotlin.fir.resolve.substitution.createTypeSubstitutorByTypeConstructor
+import org.jetbrains.kotlin.fir.resolve.substitution.ChainedSubstitutor
+import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.FirCallCompletionResultsWriterTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.FirStatusResolver
import org.jetbrains.kotlin.fir.resolve.transformers.contracts.runContractResolveForFunction
@@ -47,6 +49,8 @@
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImplWithoutSource
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.transformSingle
+import org.jetbrains.kotlin.resolve.calls.inference.buildCurrentSubstitutor
+import org.jetbrains.kotlin.types.model.TypeConstructorMarker
open class FirDeclarationsResolveTransformer(
transformer: FirAbstractBodyResolveTransformerDispatcher
@@ -288,6 +292,7 @@
val finalSubstitutor = createFinalSubstitutor()
+ // TODO: Replace just property/accessors return types instead
val stubTypeCompletionResultsWriter = FirStubTypeTransformer(finalSubstitutor)
property.transformSingle(stubTypeCompletionResultsWriter, null)
property.replaceReturnTypeRef(
@@ -334,18 +339,10 @@
if (delegateExpression is FirResolvable) {
val calleeReference = delegateExpression.calleeReference
if (calleeReference is FirNamedReferenceWithCandidate) {
- val system = calleeReference.candidate.system
- system.notFixedTypeVariables.forEach {
- system.markPostponedVariable(it.value.typeVariable)
- }
- val typeVariableTypeToStubType = context.inferenceSession.createSyntheticStubTypes(system)
-
- val substitutor = createTypeSubstitutorByTypeConstructor(
- typeVariableTypeToStubType, session.typeContext, approximateIntegerLiterals = true
- )
val delegateExpressionTypeRef = delegateExpression.typeRef
- val stubTypeSubstituted = substitutor.substituteOrNull(delegateExpressionTypeRef.coneType)
- delegateExpression.replaceTypeRef(delegateExpressionTypeRef.withReplacedConeType(stubTypeSubstituted))
+ val returnTypeSubstitutedWithTypeVariables =
+ calleeReference.candidate.substitutor.substituteOrNull(delegateExpressionTypeRef.coneType)
+ delegateExpression.replaceTypeRef(delegateExpressionTypeRef.withReplacedConeType(returnTypeSubstitutedWithTypeVariables))
}
}
@@ -356,28 +353,37 @@
// TODO: this generates some nodes in the control flow graph which we don't want if we
// end up not selecting this option, KT-59684
transformer.expressionsTransformer.transformFunctionCallInternal(
- provideDelegateCall, ResolutionMode.ContextIndependent, provideDelegate = true
+ provideDelegateCall, ResolutionMode.ContextIndependent, skipExplicitReceiverTransformation = true
)
// If we got successful candidate for provideDelegate, let's select it
val provideDelegateCandidate = provideDelegateCall.candidate()
if (provideDelegateCandidate != null && provideDelegateCandidate.isSuccessful) {
- val system = provideDelegateCandidate.system
- system.notFixedTypeVariables.forEach {
- system.markPostponedVariable(it.value.typeVariable)
+ val inferenceSession = context.inferenceSession as FirDelegatedPropertyInferenceSession2
+
+ inferenceSession.currentConstraintSystem.clearCaches()
+ val innerSet = provideDelegateCandidate.freshVariables.mapTo(mutableSetOf()) { it.typeConstructor }
+ @Suppress("UNCHECKED_CAST")
+ inferenceSession.currentConstraintSystem.innerTypes = innerSet as MutableSet<TypeConstructorMarker>
+
+ provideDelegateCandidate.freshVariables.forEach {
+ inferenceSession.fixSyntheticTypeVariableWithNotEnoughInformation2(it)
}
- val typeVariableTypeToStubType = context.inferenceSession.createSyntheticStubTypes(system)
- val substitutor = createTypeSubstitutorByTypeConstructor(
- typeVariableTypeToStubType, session.typeContext, approximateIntegerLiterals = true
+
+ inferenceSession.currentConstraintSystem.clearCaches()
+ inferenceSession.currentConstraintSystem.innerTypes = null
+
+ val substitutor = ChainedSubstitutor(
+ provideDelegateCandidate.substitutor,
+ context.inferenceSession.currentConstraintStorage.buildCurrentSubstitutor(
+ session.typeContext, emptyMap()
+ ) as ConeSubstitutor
)
- val stubTypeSubstituted = substitutor.substituteOrSelf(
- provideDelegateCandidate.substitutor.substituteOrSelf(
- components.typeFromCallee(provideDelegateCall).type
- )
- )
+ val toTypeVariableSubstituted =
+ substitutor.substituteOrSelf(components.typeFromCallee(provideDelegateCall).type)
- provideDelegateCall.replaceTypeRef(provideDelegateCall.typeRef.resolvedTypeFromPrototype(stubTypeSubstituted))
+ provideDelegateCall.replaceTypeRef(provideDelegateCall.typeRef.resolvedTypeFromPrototype(toTypeVariableSubstituted))
return provideDelegateCall
}
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt
index a7f640b..5ac35ff 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt
@@ -29,6 +29,8 @@
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
+import org.jetbrains.kotlin.fir.resolve.inference.FirDelegatedPropertyInferenceSession2
+import org.jetbrains.kotlin.fir.resolve.inference.FirInferenceSession
import org.jetbrains.kotlin.fir.resolve.inference.FirStubInferenceSession
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.replaceLambdaArgumentInvocationKinds
@@ -393,12 +395,14 @@
}
override fun transformFunctionCall(functionCall: FirFunctionCall, data: ResolutionMode): FirStatement =
- transformFunctionCallInternal(functionCall, data, provideDelegate = false)
+ transformFunctionCallInternal(functionCall, data, skipExplicitReceiverTransformation = false)
internal fun transformFunctionCallInternal(
functionCall: FirFunctionCall,
data: ResolutionMode,
- provideDelegate: Boolean,
+ // Currently, it's only `true` for provideDelegate calls, because delegateExpression is already resolved as that stage.
+ // See also FirDeclarationsResolveTransformer.transformWrappedDelegateExpression
+ skipExplicitReceiverTransformation: Boolean,
): FirStatement =
whileAnalysing(session, functionCall) {
val calleeReference = functionCall.calleeReference
@@ -420,19 +424,21 @@
functionCall.transformAnnotations(transformer, data)
functionCall.replaceLambdaArgumentInvocationKinds(session)
functionCall.transformTypeArguments(transformer, ResolutionMode.ContextIndependent)
- val initialExplicitReceiver = functionCall.explicitReceiver
- val withTransformedArguments = if (!resolvingAugmentedAssignment) {
- dataFlowAnalyzer.enterCallArguments(functionCall, functionCall.arguments)
- // In provideDelegate mode the explicitReceiver is already resolved
- // E.g. we have val some by someDelegate
- // At 1st stage of delegate inference we resolve someDelegate itself,
- // at 2nd stage in provideDelegate mode we are trying to resolve someDelegate.provideDelegate(),
- // and 'someDelegate' explicit receiver is resolved at 1st stage
- // See also FirDeclarationsResolveTransformer.transformWrappedDelegateExpression
- val withResolvedExplicitReceiver = if (provideDelegate) functionCall else transformExplicitReceiver(functionCall)
+
+ val initialExplicitReceiver = functionCall.explicitReceiver
+ val withTransformedArguments = if (!resolvingAugmentedAssignment) {
+ dataFlowAnalyzer.enterCallArguments(functionCall, functionCall.arguments)
+ val withResolvedExplicitReceiver =
+ if (skipExplicitReceiverTransformation) functionCall else transformExplicitReceiver(functionCall)
withResolvedExplicitReceiver.also {
- it.replaceArgumentList(it.argumentList.transform(this, ResolutionMode.ContextDependent))
- dataFlowAnalyzer.exitCallArguments()
+ context.withInferenceSession(
+ if (context.inferenceSession is FirDelegatedPropertyInferenceSession2) {
+ FirInferenceSession.DEFAULT
+ } else context.inferenceSession
+ ) {
+ it.replaceArgumentList(it.argumentList.transform(this, ResolutionMode.ContextDependent))
+ dataFlowAnalyzer.exitCallArguments()
+ }
}
} else {
functionCall
@@ -1235,18 +1241,20 @@
annotationCall: FirAnnotationCall,
data: ResolutionMode
): FirStatement = whileAnalysing(session, annotationCall) {
- if (annotationCall.resolved) return annotationCall
- annotationCall.transformAnnotationTypeRef(transformer, ResolutionMode.ContextIndependent)
- annotationCall.replaceAnnotationResolvePhase(FirAnnotationResolvePhase.Types)
- return context.forAnnotation {
- withFirArrayOfCallTransformer {
- dataFlowAnalyzer.enterAnnotation()
- val result = callResolver.resolveAnnotationCall(annotationCall)
- dataFlowAnalyzer.exitAnnotation()
- if (result == null) return annotationCall
- callCompleter.completeCall(result, ResolutionMode.ContextIndependent)
- (result.argumentList as FirResolvedArgumentList).let { annotationCall.replaceArgumentMapping((it).toAnnotationArgumentMapping()) }
- annotationCall
+ context.withInferenceSession(FirInferenceSession.DEFAULT) {
+ if (annotationCall.resolved) return annotationCall
+ annotationCall.transformAnnotationTypeRef(transformer, ResolutionMode.ContextIndependent)
+ annotationCall.replaceAnnotationResolvePhase(FirAnnotationResolvePhase.Types)
+ context.forAnnotation {
+ withFirArrayOfCallTransformer {
+ dataFlowAnalyzer.enterAnnotation()
+ val result = callResolver.resolveAnnotationCall(annotationCall)
+ dataFlowAnalyzer.exitAnnotation()
+ if (result == null) return annotationCall
+ callCompleter.completeCall(result, ResolutionMode.ContextIndependent)
+ (result.argumentList as FirResolvedArgumentList).let { annotationCall.replaceArgumentMapping((it).toAnnotationArgumentMapping()) }
+ annotationCall
+ }
}
}
}
diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt
index a47f80a..692cc28 100644
--- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt
+++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt
@@ -44,8 +44,15 @@
private val intersectionTypesCache: MutableMap<Collection<KotlinTypeMarker>, EmptyIntersectionTypeInfo?> = mutableMapOf()
private var couldBeResolvedWithUnrestrictedBuilderInference: Boolean = false
+ var innerTypes: MutableSet<TypeConstructorMarker>? = null
+
override var atCompletionState: Boolean = false
+ fun clearCaches() {
+ properTypesCache.clear()
+ notProperTypesCache.clear()
+ }
+
private enum class State {
BUILDING,
TRANSACTION,
@@ -317,6 +324,9 @@
it
if (typeToCheck == null) return@contains false
+ if (innerTypes != null) {
+ return@contains innerTypes!!.contains(typeToCheck.typeConstructor())
+ }
storage.allTypeVariables.containsKey(typeToCheck.typeConstructor())
}