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 12b040e5b0f..2469c4ec843 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 @@ -388,6 +388,20 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform val operatorCallReference = resolvedOperatorCall.calleeReference as? FirNamedReferenceWithCandidate val operatorIsResolvable = operatorCallReference?.isError == false + fun operatorReturnTypeMatches(candidate: Candidate): Boolean { + // After KT-45503, non-assign flavor of operator is checked more strictly: the return type must be assignable to the variable. + val operatorCallReturnType = resolvedOperatorCall.typeRef.coneType + val substitutor = candidate.system.currentStorage() + .buildAbstractResultingSubstitutor(candidate.system.typeSystemContext) as ConeSubstitutor + return AbstractTypeChecker.isSubtypeOf( + session.typeContext, + substitutor.substituteOrSelf(operatorCallReturnType), + leftArgument.typeRef.coneType + ) + } + // following `!!` is safe since `operatorIsResolvable = true` implies `operatorCallReference != null` + val operatorReturnTypeMatches = operatorIsResolvable && operatorReturnTypeMatches(operatorCallReference!!.candidate) + val lhsReference = leftArgument.toResolvedCallableReference() val lhsSymbol = lhsReference?.resolvedSymbol as? FirVariableSymbol<*> val lhsVariable = lhsSymbol?.fir @@ -444,6 +458,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform !assignIsResolvable && !operatorIsResolvable -> chooseAssign() !assignIsResolvable && operatorIsResolvable -> chooseOperator() assignIsResolvable && !operatorIsResolvable -> chooseAssign() + assignIsResolvable && operatorIsResolvable && !operatorReturnTypeMatches -> chooseAssign() else -> reportAmbiguity() } } diff --git a/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnVarAndCollections.fir.kt b/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnVarAndCollections.fir.kt deleted file mode 100644 index 3be6956ba69..00000000000 --- a/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnVarAndCollections.fir.kt +++ /dev/null @@ -1,31 +0,0 @@ -// WITH_RUNTIME - -fun test1() { - var list = ArrayList() - list -= 2 -} - -fun test2() { - var set = HashMap() - set += 2 to 2 -} - -fun test3() { - var set = HashSet() - set -= 2 -} - -fun test4() { - var list = mutableListOf(1) - list += 2 -} - -fun test5() { - var map = mutableMapOf(1 to 1) - map += 2 to 2 -} - -fun test6() { - var set = mutableSetOf(1) - set += 2 -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnVarAndCollections.kt b/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnVarAndCollections.kt index 5eff7fc7f4e..a4aef632975 100644 --- a/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnVarAndCollections.kt +++ b/compiler/testData/diagnostics/tests/operatorsOverloading/plusAssignOnVarAndCollections.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // WITH_RUNTIME fun test1() {