diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolver/SingleCandidateResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolver/SingleCandidateResolver.kt index ede3aa5d757..32e9ed657e2 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolver/SingleCandidateResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolver/SingleCandidateResolver.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.expressions.FirEmptyArgumentList import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.builder.buildFunctionCall +import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.calls.* import org.jetbrains.kotlin.fir.resolve.createConeDiagnosticForCandidateWithError import org.jetbrains.kotlin.fir.resolve.inference.FirCallCompleter @@ -74,8 +75,10 @@ class SingleCandidateResolver( return null } - val expectedType = resolutionParameters.expectedType ?: bodyResolveComponents.noExpectedType - val completionResult = firCallCompleter.completeCall(fakeCall, expectedType) + val completionResult = firCallCompleter.completeCall( + fakeCall, + resolutionParameters.expectedType?.let(ResolutionMode::WithExpectedType) ?: ResolutionMode.ContextIndependent + ) return completionResult.takeIf { it.callCompleted }?.result } 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 ce579e7a753..0b49451648e 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 @@ -56,39 +56,7 @@ class FirCallCompleter( data class CompletionResult(val result: T, val callCompleted: Boolean) - fun completeCall( - call: T, - expectedTypeRef: FirTypeRef?, - expectedTypeMismatchIsReportedInChecker: Boolean = false, - ): CompletionResult where T : FirResolvable, T : FirStatement = - completeCall( - call, - expectedTypeRef, - mayBeCoercionToUnitApplied = false, - expectedTypeMismatchIsReportedInChecker, - isFromCast = false, - shouldEnforceExpectedType = true, - ) - - fun completeCall(call: T, data: ResolutionMode): CompletionResult where T : FirResolvable, T : FirStatement = - completeCall( - call, - data.expectedType(components, allowFromCast = true), - (data as? ResolutionMode.WithExpectedType)?.mayBeCoercionToUnitApplied == true, - (data as? ResolutionMode.WithExpectedType)?.expectedTypeMismatchIsReportedInChecker == true, - isFromCast = (data as? ResolutionMode.WithExpectedType)?.fromCast == true, - shouldEnforceExpectedType = (data as? ResolutionMode.WithExpectedType)?.shouldBeStrictlyEnforced == true, - ) - - private fun completeCall( - call: T, - expectedTypeRef: FirTypeRef?, - mayBeCoercionToUnitApplied: Boolean, - expectedTypeMismatchIsReportedInChecker: Boolean, - isFromCast: Boolean, - shouldEnforceExpectedType: Boolean, - ): CompletionResult - where T : FirResolvable, T : FirStatement { + fun completeCall(call: T, resolutionMode: ResolutionMode): CompletionResult where T : FirResolvable, T : FirStatement { val typeRef = components.typeFromCallee(call) val reference = call.calleeReference as? FirNamedReferenceWithCandidate ?: return CompletionResult(call, true) @@ -103,16 +71,14 @@ class FirCallCompleter( } addConstraintFromExpectedType( - expectedTypeMismatchIsReportedInChecker, - expectedTypeRef, - shouldEnforceExpectedType, candidate, initialType, - isFromCast, - mayBeCoercionToUnitApplied + resolutionMode, ) - val completionMode = candidate.computeCompletionMode(session.inferenceComponents, expectedTypeRef, initialType) + val completionMode = candidate.computeCompletionMode( + session.inferenceComponents, resolutionMode.expectedType(components, allowFromCast = true), initialType + ) val analyzer = createPostponedArgumentsAnalyzer(transformer.resolutionContext) if (call is FirFunctionCall) { @@ -157,15 +123,12 @@ class FirCallCompleter( } private fun addConstraintFromExpectedType( - expectedTypeMismatchIsReportedInChecker: Boolean, - expectedTypeRef: FirTypeRef?, - shouldEnforceExpectedType: Boolean, candidate: Candidate, initialType: ConeKotlinType, - isFromCast: Boolean, - mayBeCoercionToUnitApplied: Boolean + resolutionMode: ResolutionMode, ) { - val expectedType = expectedTypeRef?.coneTypeSafe() ?: return + if (resolutionMode !is ResolutionMode.WithExpectedType) return + val expectedType = resolutionMode.expectedTypeRef.coneTypeSafe() ?: return val system = candidate.system when { @@ -175,10 +138,10 @@ class FirCallCompleter( // It's assumed to be safe & sound, because if constraint system has contradictions when expected type is added, // the resulting expression type cannot be inferred to something that is a subtype of `expectedType`, // thus the diagnostic should be reported. - !shouldEnforceExpectedType || expectedTypeMismatchIsReportedInChecker -> { + !resolutionMode.shouldBeStrictlyEnforced || resolutionMode.expectedTypeMismatchIsReportedInChecker -> { system.addSubtypeConstraintIfCompatible(initialType, expectedType, ConeExpectedTypeConstraintPosition) } - isFromCast -> { + resolutionMode.fromCast -> { if (candidate.isFunctionForExpectTypeFromCastFeature()) { system.addSubtypeConstraint( initialType, expectedType, @@ -186,7 +149,7 @@ class FirCallCompleter( ) } } - !expectedType.isUnitOrFlexibleUnit || (!mayBeCoercionToUnitApplied && !expectedTypeMismatchIsReportedInChecker) -> { + !expectedType.isUnitOrFlexibleUnit || !resolutionMode.mayBeCoercionToUnitApplied -> { system.addSubtypeConstraint(initialType, expectedType, ConeExpectedTypeConstraintPosition) } system.notFixedTypeVariables.isEmpty() -> return @@ -411,4 +374,3 @@ internal fun FirFunction.isFunctionForExpectTypeFromCastFeature(): Boolean { private fun ConeKotlinType.unwrap(): ConeSimpleKotlinType = lowerBoundIfFlexible().let { if (it is ConeDefinitelyNotNullType) it.original.unwrap() else it } - 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 4fb30d787f2..71f2fef9d8c 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 @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.fir.moduleData import org.jetbrains.kotlin.fir.references.FirReference import org.jetbrains.kotlin.fir.references.impl.FirStubReference import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents +import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.calls.* import org.jetbrains.kotlin.fir.resolve.createErrorReferenceWithExistingCandidate import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError @@ -182,7 +183,7 @@ class FirSyntheticCallGenerator( this.argumentList = argumentList } - val argument = components.callCompleter.completeCall(fakeCallElement, expectedTypeRef = null).result.argument + val argument = components.callCompleter.completeCall(fakeCallElement, ResolutionMode.ContextIndependent).result.argument return argument as FirCallableReferenceAccess? } 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 5d48111e959..4d41bab8140 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 @@ -421,7 +421,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT val resultExplicitReceiver = resultExpression.explicitReceiver?.unwrapSmartcastExpression() if (initialExplicitReceiver !== resultExplicitReceiver && resultExplicitReceiver is FirQualifiedAccessExpression) { // name.invoke() case - callCompleter.completeCall(resultExplicitReceiver, noExpectedType) + callCompleter.completeCall(resultExplicitReceiver, ResolutionMode.ContextIndependent) } callCompleter.completeCall(resultExpression, data) } @@ -607,7 +607,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT val lhsIsVar = lhsVariable?.isVar == true fun chooseAssign(): FirStatement { - callCompleter.completeCall(resolvedAssignCall, noExpectedType) + callCompleter.completeCall(resolvedAssignCall, ResolutionMode.ContextIndependent) dataFlowAnalyzer.exitFunctionCall(resolvedAssignCall, callCompleted = true) return resolvedAssignCall } @@ -615,8 +615,9 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT fun chooseOperator(): FirStatement { callCompleter.completeCall( resolvedOperatorCall, - lhsVariable?.returnTypeRef ?: noExpectedType, - expectedTypeMismatchIsReportedInChecker = true + lhsVariable?.returnTypeRef?.let { + ResolutionMode.WithExpectedType(it, expectedTypeMismatchIsReportedInChecker = true) + } ?: ResolutionMode.ContextIndependent, ) dataFlowAnalyzer.exitFunctionCall(resolvedOperatorCall, callCompleted = true) @@ -1116,7 +1117,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT val result = callResolver.resolveAnnotationCall(annotationCall) dataFlowAnalyzer.exitAnnotation() if (result == null) return annotationCall - callCompleter.completeCall(result, noExpectedType) + callCompleter.completeCall(result, ResolutionMode.ContextIndependent) (result.argumentList as FirResolvedArgumentList).let { annotationCall.replaceArgumentMapping((it).toAnnotationArgumentMapping()) } annotationCall } @@ -1188,7 +1189,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT // it seems that we may leave this code as is // without adding `context.withTowerDataContext(context.getTowerDataContextForConstructorResolution())` - val (result, callCompleted) = callCompleter.completeCall(resolvedCall, noExpectedType) + val (result, callCompleted) = callCompleter.completeCall(resolvedCall, ResolutionMode.ContextIndependent) dataFlowAnalyzer.exitDelegatedConstructorCall(result, callCompleted) return result } @@ -1280,7 +1281,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT val assignIsSuccessful = assignCallReference?.isError == false fun chooseAssign(): FirFunctionCall { - callCompleter.completeCall(resolvedAssignCall, noExpectedType) + callCompleter.completeCall(resolvedAssignCall, ResolutionMode.ContextIndependent) dataFlowAnalyzer.exitFunctionCall(resolvedAssignCall, callCompleted = true) return resolvedAssignCall } @@ -1308,11 +1309,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT val setIsSuccessful = setCallReference?.isError == false fun chooseSetOperator(): FirStatement { - callCompleter.completeCall( - resolvedSetCall, - noExpectedType, - expectedTypeMismatchIsReportedInChecker = true - ) + callCompleter.completeCall(resolvedSetCall, ResolutionMode.ContextIndependent) dataFlowAnalyzer.exitFunctionCall(resolvedSetCall, callCompleted = true) return info.toBlock() } @@ -1488,7 +1485,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT } val syntheticIdCall = components.syntheticCallGenerator.generateSyntheticCallForArrayOfCall(arrayOfCall, resolutionContext) arrayOfCall.transformChildren(transformer, ResolutionMode.ContextDependent) - callCompleter.completeCall(syntheticIdCall, data.expectedType ?: components.noExpectedType) + callCompleter.completeCall(syntheticIdCall, data) return arrayOfCall }