[FIR] KT-55747: Report error for `operator fun mod`
^KT-55747 Fixed
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt
index e04d8e8..4badab0 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt
@@ -387,6 +387,22 @@
token,
)
}
+ add(FirErrors.FORBIDDEN_BINARY_MOD) { firDiagnostic ->
+ ForbiddenBinaryModImpl(
+ firSymbolBuilder.buildSymbol(firDiagnostic.a),
+ firDiagnostic.b,
+ firDiagnostic as KtPsiDiagnostic,
+ token,
+ )
+ }
+ add(FirErrors.DEPRECATED_BINARY_MOD) { firDiagnostic ->
+ DeprecatedBinaryModImpl(
+ firSymbolBuilder.buildSymbol(firDiagnostic.a),
+ firDiagnostic.b,
+ firDiagnostic as KtPsiDiagnostic,
+ token,
+ )
+ }
add(FirErrors.SUPER_IS_NOT_AN_EXPRESSION) { firDiagnostic ->
SuperIsNotAnExpressionImpl(
firDiagnostic as KtPsiDiagnostic,
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt
index b446c2b..5226d8c 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt
@@ -307,6 +307,18 @@
abstract val altererNames: List<String?>
}
+ abstract class ForbiddenBinaryMod : KtFirDiagnostic<PsiElement>() {
+ override val diagnosticClass get() = ForbiddenBinaryMod::class
+ abstract val forbiddenFunction: KtSymbol
+ abstract val suggestedFunction: String
+ }
+
+ abstract class DeprecatedBinaryMod : KtFirDiagnostic<PsiElement>() {
+ override val diagnosticClass get() = DeprecatedBinaryMod::class
+ abstract val forbiddenFunction: KtSymbol
+ abstract val suggestedFunction: String
+ }
+
abstract class SuperIsNotAnExpression : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = SuperIsNotAnExpression::class
}
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt
index ef344e1..c42a25e 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt
@@ -355,6 +355,20 @@
override val token: KtLifetimeToken,
) : KtFirDiagnostic.AmbiguousAlteredAssign(), KtAbstractFirDiagnostic<PsiElement>
+internal class ForbiddenBinaryModImpl(
+ override val forbiddenFunction: KtSymbol,
+ override val suggestedFunction: String,
+ override val firDiagnostic: KtPsiDiagnostic,
+ override val token: KtLifetimeToken,
+) : KtFirDiagnostic.ForbiddenBinaryMod(), KtAbstractFirDiagnostic<PsiElement>
+
+internal class DeprecatedBinaryModImpl(
+ override val forbiddenFunction: KtSymbol,
+ override val suggestedFunction: String,
+ override val firDiagnostic: KtPsiDiagnostic,
+ override val token: KtLifetimeToken,
+) : KtFirDiagnostic.DeprecatedBinaryMod(), KtAbstractFirDiagnostic<PsiElement>
+
internal class SuperIsNotAnExpressionImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java
index c720247..d6e825b 100644
--- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java
+++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java
@@ -35362,6 +35362,12 @@
}
@Test
+ @TestMetadata("kt55747.kt")
+ public void testKt55747() throws Exception {
+ runTest("compiler/testData/diagnostics/testsWithStdLib/kt55747.kt");
+ }
+
+ @Test
@TestMetadata("kt8050.kt")
public void testKt8050() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/kt8050.kt");
diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java
index 4f2df20..a413d2f 100644
--- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java
+++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java
@@ -35458,6 +35458,12 @@
}
@Test
+ @TestMetadata("kt55747.kt")
+ public void testKt55747() throws Exception {
+ runTest("compiler/testData/diagnostics/testsWithStdLib/kt55747.kt");
+ }
+
+ @Test
@TestMetadata("kt8050.kt")
public void testKt8050() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/kt8050.kt");
diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java
index 19fce44..770170b 100644
--- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java
+++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java
@@ -35362,6 +35362,12 @@
}
@Test
+ @TestMetadata("kt55747.kt")
+ public void testKt55747() throws Exception {
+ runTest("compiler/testData/diagnostics/testsWithStdLib/kt55747.kt");
+ }
+
+ @Test
@TestMetadata("kt8050.kt")
public void testKt8050() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/kt8050.kt");
diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt
index a7d58b1..9692dfd 100644
--- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt
+++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt
@@ -152,6 +152,14 @@
val AMBIGUOUS_ALTERED_ASSIGN by error<PsiElement> {
parameter<List<String?>>("altererNames")
}
+ val FORBIDDEN_BINARY_MOD by error<PsiElement>(PositioningStrategy.OPERATOR_MODIFIER) {
+ parameter<FirBasedSymbol<*>>("forbiddenFunction")
+ parameter<String>("suggestedFunction")
+ }
+ val DEPRECATED_BINARY_MOD by error<PsiElement>(PositioningStrategy.OPERATOR_MODIFIER) {
+ parameter<FirBasedSymbol<*>>("forbiddenFunction")
+ parameter<String>("suggestedFunction")
+ }
}
val SUPER by object : DiagnosticGroup("Super") {
diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt
index 84c2821..73ac111 100644
--- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt
+++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt
@@ -164,6 +164,8 @@
val FUNCTION_EXPECTED by error2<PsiElement, String, ConeKotlinType>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
val RESOLUTION_TO_CLASSIFIER by error1<PsiElement, FirRegularClassSymbol>()
val AMBIGUOUS_ALTERED_ASSIGN by error1<PsiElement, List<String?>>()
+ val FORBIDDEN_BINARY_MOD by error2<PsiElement, FirBasedSymbol<*>, String>(SourceElementPositioningStrategies.OPERATOR_MODIFIER)
+ val DEPRECATED_BINARY_MOD by error2<PsiElement, FirBasedSymbol<*>, String>(SourceElementPositioningStrategies.OPERATOR_MODIFIER)
// Super
val SUPER_IS_NOT_AN_EXPRESSION by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOperatorModifierChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOperatorModifierChecker.kt
index 9bbbdff..637e1a6 100644
--- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOperatorModifierChecker.kt
+++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOperatorModifierChecker.kt
@@ -19,7 +19,6 @@
import org.jetbrains.kotlin.fir.analysis.checkers.isSupertypeOf
import org.jetbrains.kotlin.fir.analysis.checkers.overriddenFunctions
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
-import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.utils.isInline
@@ -32,6 +31,8 @@
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
+import org.jetbrains.kotlin.name.isSubpackageOf
+import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.util.OperatorNameConventions.ASSIGNMENT_OPERATIONS
import org.jetbrains.kotlin.util.OperatorNameConventions.BINARY_OPERATION_NAMES
import org.jetbrains.kotlin.util.OperatorNameConventions.COMPARE_TO
@@ -76,8 +77,23 @@
return
}
}
+
+ checkReplaceableLegacyOperators(declaration, context, reporter)
}
+ private fun checkReplaceableLegacyOperators(declaration: FirSimpleFunction, context: CheckerContext, reporter: DiagnosticReporter) {
+ val diagnostic = if (
+ declaration.symbol.callableId.packageName.isSubpackageOf(StandardClassIds.BASE_KOTLIN_PACKAGE) ||
+ !context.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitOperatorMod)
+ ) {
+ FirErrors.DEPRECATED_BINARY_MOD
+ } else {
+ FirErrors.FORBIDDEN_BINARY_MOD
+ }
+
+ val replacement = OperatorNameConventions.MOD_OPERATORS_REPLACEMENT[declaration.name] ?: return
+ reporter.reportOn(declaration.source, diagnostic, declaration.symbol, replacement.asString(), context)
+ }
}
private interface Check : (CheckerContext, FirSimpleFunction) -> String? {
diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt
index ede68b4..f44b09e 100644
--- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt
+++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt
@@ -214,6 +214,8 @@
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FINAL_SUPERTYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FINAL_UPPER_BOUND
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FLOAT_LITERAL_OUT_OF_RANGE
+import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATED_BINARY_MOD
+import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FORBIDDEN_BINARY_MOD
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FORBIDDEN_VARARG_PARAMETER_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUNCTION_CALL_EXPECTED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUNCTION_DECLARATION_WITH_NO_NAME
@@ -712,6 +714,8 @@
"Multiple extensions tried to alter this assignement at the same time. Extensions: {0}",
COLLECTION(NULLABLE_STRING)
)
+ map.put(DEPRECATED_BINARY_MOD, "Convention for ''{0}'' is forbidden. Use ''{1}''", SYMBOL, STRING)
+ map.put(FORBIDDEN_BINARY_MOD, "Deprecated convention for ''{0}''. Use ''{1}''", SYMBOL, STRING)
map.put(ILLEGAL_SELECTOR, "The expression cannot be a selector (occur after a dot)")
map.put(NO_RECEIVER_ALLOWED, "No receiver can be passed to this function or property")
diff --git a/compiler/testData/diagnostics/tests/operatorRem/DeprecatedModAssignOperatorConventions.fir.kt b/compiler/testData/diagnostics/tests/operatorRem/DeprecatedModAssignOperatorConventions.fir.kt
index 68a4881..d4c57fb3 100644
--- a/compiler/testData/diagnostics/tests/operatorRem/DeprecatedModAssignOperatorConventions.fir.kt
+++ b/compiler/testData/diagnostics/tests/operatorRem/DeprecatedModAssignOperatorConventions.fir.kt
@@ -2,12 +2,12 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class OldAndNew {
- operator fun modAssign(x: Int) {}
+ <!DEPRECATED_BINARY_MOD!>operator<!> fun modAssign(x: Int) {}
operator fun remAssign(x: Int) {}
}
class OnlyOld {
- operator fun modAssign(x: Int) {}
+ <!DEPRECATED_BINARY_MOD!>operator<!> fun modAssign(x: Int) {}
}
class OnlyNew {
@@ -16,11 +16,11 @@
class Sample
-operator fun Sample.modAssign(x: Int) {}
+<!DEPRECATED_BINARY_MOD!>operator<!> fun Sample.modAssign(x: Int) {}
operator fun Sample.remAssign(x: Int) {}
class ModAndRemAssign {
- operator fun mod(x: Int): ModAndRemAssign = ModAndRemAssign()
+ <!DEPRECATED_BINARY_MOD!>operator<!> fun mod(x: Int): ModAndRemAssign = ModAndRemAssign()
operator fun remAssign(x: Int) {}
}
diff --git a/compiler/testData/diagnostics/tests/operatorRem/DeprecatedModOperatorConventions.fir.kt b/compiler/testData/diagnostics/tests/operatorRem/DeprecatedModOperatorConventions.fir.kt
index ebe52c3..50d476f 100644
--- a/compiler/testData/diagnostics/tests/operatorRem/DeprecatedModOperatorConventions.fir.kt
+++ b/compiler/testData/diagnostics/tests/operatorRem/DeprecatedModOperatorConventions.fir.kt
@@ -2,12 +2,12 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class OldAndNew {
- operator fun mod(x: Int) {}
+ <!DEPRECATED_BINARY_MOD!>operator<!> fun mod(x: Int) {}
operator fun rem(x: Int) {}
}
class OnlyOld {
- operator fun mod(x: Int) {}
+ <!DEPRECATED_BINARY_MOD!>operator<!> fun mod(x: Int) {}
}
class OnlyNew {
@@ -16,11 +16,11 @@
class Sample
-operator fun Sample.mod(x: Int) {}
+<!DEPRECATED_BINARY_MOD!>operator<!> fun Sample.mod(x: Int) {}
operator fun Sample.rem(x: Int) {}
class IntAndUnit {
- operator fun mod(x: Int) = 0
+ <!DEPRECATED_BINARY_MOD!>operator<!> fun mod(x: Int) = 0
operator fun rem(x: Int): Int = 0
}
diff --git a/compiler/testData/diagnostics/tests/operatorRem/deprecatedModConvention.fir.kt b/compiler/testData/diagnostics/tests/operatorRem/deprecatedModConvention.fir.kt
index 7873fff..61d4eb6 100644
--- a/compiler/testData/diagnostics/tests/operatorRem/deprecatedModConvention.fir.kt
+++ b/compiler/testData/diagnostics/tests/operatorRem/deprecatedModConvention.fir.kt
@@ -2,23 +2,23 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
object ModAndRem {
- operator fun mod(x: Int) {}
+ <!DEPRECATED_BINARY_MOD!>operator<!> fun mod(x: Int) {}
operator fun rem(x: Int) {}
}
object OldMod {
- operator fun mod(x: Int) {}
+ <!DEPRECATED_BINARY_MOD!>operator<!> fun mod(x: Int) {}
}
object ModAndRemExtension
-operator fun ModAndRemExtension.mod(x: Int) {}
+<!DEPRECATED_BINARY_MOD!>operator<!> fun ModAndRemExtension.mod(x: Int) {}
operator fun ModAndRemExtension.rem(x: Int) {}
object ModExtension
-operator fun ModExtension.mod(x: Int) {}
+<!DEPRECATED_BINARY_MOD!>operator<!> fun ModExtension.mod(x: Int) {}
object ModMemberAndRemExtension {
- operator fun mod(x: Int) {}
+ <!DEPRECATED_BINARY_MOD!>operator<!> fun mod(x: Int) {}
}
operator fun ModMemberAndRemExtension.rem(x: Int) {}
diff --git a/compiler/testData/diagnostics/tests/operatorRem/doNotResolveToInapplicableRem.fir.kt b/compiler/testData/diagnostics/tests/operatorRem/doNotResolveToInapplicableRem.fir.kt
index e6965a5..331b844 100644
--- a/compiler/testData/diagnostics/tests/operatorRem/doNotResolveToInapplicableRem.fir.kt
+++ b/compiler/testData/diagnostics/tests/operatorRem/doNotResolveToInapplicableRem.fir.kt
@@ -2,7 +2,7 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
object OldMod {
- operator fun mod(x: Int) {}
+ <!DEPRECATED_BINARY_MOD!>operator<!> fun mod(x: Int) {}
}
object RemExtension
diff --git a/compiler/testData/diagnostics/tests/operatorRem/forbiddenModOperatorConvention.fir.kt b/compiler/testData/diagnostics/tests/operatorRem/forbiddenModOperatorConvention.fir.kt
index 842be5c..f145162 100644
--- a/compiler/testData/diagnostics/tests/operatorRem/forbiddenModOperatorConvention.fir.kt
+++ b/compiler/testData/diagnostics/tests/operatorRem/forbiddenModOperatorConvention.fir.kt
@@ -2,16 +2,16 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
object ModAndRem {
- operator fun mod(x: Int) {}
+ <!FORBIDDEN_BINARY_MOD!>operator<!> fun mod(x: Int) {}
operator fun rem(x: Int) {}
- operator fun modAssign(x: Int) {}
+ <!FORBIDDEN_BINARY_MOD!>operator<!> fun modAssign(x: Int) {}
operator fun remAssign(x: Int) {}
}
object JustMod {
- operator fun mod(x: Int) {}
- operator fun modAssign(x: Int) {}
+ <!FORBIDDEN_BINARY_MOD!>operator<!> fun mod(x: Int) {}
+ <!FORBIDDEN_BINARY_MOD!>operator<!> fun modAssign(x: Int) {}
}
fun foo() {
diff --git a/compiler/testData/diagnostics/tests/operatorRem/modWithRemAssign.fir.kt b/compiler/testData/diagnostics/tests/operatorRem/modWithRemAssign.fir.kt
deleted file mode 100644
index 1f88d50..0000000
--- a/compiler/testData/diagnostics/tests/operatorRem/modWithRemAssign.fir.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-// !LANGUAGE: -ProhibitOperatorMod
-// !DIAGNOSTICS: -UNUSED_PARAMETER, -EXTENSION_SHADOWED_BY_MEMBER
-
-class ModAndRemAssign {
- operator fun mod(x: Int) = ModAndRemAssign()
- operator fun mod(x: String) = ModAndRemAssign()
- operator fun modAssign(x: String) {}
- operator fun remAssign(x: Int) {}
-}
-
-operator fun ModAndRemAssign.mod(x: String) = ModAndRemAssign()
-operator fun ModAndRemAssign.modAssign(x: String) {}
-
-fun test() {
- val modAndRemAssign = ModAndRemAssign()
- modAndRemAssign %= 1
-}
\ No newline at end of file
diff --git a/compiler/testData/diagnostics/tests/operatorRem/modWithRemAssign.kt b/compiler/testData/diagnostics/tests/operatorRem/modWithRemAssign.kt
index 2f6fdef..efe449c 100644
--- a/compiler/testData/diagnostics/tests/operatorRem/modWithRemAssign.kt
+++ b/compiler/testData/diagnostics/tests/operatorRem/modWithRemAssign.kt
@@ -1,3 +1,4 @@
+// FIR_IDENTICAL
// !LANGUAGE: -ProhibitOperatorMod
// !DIAGNOSTICS: -UNUSED_PARAMETER, -EXTENSION_SHADOWED_BY_MEMBER
diff --git a/compiler/testData/diagnostics/tests/operatorRem/preferRemAsExtentionOverMod.fir.kt b/compiler/testData/diagnostics/tests/operatorRem/preferRemAsExtentionOverMod.fir.kt
deleted file mode 100644
index 3695372..0000000
--- a/compiler/testData/diagnostics/tests/operatorRem/preferRemAsExtentionOverMod.fir.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-// !LANGUAGE: -ProhibitOperatorMod
-// !DIAGNOSTICS: -UNUSED_PARAMETER
-
-class Foo {
-}
-operator fun Foo.mod(x: Int): Foo = Foo()
-operator fun Foo.rem(x: Int): Int = 0
-
-fun foo() {
- takeInt(Foo() % 1)
-}
-
-fun takeInt(x: Int) {}
\ No newline at end of file
diff --git a/compiler/testData/diagnostics/tests/operatorRem/preferRemAsExtentionOverMod.kt b/compiler/testData/diagnostics/tests/operatorRem/preferRemAsExtentionOverMod.kt
index 56c6a55..58acaad 100644
--- a/compiler/testData/diagnostics/tests/operatorRem/preferRemAsExtentionOverMod.kt
+++ b/compiler/testData/diagnostics/tests/operatorRem/preferRemAsExtentionOverMod.kt
@@ -1,3 +1,4 @@
+// FIR_IDENTICAL
// !LANGUAGE: -ProhibitOperatorMod
// !DIAGNOSTICS: -UNUSED_PARAMETER
diff --git a/compiler/testData/diagnostics/tests/operatorRem/preferRemAsMemberOverMod.fir.kt b/compiler/testData/diagnostics/tests/operatorRem/preferRemAsMemberOverMod.fir.kt
deleted file mode 100644
index eec75b3..0000000
--- a/compiler/testData/diagnostics/tests/operatorRem/preferRemAsMemberOverMod.fir.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-// !LANGUAGE: -ProhibitOperatorMod
-// !DIAGNOSTICS: -UNUSED_PARAMETER
-
-class Foo {
- operator fun mod(x: Int): Foo = Foo()
- operator fun rem(x: Int): Int = 0
-}
-
-fun foo() {
- takeInt(Foo() % 1)
-}
-
-fun takeInt(x: Int) {}
\ No newline at end of file
diff --git a/compiler/testData/diagnostics/tests/operatorRem/preferRemAsMemberOverMod.kt b/compiler/testData/diagnostics/tests/operatorRem/preferRemAsMemberOverMod.kt
index 1adf05b..5cf456a 100644
--- a/compiler/testData/diagnostics/tests/operatorRem/preferRemAsMemberOverMod.kt
+++ b/compiler/testData/diagnostics/tests/operatorRem/preferRemAsMemberOverMod.kt
@@ -1,3 +1,4 @@
+// FIR_IDENTICAL
// !LANGUAGE: -ProhibitOperatorMod
// !DIAGNOSTICS: -UNUSED_PARAMETER
diff --git a/compiler/testData/diagnostics/tests/operatorRem/preferRemFromCompanionObjectOverRem.fir.kt b/compiler/testData/diagnostics/tests/operatorRem/preferRemFromCompanionObjectOverRem.fir.kt
deleted file mode 100644
index acf62c6..0000000
--- a/compiler/testData/diagnostics/tests/operatorRem/preferRemFromCompanionObjectOverRem.fir.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-// !LANGUAGE: -ProhibitOperatorMod
-// !DIAGNOSTICS: -UNUSED_PARAMETER
-
-class A {
- companion object {
- operator fun A.rem(x: Int) = 0
- }
-
- fun test() {
- operator fun A.mod(x: Int) = ""
-
- takeInt(A() % 123)
- }
-}
-
-fun takeInt(x: Int) {}
\ No newline at end of file
diff --git a/compiler/testData/diagnostics/tests/operatorRem/preferRemFromCompanionObjectOverRem.kt b/compiler/testData/diagnostics/tests/operatorRem/preferRemFromCompanionObjectOverRem.kt
index 17a7880..0a5fa68 100644
--- a/compiler/testData/diagnostics/tests/operatorRem/preferRemFromCompanionObjectOverRem.kt
+++ b/compiler/testData/diagnostics/tests/operatorRem/preferRemFromCompanionObjectOverRem.kt
@@ -1,3 +1,4 @@
+// FIR_IDENTICAL
// !LANGUAGE: -ProhibitOperatorMod
// !DIAGNOSTICS: -UNUSED_PARAMETER
diff --git a/compiler/testData/diagnostics/tests/operatorRem/preferRemOverModInLocalFunctions.fir.kt b/compiler/testData/diagnostics/tests/operatorRem/preferRemOverModInLocalFunctions.fir.kt
deleted file mode 100644
index d705914..0000000
--- a/compiler/testData/diagnostics/tests/operatorRem/preferRemOverModInLocalFunctions.fir.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-// !LANGUAGE: -ProhibitOperatorMod
-// !DIAGNOSTICS: -UNUSED_PARAMETER
-
-object B
-
-class A {
- operator fun B.rem(x: Int) = 0
-}
-
-fun test1() {
- operator fun B.mod(x: Int) = ""
-
- with(A()) {
- takeInt(B % 10)
- }
-}
-
-class C {
- operator fun B.mod(x: Int) = ""
-}
-
-fun test2() {
- operator fun B.rem(x: Int) = 0
-
- with(C()) {
- takeInt(B % 10)
- }
-}
-
-fun takeInt(x: Int) {}
\ No newline at end of file
diff --git a/compiler/testData/diagnostics/tests/operatorRem/preferRemOverModInLocalFunctions.kt b/compiler/testData/diagnostics/tests/operatorRem/preferRemOverModInLocalFunctions.kt
index 0e7f7d3..89a6d92 100644
--- a/compiler/testData/diagnostics/tests/operatorRem/preferRemOverModInLocalFunctions.kt
+++ b/compiler/testData/diagnostics/tests/operatorRem/preferRemOverModInLocalFunctions.kt
@@ -1,3 +1,4 @@
+// FIR_IDENTICAL
// !LANGUAGE: -ProhibitOperatorMod
// !DIAGNOSTICS: -UNUSED_PARAMETER
diff --git a/compiler/testData/diagnostics/tests/operatorRem/preferRemWithImplicitReceivers.fir.kt b/compiler/testData/diagnostics/tests/operatorRem/preferRemWithImplicitReceivers.fir.kt
deleted file mode 100644
index e1a2d48..0000000
--- a/compiler/testData/diagnostics/tests/operatorRem/preferRemWithImplicitReceivers.fir.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-// !LANGUAGE: -ProhibitOperatorMod
-// !DIAGNOSTICS: -UNUSED_PARAMETER
-
-class A {
- operator fun Int.mod(s: String) = 4
-}
-
-class B {
- operator fun Int.rem(s: String) = ""
-}
-
-fun test() {
- with(B()) {
- with(A()) {
- takeString(1 % "")
- }
- }
-}
-
-fun takeString(s: String) {}
diff --git a/compiler/testData/diagnostics/tests/operatorRem/preferRemWithImplicitReceivers.kt b/compiler/testData/diagnostics/tests/operatorRem/preferRemWithImplicitReceivers.kt
index 67caa7f..d6783ee 100644
--- a/compiler/testData/diagnostics/tests/operatorRem/preferRemWithImplicitReceivers.kt
+++ b/compiler/testData/diagnostics/tests/operatorRem/preferRemWithImplicitReceivers.kt
@@ -1,3 +1,4 @@
+// FIR_IDENTICAL
// !LANGUAGE: -ProhibitOperatorMod
// !DIAGNOSTICS: -UNUSED_PARAMETER
diff --git a/compiler/testData/diagnostics/tests/operatorRem/prefereRemAsExtensionOverMemberMod.fir.kt b/compiler/testData/diagnostics/tests/operatorRem/prefereRemAsExtensionOverMemberMod.fir.kt
deleted file mode 100644
index 0b7bcae..0000000
--- a/compiler/testData/diagnostics/tests/operatorRem/prefereRemAsExtensionOverMemberMod.fir.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-// !LANGUAGE: -ProhibitOperatorMod
-// !DIAGNOSTICS: -UNUSED_PARAMETER
-
-class Foo {
- operator fun mod(x: Int): Foo = Foo()
-}
-
-operator fun Foo.rem(x: Int): Int = 0
-
-
-fun foo() {
- takeInt(Foo() % 1)
-}
-
-fun takeInt(x: Int) {}
\ No newline at end of file
diff --git a/compiler/testData/diagnostics/tests/operatorRem/prefereRemAsExtensionOverMemberMod.kt b/compiler/testData/diagnostics/tests/operatorRem/prefereRemAsExtensionOverMemberMod.kt
index 78fa07f..3d8e86a 100644
--- a/compiler/testData/diagnostics/tests/operatorRem/prefereRemAsExtensionOverMemberMod.kt
+++ b/compiler/testData/diagnostics/tests/operatorRem/prefereRemAsExtensionOverMemberMod.kt
@@ -1,3 +1,4 @@
+// FIR_IDENTICAL
// !LANGUAGE: -ProhibitOperatorMod
// !DIAGNOSTICS: -UNUSED_PARAMETER
diff --git a/compiler/testData/diagnostics/tests/operatorRem/remWithModAndModAssign.fir.kt b/compiler/testData/diagnostics/tests/operatorRem/remWithModAndModAssign.fir.kt
deleted file mode 100644
index 530b505..0000000
--- a/compiler/testData/diagnostics/tests/operatorRem/remWithModAndModAssign.fir.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-// !LANGUAGE: -ProhibitOperatorMod
-// !DIAGNOSTICS: -UNUSED_PARAMETER, -EXTENSION_SHADOWED_BY_MEMBER
-
-class ModAndRemAssign {
- operator fun mod(x: Int) = ModAndRemAssign()
- operator fun mod(x: String) = ModAndRemAssign()
- operator fun modAssign(x: String) {}
- operator fun rem(x: Int) = ModAndRemAssign()
-}
-
-operator fun ModAndRemAssign.mod(x: String) = ModAndRemAssign()
-operator fun ModAndRemAssign.modAssign(x: String) {}
-
-fun test() {
- var modAndRemAssign = ModAndRemAssign()
- modAndRemAssign %= 1
-}
\ No newline at end of file
diff --git a/compiler/testData/diagnostics/tests/operatorRem/remWithModAndModAssign.kt b/compiler/testData/diagnostics/tests/operatorRem/remWithModAndModAssign.kt
index 38b40ff..848d425 100644
--- a/compiler/testData/diagnostics/tests/operatorRem/remWithModAndModAssign.kt
+++ b/compiler/testData/diagnostics/tests/operatorRem/remWithModAndModAssign.kt
@@ -1,3 +1,4 @@
+// FIR_IDENTICAL
// !LANGUAGE: -ProhibitOperatorMod
// !DIAGNOSTICS: -UNUSED_PARAMETER, -EXTENSION_SHADOWED_BY_MEMBER
diff --git a/compiler/testData/diagnostics/tests/operatorRem/remWithModAssign.fir.kt b/compiler/testData/diagnostics/tests/operatorRem/remWithModAssign.fir.kt
deleted file mode 100644
index 2ceabb2..0000000
--- a/compiler/testData/diagnostics/tests/operatorRem/remWithModAssign.fir.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-// !LANGUAGE: -ProhibitOperatorMod
-// !DIAGNOSTICS: -UNUSED_PARAMETER
-
-object RemAndModAssign {
- operator fun modAssign(x: String) {}
- operator fun rem(x: Int) = RemAndModAssign
-}
-
-fun test2() {
- var c = RemAndModAssign
- c %= 123
-}
\ No newline at end of file
diff --git a/compiler/testData/diagnostics/tests/operatorRem/remWithModAssign.kt b/compiler/testData/diagnostics/tests/operatorRem/remWithModAssign.kt
index 3ff810b..d9532df 100644
--- a/compiler/testData/diagnostics/tests/operatorRem/remWithModAssign.kt
+++ b/compiler/testData/diagnostics/tests/operatorRem/remWithModAssign.kt
@@ -1,3 +1,4 @@
+// FIR_IDENTICAL
// !LANGUAGE: -ProhibitOperatorMod
// !DIAGNOSTICS: -UNUSED_PARAMETER
diff --git a/compiler/testData/diagnostics/tests/operatorRem/resolveModIfRemIsHidden.fir.kt b/compiler/testData/diagnostics/tests/operatorRem/resolveModIfRemIsHidden.fir.kt
index 008c29c..29f164f 100644
--- a/compiler/testData/diagnostics/tests/operatorRem/resolveModIfRemIsHidden.fir.kt
+++ b/compiler/testData/diagnostics/tests/operatorRem/resolveModIfRemIsHidden.fir.kt
@@ -6,7 +6,7 @@
@Deprecated("Use mod instead", ReplaceWith("mod"), DeprecationLevel.HIDDEN)
operator fun rem(x: Int) = 0
- operator fun mod(x: Int) = ""
+ <!DEPRECATED_BINARY_MOD!>operator<!> fun mod(x: Int) = ""
}
fun test() {
diff --git a/compiler/testData/diagnostics/testsWithStdLib/kt55747.kt b/compiler/testData/diagnostics/testsWithStdLib/kt55747.kt
new file mode 100644
index 0000000..0b9c5b8
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/kt55747.kt
@@ -0,0 +1,6 @@
+// FIR_IDENTICAL
+
+object Rem {
+ <!FORBIDDEN_BINARY_MOD!>operator<!> fun mod(x: Int) {}
+ <!FORBIDDEN_BINARY_MOD!>operator<!> fun modAssign(x: Int) {}
+}
diff --git a/compiler/testData/diagnostics/testsWithStdLib/kt55747.txt b/compiler/testData/diagnostics/testsWithStdLib/kt55747.txt
new file mode 100644
index 0000000..b50472c
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/kt55747.txt
@@ -0,0 +1,10 @@
+package
+
+public object Rem {
+ private constructor Rem()
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public final operator fun mod(/*0*/ x: kotlin.Int): kotlin.Unit
+ public final operator fun modAssign(/*0*/ x: kotlin.Int): kotlin.Unit
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java
index a67047f..17cdd7e 100644
--- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java
+++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java
@@ -35458,6 +35458,12 @@
}
@Test
+ @TestMetadata("kt55747.kt")
+ public void testKt55747() throws Exception {
+ runTest("compiler/testData/diagnostics/testsWithStdLib/kt55747.kt");
+ }
+
+ @Test
@TestMetadata("kt8050.kt")
public void testKt8050() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/kt8050.kt");
diff --git a/core/compiler.common/src/org/jetbrains/kotlin/util/OperatorNameConventions.kt b/core/compiler.common/src/org/jetbrains/kotlin/util/OperatorNameConventions.kt
index 73a41f8..5e14b0e 100644
--- a/core/compiler.common/src/org/jetbrains/kotlin/util/OperatorNameConventions.kt
+++ b/core/compiler.common/src/org/jetbrains/kotlin/util/OperatorNameConventions.kt
@@ -92,4 +92,7 @@
@JvmField
val DELEGATED_PROPERTY_OPERATORS = setOf(GET_VALUE, SET_VALUE, PROVIDE_DELEGATE)
+
+ @JvmField
+ val MOD_OPERATORS_REPLACEMENT = mapOf(MOD to REM, MOD_ASSIGN to REM_ASSIGN)
}