diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/OperatorCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/OperatorCallChecker.kt index fae2fb08a87..1361b3975af 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/OperatorCallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/OperatorCallChecker.kt @@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.diagnostics.DiagnosticSink import org.jetbrains.kotlin.diagnostics.Errors +import org.jetbrains.kotlin.psi.Call import org.jetbrains.kotlin.psi.KtArrayAccessExpression import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry import org.jetbrains.kotlin.psi.KtOperationReferenceExpression @@ -42,9 +43,10 @@ class OperatorCallChecker : CallChecker { if (resolvedCall is VariableAsFunctionResolvedCall && call is CallTransformer.CallForImplicitInvoke && call.itIsVariableAsFunctionCall) { val outerCall = call.outerCall - if (isConventionCall(outerCall) || outerCall.typeArguments.isNotEmpty()) { + if (isConventionCall(outerCall) || isWrongCallWithExplicitTypeArguments(resolvedCall, outerCall)) { throw AssertionError("Illegal resolved call to variable with invoke for $outerCall. " + - "Variable: ${resolvedCall.variableCall.resultingDescriptor}") + "Variable: ${resolvedCall.variableCall.resultingDescriptor}" + + "Invoke: ${resolvedCall.functionCall.resultingDescriptor}") } } @@ -75,5 +77,14 @@ class OperatorCallChecker : CallChecker { private fun checkNotErrorOrDynamic(functionDescriptor: FunctionDescriptor): Boolean { return !functionDescriptor.isDynamic() && !ErrorUtils.isError(functionDescriptor) } + + private fun isWrongCallWithExplicitTypeArguments( + resolvedCall: VariableAsFunctionResolvedCall, + outerCall: Call + ): Boolean { + val passedTypeArgumentsToInvoke = outerCall.typeArguments.isNotEmpty() && + resolvedCall.functionCall.candidateDescriptor.typeParameters.isNotEmpty() + return passedTypeArgumentsToInvoke && resolvedCall.variableCall.candidateDescriptor.typeParameters.isNotEmpty() + } } } diff --git a/compiler/testData/diagnostics/tests/operatorsOverloading/kt13330.kt b/compiler/testData/diagnostics/tests/operatorsOverloading/kt13330.kt new file mode 100644 index 00000000000..d41763b36b7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/operatorsOverloading/kt13330.kt @@ -0,0 +1,3 @@ +//KT-13330 AssertionError: Illegal resolved call to variable with invoke + +fun foo(exec: (String.() -> Unit)?) = "".exec<caret>() // is test data tag here \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/operatorsOverloading/kt13330.txt b/compiler/testData/diagnostics/tests/operatorsOverloading/kt13330.txt new file mode 100644 index 00000000000..10773a01dfd --- /dev/null +++ b/compiler/testData/diagnostics/tests/operatorsOverloading/kt13330.txt @@ -0,0 +1,3 @@ +package + +public fun foo(/*0*/ exec: (kotlin.String.() -> kotlin.Unit)?): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/operatorsOverloading/kt13349.kt b/compiler/testData/diagnostics/tests/operatorsOverloading/kt13349.kt new file mode 100644 index 00000000000..4b1fe702fb0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/operatorsOverloading/kt13349.kt @@ -0,0 +1,7 @@ +object Foo { + operator fun invoke() {} +} + +fun main(args: Array) { + Foo() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/operatorsOverloading/kt13349.txt b/compiler/testData/diagnostics/tests/operatorsOverloading/kt13349.txt new file mode 100644 index 00000000000..2c22677a3ce --- /dev/null +++ b/compiler/testData/diagnostics/tests/operatorsOverloading/kt13349.txt @@ -0,0 +1,11 @@ +package + +public fun main(/*0*/ args: kotlin.Array): kotlin.Unit + +public object Foo { + private constructor Foo() + 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 invoke(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 83dbc4b71b0..81c0723a8c5 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -12567,6 +12567,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("kt13330.kt") + public void testKt13330() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/operatorsOverloading/kt13330.kt"); + doTest(fileName); + } + + @TestMetadata("kt13349.kt") + public void testKt13349() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/operatorsOverloading/kt13349.kt"); + doTest(fileName); + } + @TestMetadata("kt3450.kt") public void testKt3450() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/operatorsOverloading/kt3450.kt");