diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt index 91202984cdd..49deb83fba1 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt @@ -143,6 +143,8 @@ private fun mapInapplicableCandidateError( is UnsafeCall -> mapUnsafeCallError(diagnostic.candidate, rootCause, source, qualifiedAccessSource) is ManyLambdaExpressionArguments -> FirErrors.MANY_LAMBDA_EXPRESSION_ARGUMENTS.on(rootCause.argument.source ?: source) is InfixCallOfNonInfixFunction -> FirErrors.INFIX_MODIFIER_REQUIRED.on(source, rootCause.function) + is OperatorCallOfNonOperatorFunction -> + FirErrors.OPERATOR_MODIFIER_REQUIRED.on(source, rootCause.function, rootCause.function.fir.name.asString()) else -> null } }.ifEmpty { listOf(FirErrors.INAPPLICABLE_CANDIDATE.on(source, diagnostic.candidate.symbol)) } diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index ffdcb28deb0..a53b4c3a1aa 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -1889,7 +1889,7 @@ open class RawFirBuilder( } explicitReceiver = leftArgument argumentList = buildUnaryArgumentList(rightArgument) - origin = if (conventionCallName != null) FirFunctionCallOrigin.REGULAR else FirFunctionCallOrigin.INFIX + origin = if (conventionCallName != null) FirFunctionCallOrigin.OPERATOR else FirFunctionCallOrigin.INFIX } } else { val firOperation = operationToken.toFirOperation() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallKind.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallKind.kt index 6c3795b45c1..0be5e383e08 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallKind.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallKind.kt @@ -39,7 +39,7 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) { CheckDispatchReceiver, CheckExtensionReceiver, CheckArguments, - CheckInfixCall, + CheckCallModifiers, EagerResolveOfCallableReferences, CheckLowPriorityInOverloadResolution, PostponedVariablesInitializerResolutionStage diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionDiagnostic.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionDiagnostic.kt index ba95b3fc2bb..7f661e02aa3 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionDiagnostic.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionDiagnostic.kt @@ -104,4 +104,5 @@ class ManyLambdaExpressionArguments( val argument: FirExpression ) : ResolutionDiagnostic(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR) -class InfixCallOfNonInfixFunction(val function: FirNamedFunctionSymbol) : ResolutionDiagnostic(INAPPLICABLE_MODIFIER) \ No newline at end of file +class InfixCallOfNonInfixFunction(val function: FirNamedFunctionSymbol) : ResolutionDiagnostic(INAPPLICABLE_MODIFIER) +class OperatorCallOfNonOperatorFunction(val function: FirNamedFunctionSymbol) : ResolutionDiagnostic(INAPPLICABLE_MODIFIER) \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt index 80dee4a7d80..8d4efad8fc1 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt @@ -267,14 +267,15 @@ internal object PostponedVariablesInitializerResolutionStage : ResolutionStage() } } -internal object CheckInfixCall : CheckerStage() { +internal object CheckCallModifiers : CheckerStage() { override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) { if (callInfo.callSite is FirFunctionCall) { - if (callInfo.callSite.origin == FirFunctionCallOrigin.INFIX) { - val functionSymbol = candidate.symbol as? FirNamedFunctionSymbol ?: return - if (!functionSymbol.fir.isInfix) { + val functionSymbol = candidate.symbol as? FirNamedFunctionSymbol ?: return + when { + callInfo.callSite.origin == FirFunctionCallOrigin.INFIX && !functionSymbol.fir.isInfix -> sink.reportDiagnostic(InfixCallOfNonInfixFunction(functionSymbol)) - } + callInfo.callSite.origin == FirFunctionCallOrigin.OPERATOR && !functionSymbol.fir.isOperator -> + sink.reportDiagnostic(OperatorCallOfNonOperatorFunction(functionSymbol)) } } } diff --git a/compiler/testData/diagnostics/tests/Operators.fir.kt b/compiler/testData/diagnostics/tests/Operators.fir.kt index ba2b63936ac..c916a2e5261 100644 --- a/compiler/testData/diagnostics/tests/Operators.fir.kt +++ b/compiler/testData/diagnostics/tests/Operators.fir.kt @@ -49,9 +49,9 @@ fun test() { a == b c != d - Example() + Example() + Example() + Example() - a + b + a + b a - b a[1] a["str"] @@ -67,10 +67,10 @@ fun test() { c += d c -= d - a..b + a..b c..d - Example()..Example() + Example()..Example() Example2()..Example2() a < b @@ -109,7 +109,7 @@ class Anc2 : Anc() fun test2() { Anc() + Anc() - Anc() - Anc() + Anc() - Anc() Anc2() + Anc2() } diff --git a/compiler/testData/diagnostics/tests/modifiers/operatorInfix/LocalFunctions.fir.kt b/compiler/testData/diagnostics/tests/modifiers/operatorInfix/LocalFunctions.fir.kt deleted file mode 100644 index 13e84d7c392..00000000000 --- a/compiler/testData/diagnostics/tests/modifiers/operatorInfix/LocalFunctions.fir.kt +++ /dev/null @@ -1,39 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_PARAMETER - -class Example - -fun Example.plus(other: Example) = 0 -operator infix fun Example.minus(other: Example) = 0 - -operator infix fun Example.times(other: Example) = 0 -fun Example.div(other: Example) = 0 - -fun a() { - with (Example()) { - operator infix fun Example.plus(other: Example) = "" - fun Example.minus(other: Example) = "" - - operator infix fun Example.times(other: Example) = "" - fun Example.div(other: Example) = "" - - with (Example()) { - val a = Example() - val b = Example() - - consumeString(a + b) - consumeInt(a - b) - - consumeString(a plus b) - consumeInt(a minus b) - - a * b - a / b - - a times b - a div b - } - } -} - -fun consumeInt(i: Int) {} -fun consumeString(s: String) {} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/modifiers/operatorInfix/LocalFunctions.kt b/compiler/testData/diagnostics/tests/modifiers/operatorInfix/LocalFunctions.kt index 58c21ffe96d..ff79914ce3f 100644 --- a/compiler/testData/diagnostics/tests/modifiers/operatorInfix/LocalFunctions.kt +++ b/compiler/testData/diagnostics/tests/modifiers/operatorInfix/LocalFunctions.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_PARAMETER class Example diff --git a/compiler/testData/diagnostics/tests/modifiers/operatorInfix/MemberFunctions.fir.kt b/compiler/testData/diagnostics/tests/modifiers/operatorInfix/MemberFunctions.fir.kt deleted file mode 100644 index 8cfe751b8df..00000000000 --- a/compiler/testData/diagnostics/tests/modifiers/operatorInfix/MemberFunctions.fir.kt +++ /dev/null @@ -1,45 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_PARAMETER, -EXTENSION_SHADOWED_BY_MEMBER - -class Example { - operator infix fun plus(other: Example) = 0 - fun minus(other: Example) = 0 - - operator infix fun times(other: Example) = 0 - fun div(other: Example) = 0 -} - -fun Example.plus(other: Example) = "" -operator infix fun Example.minus(other: Example) = "" - -operator infix fun Example.times(other: Example) = "" -fun Example.div(other: Example) = "" - -fun a() { - val a = Example() - val b = Example() - - a + b - a - b - a * b - a / b - - a plus b - a minus b - a times b - a div b - - with (Example()) { - consumeInt(this + a) - consumeString(this - b) - consumeInt(this * a) - consumeInt(this / b) - - consumeInt(this plus a) - consumeString(this minus b) - consumeInt(this times a) - consumeInt(this div b) - } -} - -fun consumeInt(i: Int) {} -fun consumeString(s: String) {} diff --git a/compiler/testData/diagnostics/tests/modifiers/operatorInfix/MemberFunctions.kt b/compiler/testData/diagnostics/tests/modifiers/operatorInfix/MemberFunctions.kt index 08ef0773ee0..698a21ab947 100644 --- a/compiler/testData/diagnostics/tests/modifiers/operatorInfix/MemberFunctions.kt +++ b/compiler/testData/diagnostics/tests/modifiers/operatorInfix/MemberFunctions.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_PARAMETER, -EXTENSION_SHADOWED_BY_MEMBER class Example {