K2: Unify completeCall overloads and usages

- Leave only the overload with ResolutionMode parameter
- Get rid of boolean flags that belong to ResolutionMode.WithExpectedType
This commit is contained in:
Denis.Zharkov
2022-12-01 13:55:10 +01:00
committed by Space Team
parent 73fa41f7fb
commit 28ff276320
4 changed files with 28 additions and 65 deletions
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.expressions.FirEmptyArgumentList
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.builder.buildFunctionCall 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.calls.*
import org.jetbrains.kotlin.fir.resolve.createConeDiagnosticForCandidateWithError import org.jetbrains.kotlin.fir.resolve.createConeDiagnosticForCandidateWithError
import org.jetbrains.kotlin.fir.resolve.inference.FirCallCompleter import org.jetbrains.kotlin.fir.resolve.inference.FirCallCompleter
@@ -74,8 +75,10 @@ class SingleCandidateResolver(
return null return null
} }
val expectedType = resolutionParameters.expectedType ?: bodyResolveComponents.noExpectedType val completionResult = firCallCompleter.completeCall(
val completionResult = firCallCompleter.completeCall(fakeCall, expectedType) fakeCall,
resolutionParameters.expectedType?.let(ResolutionMode::WithExpectedType) ?: ResolutionMode.ContextIndependent
)
return completionResult.takeIf { it.callCompleted }?.result return completionResult.takeIf { it.callCompleted }?.result
} }
@@ -56,39 +56,7 @@ class FirCallCompleter(
data class CompletionResult<T>(val result: T, val callCompleted: Boolean) data class CompletionResult<T>(val result: T, val callCompleted: Boolean)
fun <T> completeCall( fun <T> completeCall(call: T, resolutionMode: ResolutionMode): CompletionResult<T> where T : FirResolvable, T : FirStatement {
call: T,
expectedTypeRef: FirTypeRef?,
expectedTypeMismatchIsReportedInChecker: Boolean = false,
): CompletionResult<T> where T : FirResolvable, T : FirStatement =
completeCall(
call,
expectedTypeRef,
mayBeCoercionToUnitApplied = false,
expectedTypeMismatchIsReportedInChecker,
isFromCast = false,
shouldEnforceExpectedType = true,
)
fun <T> completeCall(call: T, data: ResolutionMode): CompletionResult<T> 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 <T> completeCall(
call: T,
expectedTypeRef: FirTypeRef?,
mayBeCoercionToUnitApplied: Boolean,
expectedTypeMismatchIsReportedInChecker: Boolean,
isFromCast: Boolean,
shouldEnforceExpectedType: Boolean,
): CompletionResult<T>
where T : FirResolvable, T : FirStatement {
val typeRef = components.typeFromCallee(call) val typeRef = components.typeFromCallee(call)
val reference = call.calleeReference as? FirNamedReferenceWithCandidate ?: return CompletionResult(call, true) val reference = call.calleeReference as? FirNamedReferenceWithCandidate ?: return CompletionResult(call, true)
@@ -103,16 +71,14 @@ class FirCallCompleter(
} }
addConstraintFromExpectedType( addConstraintFromExpectedType(
expectedTypeMismatchIsReportedInChecker,
expectedTypeRef,
shouldEnforceExpectedType,
candidate, candidate,
initialType, initialType,
isFromCast, resolutionMode,
mayBeCoercionToUnitApplied
) )
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) val analyzer = createPostponedArgumentsAnalyzer(transformer.resolutionContext)
if (call is FirFunctionCall) { if (call is FirFunctionCall) {
@@ -157,15 +123,12 @@ class FirCallCompleter(
} }
private fun addConstraintFromExpectedType( private fun addConstraintFromExpectedType(
expectedTypeMismatchIsReportedInChecker: Boolean,
expectedTypeRef: FirTypeRef?,
shouldEnforceExpectedType: Boolean,
candidate: Candidate, candidate: Candidate,
initialType: ConeKotlinType, initialType: ConeKotlinType,
isFromCast: Boolean, resolutionMode: ResolutionMode,
mayBeCoercionToUnitApplied: Boolean
) { ) {
val expectedType = expectedTypeRef?.coneTypeSafe<ConeKotlinType>() ?: return if (resolutionMode !is ResolutionMode.WithExpectedType) return
val expectedType = resolutionMode.expectedTypeRef.coneTypeSafe<ConeKotlinType>() ?: return
val system = candidate.system val system = candidate.system
when { 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, // 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`, // the resulting expression type cannot be inferred to something that is a subtype of `expectedType`,
// thus the diagnostic should be reported. // thus the diagnostic should be reported.
!shouldEnforceExpectedType || expectedTypeMismatchIsReportedInChecker -> { !resolutionMode.shouldBeStrictlyEnforced || resolutionMode.expectedTypeMismatchIsReportedInChecker -> {
system.addSubtypeConstraintIfCompatible(initialType, expectedType, ConeExpectedTypeConstraintPosition) system.addSubtypeConstraintIfCompatible(initialType, expectedType, ConeExpectedTypeConstraintPosition)
} }
isFromCast -> { resolutionMode.fromCast -> {
if (candidate.isFunctionForExpectTypeFromCastFeature()) { if (candidate.isFunctionForExpectTypeFromCastFeature()) {
system.addSubtypeConstraint( system.addSubtypeConstraint(
initialType, expectedType, initialType, expectedType,
@@ -186,7 +149,7 @@ class FirCallCompleter(
) )
} }
} }
!expectedType.isUnitOrFlexibleUnit || (!mayBeCoercionToUnitApplied && !expectedTypeMismatchIsReportedInChecker) -> { !expectedType.isUnitOrFlexibleUnit || !resolutionMode.mayBeCoercionToUnitApplied -> {
system.addSubtypeConstraint(initialType, expectedType, ConeExpectedTypeConstraintPosition) system.addSubtypeConstraint(initialType, expectedType, ConeExpectedTypeConstraintPosition)
} }
system.notFixedTypeVariables.isEmpty() -> return system.notFixedTypeVariables.isEmpty() -> return
@@ -411,4 +374,3 @@ internal fun FirFunction.isFunctionForExpectTypeFromCastFeature(): Boolean {
private fun ConeKotlinType.unwrap(): ConeSimpleKotlinType = lowerBoundIfFlexible().let { private fun ConeKotlinType.unwrap(): ConeSimpleKotlinType = lowerBoundIfFlexible().let {
if (it is ConeDefinitelyNotNullType) it.original.unwrap() else it if (it is ConeDefinitelyNotNullType) it.original.unwrap() else it
} }
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.references.FirReference import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.references.impl.FirStubReference import org.jetbrains.kotlin.fir.references.impl.FirStubReference
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents 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.calls.*
import org.jetbrains.kotlin.fir.resolve.createErrorReferenceWithExistingCandidate import org.jetbrains.kotlin.fir.resolve.createErrorReferenceWithExistingCandidate
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError
@@ -182,7 +183,7 @@ class FirSyntheticCallGenerator(
this.argumentList = argumentList 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? return argument as FirCallableReferenceAccess?
} }
@@ -421,7 +421,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
val resultExplicitReceiver = resultExpression.explicitReceiver?.unwrapSmartcastExpression() val resultExplicitReceiver = resultExpression.explicitReceiver?.unwrapSmartcastExpression()
if (initialExplicitReceiver !== resultExplicitReceiver && resultExplicitReceiver is FirQualifiedAccessExpression) { if (initialExplicitReceiver !== resultExplicitReceiver && resultExplicitReceiver is FirQualifiedAccessExpression) {
// name.invoke() case // name.invoke() case
callCompleter.completeCall(resultExplicitReceiver, noExpectedType) callCompleter.completeCall(resultExplicitReceiver, ResolutionMode.ContextIndependent)
} }
callCompleter.completeCall(resultExpression, data) callCompleter.completeCall(resultExpression, data)
} }
@@ -607,7 +607,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
val lhsIsVar = lhsVariable?.isVar == true val lhsIsVar = lhsVariable?.isVar == true
fun chooseAssign(): FirStatement { fun chooseAssign(): FirStatement {
callCompleter.completeCall(resolvedAssignCall, noExpectedType) callCompleter.completeCall(resolvedAssignCall, ResolutionMode.ContextIndependent)
dataFlowAnalyzer.exitFunctionCall(resolvedAssignCall, callCompleted = true) dataFlowAnalyzer.exitFunctionCall(resolvedAssignCall, callCompleted = true)
return resolvedAssignCall return resolvedAssignCall
} }
@@ -615,8 +615,9 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
fun chooseOperator(): FirStatement { fun chooseOperator(): FirStatement {
callCompleter.completeCall( callCompleter.completeCall(
resolvedOperatorCall, resolvedOperatorCall,
lhsVariable?.returnTypeRef ?: noExpectedType, lhsVariable?.returnTypeRef?.let {
expectedTypeMismatchIsReportedInChecker = true ResolutionMode.WithExpectedType(it, expectedTypeMismatchIsReportedInChecker = true)
} ?: ResolutionMode.ContextIndependent,
) )
dataFlowAnalyzer.exitFunctionCall(resolvedOperatorCall, callCompleted = true) dataFlowAnalyzer.exitFunctionCall(resolvedOperatorCall, callCompleted = true)
@@ -1116,7 +1117,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
val result = callResolver.resolveAnnotationCall(annotationCall) val result = callResolver.resolveAnnotationCall(annotationCall)
dataFlowAnalyzer.exitAnnotation() dataFlowAnalyzer.exitAnnotation()
if (result == null) return annotationCall if (result == null) return annotationCall
callCompleter.completeCall(result, noExpectedType) callCompleter.completeCall(result, ResolutionMode.ContextIndependent)
(result.argumentList as FirResolvedArgumentList).let { annotationCall.replaceArgumentMapping((it).toAnnotationArgumentMapping()) } (result.argumentList as FirResolvedArgumentList).let { annotationCall.replaceArgumentMapping((it).toAnnotationArgumentMapping()) }
annotationCall annotationCall
} }
@@ -1188,7 +1189,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
// it seems that we may leave this code as is // it seems that we may leave this code as is
// without adding `context.withTowerDataContext(context.getTowerDataContextForConstructorResolution())` // 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) dataFlowAnalyzer.exitDelegatedConstructorCall(result, callCompleted)
return result return result
} }
@@ -1280,7 +1281,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
val assignIsSuccessful = assignCallReference?.isError == false val assignIsSuccessful = assignCallReference?.isError == false
fun chooseAssign(): FirFunctionCall { fun chooseAssign(): FirFunctionCall {
callCompleter.completeCall(resolvedAssignCall, noExpectedType) callCompleter.completeCall(resolvedAssignCall, ResolutionMode.ContextIndependent)
dataFlowAnalyzer.exitFunctionCall(resolvedAssignCall, callCompleted = true) dataFlowAnalyzer.exitFunctionCall(resolvedAssignCall, callCompleted = true)
return resolvedAssignCall return resolvedAssignCall
} }
@@ -1308,11 +1309,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
val setIsSuccessful = setCallReference?.isError == false val setIsSuccessful = setCallReference?.isError == false
fun chooseSetOperator(): FirStatement { fun chooseSetOperator(): FirStatement {
callCompleter.completeCall( callCompleter.completeCall(resolvedSetCall, ResolutionMode.ContextIndependent)
resolvedSetCall,
noExpectedType,
expectedTypeMismatchIsReportedInChecker = true
)
dataFlowAnalyzer.exitFunctionCall(resolvedSetCall, callCompleted = true) dataFlowAnalyzer.exitFunctionCall(resolvedSetCall, callCompleted = true)
return info.toBlock() return info.toBlock()
} }
@@ -1488,7 +1485,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
} }
val syntheticIdCall = components.syntheticCallGenerator.generateSyntheticCallForArrayOfCall(arrayOfCall, resolutionContext) val syntheticIdCall = components.syntheticCallGenerator.generateSyntheticCallForArrayOfCall(arrayOfCall, resolutionContext)
arrayOfCall.transformChildren(transformer, ResolutionMode.ContextDependent) arrayOfCall.transformChildren(transformer, ResolutionMode.ContextDependent)
callCompleter.completeCall(syntheticIdCall, data.expectedType ?: components.noExpectedType) callCompleter.completeCall(syntheticIdCall, data)
return arrayOfCall return arrayOfCall
} }