From c43faa2adace460acd9822b06f8a4a2d0ef355df Mon Sep 17 00:00:00 2001 From: Tianyu Geng Date: Thu, 8 Apr 2021 17:57:39 -0700 Subject: [PATCH] FIR: refactor FirExpressionsResolveTransformer#transformAssignmentOperatorStatement No logic change. This commit only rearrange stuff to make it cleaner --- .../FirExpressionsResolveTransformer.kt | 99 +++++++++++-------- 1 file changed, 56 insertions(+), 43 deletions(-) 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 a6172dd807a..12b040e5b0f 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 @@ -25,15 +25,18 @@ import org.jetbrains.kotlin.fir.resolve.calls.* import org.jetbrains.kotlin.fir.resolve.diagnostics.* import org.jetbrains.kotlin.fir.resolve.inference.FirStubInferenceSession import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents +import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.transformers.InvocationKindTransformer import org.jetbrains.kotlin.fir.resolve.transformers.StoreReceiver import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike -import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol import org.jetbrains.kotlin.fir.types.* -import org.jetbrains.kotlin.fir.types.builder.* +import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef +import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.visitors.* import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.name.StandardClassIds +import org.jetbrains.kotlin.resolve.calls.inference.buildAbstractResultingSubstitutor import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.types.ConstantValueKind @@ -374,7 +377,8 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform assignOperatorCall.transformSingle(this, ResolutionMode.ContextDependent) } val assignCallReference = resolvedAssignCall.calleeReference as? FirNamedReferenceWithCandidate - val assignIsError = assignCallReference?.isError ?: true + val assignIsResolvable = assignCallReference?.isError == false + // x = x + y val simpleOperatorName = FirOperationNameConventions.ASSIGNMENTS_TO_SIMPLE_OPERATOR.getValue(assignmentOperatorStatement.operation) val simpleOperatorCall = createFunctionCall(simpleOperatorName) @@ -382,57 +386,66 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform simpleOperatorCall.transformSingle(this, ResolutionMode.ContextDependent) } val operatorCallReference = resolvedOperatorCall.calleeReference as? FirNamedReferenceWithCandidate - val operatorIsError = operatorCallReference?.isError ?: true + val operatorIsResolvable = operatorCallReference?.isError == false val lhsReference = leftArgument.toResolvedCallableReference() val lhsSymbol = lhsReference?.resolvedSymbol as? FirVariableSymbol<*> val lhsVariable = lhsSymbol?.fir val lhsIsVar = lhsVariable?.isVar == true - return when { - operatorIsError || (!lhsIsVar && !assignIsError) -> { - callCompleter.completeCall(resolvedAssignCall, noExpectedType) - dataFlowAnalyzer.exitFunctionCall(resolvedAssignCall, callCompleted = true) - resolvedAssignCall - } - assignIsError -> { - callCompleter.completeCall(resolvedOperatorCall, lhsVariable?.returnTypeRef ?: noExpectedType) - dataFlowAnalyzer.exitFunctionCall(resolvedOperatorCall, callCompleted = true) - val assignment = - buildVariableAssignment { - source = assignmentOperatorStatement.source - rValue = resolvedOperatorCall - calleeReference = when { - lhsIsVar -> lhsReference!! - else -> buildErrorNamedReference { - source = when (leftArgument) { - is FirFunctionCall -> leftArgument.source - is FirQualifiedAccess -> - leftArgument.calleeReference.source - else -> leftArgument.source - } - diagnostic = if (lhsSymbol == null) ConeVariableExpectedError() else ConeValReassignmentError(lhsSymbol) + + fun chooseAssign(): FirStatement { + callCompleter.completeCall(resolvedAssignCall, noExpectedType) + dataFlowAnalyzer.exitFunctionCall(resolvedAssignCall, callCompleted = true) + return resolvedAssignCall + } + + fun chooseOperator(): FirStatement { + callCompleter.completeCall(resolvedOperatorCall, lhsVariable?.returnTypeRef ?: noExpectedType) + dataFlowAnalyzer.exitFunctionCall(resolvedOperatorCall, callCompleted = true) + val assignment = + buildVariableAssignment { + source = assignmentOperatorStatement.source + rValue = resolvedOperatorCall + calleeReference = when { + lhsIsVar -> lhsReference!! + else -> buildErrorNamedReference { + source = when (leftArgument) { + is FirFunctionCall -> leftArgument.source + is FirQualifiedAccess -> + leftArgument.calleeReference.source + else -> leftArgument.source } - } - (leftArgument as? FirQualifiedAccess)?.let { - dispatchReceiver = it.dispatchReceiver - extensionReceiver = it.extensionReceiver + diagnostic = if (lhsSymbol == null) ConeVariableExpectedError() else ConeValReassignmentError(lhsSymbol) } } - assignment.transform(transformer, ResolutionMode.ContextIndependent) - } - else -> { - val operatorCallSymbol = operatorCallReference?.candidateSymbol - val assignmentCallSymbol = assignCallReference?.candidateSymbol - - requireNotNull(operatorCallSymbol) - requireNotNull(assignmentCallSymbol) - - buildErrorExpression { - source = assignmentOperatorStatement.source - diagnostic = ConeOperatorAmbiguityError(listOf(operatorCallSymbol, assignmentCallSymbol)) + (leftArgument as? FirQualifiedAccess)?.let { + dispatchReceiver = it.dispatchReceiver + extensionReceiver = it.extensionReceiver + } } + return assignment.transform(transformer, ResolutionMode.ContextIndependent) + } + + fun reportAmbiguity(): FirStatement { + val operatorCallSymbol = operatorCallReference?.candidateSymbol + val assignmentCallSymbol = assignCallReference?.candidateSymbol + + requireNotNull(operatorCallSymbol) + requireNotNull(assignmentCallSymbol) + + return buildErrorExpression { + source = assignmentOperatorStatement.source + diagnostic = ConeOperatorAmbiguityError(listOf(operatorCallSymbol, assignmentCallSymbol)) } } + + return when { + assignIsResolvable && !lhsIsVar -> chooseAssign() + !assignIsResolvable && !operatorIsResolvable -> chooseAssign() + !assignIsResolvable && operatorIsResolvable -> chooseOperator() + assignIsResolvable && !operatorIsResolvable -> chooseAssign() + else -> reportAmbiguity() + } } override fun transformEqualityOperatorCall(