diff --git a/compiler/cli/cli-common/resources/META-INF/extensions/compiler.xml b/compiler/cli/cli-common/resources/META-INF/extensions/compiler.xml
index 3e468bfc9f6..f8f16819081 100644
--- a/compiler/cli/cli-common/resources/META-INF/extensions/compiler.xml
+++ b/compiler/cli/cli-common/resources/META-INF/extensions/compiler.xml
@@ -23,6 +23,9 @@
+
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/extensions/AssignResolutionAltererExtension.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/extensions/AssignResolutionAltererExtension.kt
new file mode 100644
index 00000000000..76fdca500f3
--- /dev/null
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/extensions/AssignResolutionAltererExtension.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2010-2022 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.resolve.extensions
+
+import org.jetbrains.kotlin.extensions.AnnotationBasedExtension
+import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
+import org.jetbrains.kotlin.extensions.internal.InternalNonStableExtensionPoints
+import org.jetbrains.kotlin.psi.KtBinaryExpression
+import org.jetbrains.kotlin.psi.KtExpression
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope
+import org.jetbrains.kotlin.types.KotlinType
+import org.jetbrains.kotlin.types.expressions.ExpressionTypingComponents
+import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
+import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo
+
+@InternalNonStableExtensionPoints
+interface AssignResolutionAltererExtension : AnnotationBasedExtension {
+ companion object : ProjectExtensionDescriptor(
+ "org.jetbrains.kotlin.assignResolutionAltererExtension",
+ AssignResolutionAltererExtension::class.java
+ )
+
+ fun needOverloadAssign(expression: KtBinaryExpression, leftType: KotlinType?, bindingContext: BindingContext): Boolean
+
+ fun resolveAssign(
+ bindingContext: BindingContext,
+ expression: KtBinaryExpression,
+ leftOperand: KtExpression,
+ left: KtExpression,
+ leftInfo: KotlinTypeInfo,
+ context: ExpressionTypingContext,
+ components: ExpressionTypingComponents,
+ scope: LexicalWritableScope
+ ): KotlinTypeInfo?
+}
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java
index 73279fffc9f..b3f81527910 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java
+++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl;
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
+import org.jetbrains.kotlin.resolve.extensions.AssignResolutionAltererExtension;
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope;
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
@@ -56,6 +57,8 @@ import org.jetbrains.kotlin.util.OperatorNameConventions;
import java.util.Collection;
import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
import static org.jetbrains.kotlin.diagnostics.Errors.*;
import static org.jetbrains.kotlin.psi.KtPsiUtil.deparenthesize;
@@ -441,6 +444,19 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
? refineTypeByPropertyInType(bindingContext, leftOperand, leftType)
: refineTypeFromPropertySetterIfPossible(bindingContext, leftOperand, leftType);
+ List assignAlterers = AssignResolutionAltererExtension.Companion.getInstances(expression.getProject());
+ if (!assignAlterers.isEmpty()) {
+ KotlinTypeInfo alteredTypeInfo = assignAlterers.stream()
+ .filter((it) -> it.needOverloadAssign(expression, leftType, bindingContext))
+ .map((it) -> it.resolveAssign(bindingContext, expression, leftOperand, left, leftInfo, context, components, scope))
+ .filter(Objects::nonNull)
+ .findFirst()
+ .orElse(null);
+ if (alteredTypeInfo != null) {
+ return alteredTypeInfo;
+ }
+ }
+
DataFlowInfo dataFlowInfo = leftInfo.getDataFlowInfo();
KotlinTypeInfo resultInfo;
if (right != null) {