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 e04d8e85fd1..4badab06764 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 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert 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 b446c2b720a..5226d8cfe9c 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 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract val altererNames: List } + abstract class ForbiddenBinaryMod : KtFirDiagnostic() { + override val diagnosticClass get() = ForbiddenBinaryMod::class + abstract val forbiddenFunction: KtSymbol + abstract val suggestedFunction: String + } + + abstract class DeprecatedBinaryMod : KtFirDiagnostic() { + override val diagnosticClass get() = DeprecatedBinaryMod::class + abstract val forbiddenFunction: KtSymbol + abstract val suggestedFunction: String + } + abstract class SuperIsNotAnExpression : KtFirDiagnostic() { 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 ef344e1749b..c42a25e2035 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 @@ internal class AmbiguousAlteredAssignImpl( override val token: KtLifetimeToken, ) : KtFirDiagnostic.AmbiguousAlteredAssign(), KtAbstractFirDiagnostic +internal class ForbiddenBinaryModImpl( + override val forbiddenFunction: KtSymbol, + override val suggestedFunction: String, + override val firDiagnostic: KtPsiDiagnostic, + override val token: KtLifetimeToken, +) : KtFirDiagnostic.ForbiddenBinaryMod(), KtAbstractFirDiagnostic + +internal class DeprecatedBinaryModImpl( + override val forbiddenFunction: KtSymbol, + override val suggestedFunction: String, + override val firDiagnostic: KtPsiDiagnostic, + override val token: KtLifetimeToken, +) : KtFirDiagnostic.DeprecatedBinaryMod(), KtAbstractFirDiagnostic + 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 b09d8b2a7a1..5dd323410b7 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 @@ -35403,6 +35403,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/testsWithStdLib/kt54410.kt"); } + @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 { 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 66af377109b..86dd508d719 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 @@ -35499,6 +35499,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/testsWithStdLib/kt54410.kt"); } + @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 { 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 e7336fea5fd..7fb07f7e303 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 @@ -35403,6 +35403,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/testsWithStdLib/kt54410.kt"); } + @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 { 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 a7d58b1fb25..9692dfd9116 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 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val AMBIGUOUS_ALTERED_ASSIGN by error { parameter>("altererNames") } + val FORBIDDEN_BINARY_MOD by error(PositioningStrategy.OPERATOR_MODIFIER) { + parameter>("forbiddenFunction") + parameter("suggestedFunction") + } + val DEPRECATED_BINARY_MOD by error(PositioningStrategy.OPERATOR_MODIFIER) { + parameter>("forbiddenFunction") + parameter("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 84c282195e3..73ac111274a 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 @@ object FirErrors { val FUNCTION_EXPECTED by error2(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED) val RESOLUTION_TO_CLASSIFIER by error1() val AMBIGUOUS_ALTERED_ASSIGN by error1>() + val FORBIDDEN_BINARY_MOD by error2, String>(SourceElementPositioningStrategies.OPERATOR_MODIFIER) + val DEPRECATED_BINARY_MOD by error2, String>(SourceElementPositioningStrategies.OPERATOR_MODIFIER) // Super val SUPER_IS_NOT_AN_EXPRESSION by error0(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 9bbbdff8a7a..574c091fc2c 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.hasModifier 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.fir.types.impl.ConeClassLikeTypeImpl 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,24 @@ object FirOperatorModifierChecker : FirSimpleFunctionChecker() { return } } + + checkReplaceableLegacyOperators(declaration, context, reporter) } + private fun checkReplaceableLegacyOperators(declaration: FirSimpleFunction, context: CheckerContext, reporter: DiagnosticReporter) { + val replacement = OperatorNameConventions.MOD_OPERATORS_REPLACEMENT[declaration.name] ?: return + + 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 + } + + 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 ede68b4c78e..f44b09e6be9 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.EXTENSION_PROPERT 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 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { "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/codegen/box/operatorConventions/remAssignmentOperation.kt b/compiler/testData/codegen/box/operatorConventions/remAssignmentOperation.kt index 79896e8ba01..0e34c3cc8d9 100644 --- a/compiler/testData/codegen/box/operatorConventions/remAssignmentOperation.kt +++ b/compiler/testData/codegen/box/operatorConventions/remAssignmentOperation.kt @@ -4,6 +4,7 @@ class A() { var x = 5 } +@Suppress("DEPRECATED_BINARY_MOD") operator fun A.modAssign(y: Int) { throw RuntimeException("mod has been called instead of rem") } operator fun A.remAssign(y: Int) { x %= y + 1 } diff --git a/compiler/testData/codegen/box/operatorConventions/remOverModOperation.kt b/compiler/testData/codegen/box/operatorConventions/remOverModOperation.kt index e5371fcc603..4ef742e1e06 100644 --- a/compiler/testData/codegen/box/operatorConventions/remOverModOperation.kt +++ b/compiler/testData/codegen/box/operatorConventions/remOverModOperation.kt @@ -3,6 +3,7 @@ class A() { var x = 5 + @Suppress("DEPRECATED_BINARY_MOD") operator fun mod(y: Int) { throw RuntimeException("mod has been called instead of rem") } operator fun rem(y: Int) { x -= y } } diff --git a/compiler/testData/diagnostics/tests/operatorRem/DeprecatedModAssignOperatorConventions.fir.kt b/compiler/testData/diagnostics/tests/operatorRem/DeprecatedModAssignOperatorConventions.fir.kt index 68a4881569d..d4c57fb3bdd 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) {} + operator fun modAssign(x: Int) {} operator fun remAssign(x: Int) {} } class OnlyOld { - operator fun modAssign(x: Int) {} + operator fun modAssign(x: Int) {} } class OnlyNew { @@ -16,11 +16,11 @@ class OnlyNew { class Sample -operator fun Sample.modAssign(x: Int) {} +operator fun Sample.modAssign(x: Int) {} operator fun Sample.remAssign(x: Int) {} class ModAndRemAssign { - operator fun mod(x: Int): ModAndRemAssign = ModAndRemAssign() + 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 ebe52c32cb9..50d476f2bb3 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) {} + operator fun mod(x: Int) {} operator fun rem(x: Int) {} } class OnlyOld { - operator fun mod(x: Int) {} + operator fun mod(x: Int) {} } class OnlyNew { @@ -16,11 +16,11 @@ class OnlyNew { class Sample -operator fun Sample.mod(x: Int) {} +operator fun Sample.mod(x: Int) {} operator fun Sample.rem(x: Int) {} class IntAndUnit { - operator fun mod(x: Int) = 0 + 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 7873fff6e33..61d4eb6c2fe 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) {} + operator fun mod(x: Int) {} operator fun rem(x: Int) {} } object OldMod { - operator fun mod(x: Int) {} + operator fun mod(x: Int) {} } object ModAndRemExtension -operator fun ModAndRemExtension.mod(x: Int) {} +operator fun ModAndRemExtension.mod(x: Int) {} operator fun ModAndRemExtension.rem(x: Int) {} object ModExtension -operator fun ModExtension.mod(x: Int) {} +operator fun ModExtension.mod(x: Int) {} object ModMemberAndRemExtension { - operator fun mod(x: Int) {} + 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 e6965a5e5eb..331b844dcfc 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) {} + 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 842be5c2e1c..f145162a11b 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) {} + operator fun mod(x: Int) {} operator fun rem(x: Int) {} - operator fun modAssign(x: Int) {} + operator fun modAssign(x: Int) {} operator fun remAssign(x: Int) {} } object JustMod { - operator fun mod(x: Int) {} - operator fun modAssign(x: Int) {} + operator fun mod(x: Int) {} + 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 1f88d50ea19..00000000000 --- 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 2f6fdefd0a6..efe449c777e 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 3695372a668..00000000000 --- 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 56c6a556d5a..58acaad9073 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 eec75b34f0c..00000000000 --- 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 1adf05b139c..5cf456aff31 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 acf62c6d659..00000000000 --- 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 17a7880e80c..0a5fa6854c4 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 d7059144f35..00000000000 --- 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 0e7f7d3fd06..89a6d92eda4 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 e1a2d488c3e..00000000000 --- 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 67caa7fb50f..d6783ee81df 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 0b7bcaef8fe..00000000000 --- 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 78fa07fb91d..3d8e86ac8b9 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 530b5050668..00000000000 --- 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 38b40fff591..848d42562d3 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 2ceabb24a13..00000000000 --- 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 3ff810b944c..d9532df7ee8 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 008c29c703c..29f164fdb62 100644 --- a/compiler/testData/diagnostics/tests/operatorRem/resolveModIfRemIsHidden.fir.kt +++ b/compiler/testData/diagnostics/tests/operatorRem/resolveModIfRemIsHidden.fir.kt @@ -6,7 +6,7 @@ object A { @Deprecated("Use mod instead", ReplaceWith("mod"), DeprecationLevel.HIDDEN) operator fun rem(x: Int) = 0 - operator fun mod(x: Int) = "" + 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 00000000000..0b9c5b82885 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/kt55747.kt @@ -0,0 +1,6 @@ +// FIR_IDENTICAL + +object Rem { + operator fun mod(x: Int) {} + 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 00000000000..b50472c0e5a --- /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 95264f56c6c..91ffbe971e3 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 @@ -35499,6 +35499,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/testsWithStdLib/kt54410.kt"); } + @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 { 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 73a41f88dc8..5e14b0e163b 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 @@ object OperatorNameConventions { @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) }