diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/JetControlFlowProcessor.java b/compiler/frontend/src/org/jetbrains/kotlin/cfg/JetControlFlowProcessor.java index ed174d69e55..f7d478e6a3b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/JetControlFlowProcessor.java @@ -41,10 +41,6 @@ import org.jetbrains.kotlin.lexer.JetTokens; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage; -import org.jetbrains.kotlin.resolve.BindingContext; -import org.jetbrains.kotlin.resolve.BindingContextUtils; -import org.jetbrains.kotlin.resolve.BindingTrace; -import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils; import org.jetbrains.kotlin.renderer.DescriptorRenderer; import org.jetbrains.kotlin.resolve.*; import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilPackage; @@ -277,6 +273,8 @@ public class JetControlFlowProcessor { ); if (!status.isSuccess()) continue; + if ((candidate.getExtensionReceiverParameter() == null) == candidateCall.getExtensionReceiver().exists()) continue; + Map candidateArgumentMap = candidateCall.getValueArguments(); List callArguments = call.getValueArguments(); for (int i = 0; i < callArguments.size(); i++) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.java index b433ecfbd99..1d507a75c77 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.java @@ -26,7 +26,6 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.psi.*; -import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage; import org.jetbrains.kotlin.resolve.*; import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage; import org.jetbrains.kotlin.resolve.calls.context.*; @@ -104,18 +103,16 @@ public class CandidateResolver { } if (task.checkArguments == CheckValueArgumentsMode.ENABLED) { - Set unmappedArguments = Sets.newLinkedHashSet(); ValueArgumentsToParametersMapper.Status argumentMappingStatus = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters( - context.call, context.tracing, candidateCall, unmappedArguments); + context.call, context.tracing, candidateCall, Sets.newLinkedHashSet() + ); if (!argumentMappingStatus.isSuccess()) { - if (argumentMappingStatus == ValueArgumentsToParametersMapper.Status.STRONG_ERROR) { - candidateCall.addStatus(RECEIVER_PRESENCE_ERROR); - } - else { - candidateCall.addStatus(OTHER_ERROR); - } + candidateCall.addStatus(OTHER_ERROR); } } + + checkExtensionReceiver(context); + if (!checkDispatchReceiver(context)) { candidateCall.addStatus(OTHER_ERROR); } @@ -174,6 +171,25 @@ public class CandidateResolver { checkNonExtensionCalledWithReceiver(context); } + private static void checkExtensionReceiver(@NotNull CallCandidateResolutionContext context) { + MutableResolvedCall candidateCall = context.candidateCall; + ReceiverParameterDescriptor receiverParameter = candidateCall.getCandidateDescriptor().getExtensionReceiverParameter(); + ReceiverValue receiverArgument = candidateCall.getExtensionReceiver(); + if (receiverParameter != null &&!receiverArgument.exists()) { + context.tracing.missingReceiver(candidateCall.getTrace(), receiverParameter); + candidateCall.addStatus(OTHER_ERROR); + } + if (receiverParameter == null && receiverArgument.exists()) { + context.tracing.noReceiverAllowed(candidateCall.getTrace()); + if (context.call.getCalleeExpression() instanceof JetSimpleNameExpression) { + candidateCall.addStatus(RECEIVER_PRESENCE_ERROR); + } + else { + candidateCall.addStatus(OTHER_ERROR); + } + } + } + private static boolean checkDispatchReceiver(@NotNull CallCandidateResolutionContext context) { MutableResolvedCall candidateCall = context.candidateCall; CallableDescriptor candidateDescriptor = candidateCall.getCandidateDescriptor(); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ValueArgumentsToParametersMapper.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ValueArgumentsToParametersMapper.java index 636ae99dd21..5aa7d4b7b91 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ValueArgumentsToParametersMapper.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ValueArgumentsToParametersMapper.java @@ -23,7 +23,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor; import org.jetbrains.kotlin.descriptors.CallableDescriptor; -import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor; import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; import org.jetbrains.kotlin.diagnostics.Diagnostic; import org.jetbrains.kotlin.name.Name; @@ -31,7 +30,6 @@ import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage; import org.jetbrains.kotlin.resolve.calls.model.*; import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy; -import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue; import java.util.List; import java.util.Map; @@ -46,14 +44,13 @@ import static org.jetbrains.kotlin.resolve.calls.ValueArgumentsToParametersMappe public class ValueArgumentsToParametersMapper { public enum Status { - STRONG_ERROR(false), ERROR(false), WEAK_ERROR(false), OK(true); private final boolean success; - private Status(boolean success) { + Status(boolean success) { this.success = success; } @@ -62,7 +59,6 @@ public class ValueArgumentsToParametersMapper { } public Status compose(Status other) { - if (this == STRONG_ERROR || other == STRONG_ERROR) return STRONG_ERROR; if (this == ERROR || other == ERROR) return ERROR; if (this == WEAK_ERROR || other == WEAK_ERROR) return WEAK_ERROR; return this; @@ -223,7 +219,6 @@ public class ValueArgumentsToParametersMapper { processFunctionLiteralArguments(); reportUnmappedParameters(); - checkReceiverArgument(); } private void processFunctionLiteralArguments() { @@ -265,7 +260,6 @@ public class ValueArgumentsToParametersMapper { } private void reportUnmappedParameters() { - List valueParameters = candidateCall.getCandidateDescriptor().getValueParameters(); for (ValueParameterDescriptor valueParameter : valueParameters) { if (!usedParameters.contains(valueParameter)) { @@ -283,26 +277,6 @@ public class ValueArgumentsToParametersMapper { } } - private void checkReceiverArgument() { - D candidate = candidateCall.getCandidateDescriptor(); - - ReceiverParameterDescriptor receiverParameter = candidate.getExtensionReceiverParameter(); - ReceiverValue receiverArgument = candidateCall.getExtensionReceiver(); - if (receiverParameter != null &&!receiverArgument.exists()) { - tracing.missingReceiver(candidateCall.getTrace(), receiverParameter); - setStatus(ERROR); - } - if (receiverParameter == null && receiverArgument.exists()) { - tracing.noReceiverAllowed(candidateCall.getTrace()); - if (call.getCalleeExpression() instanceof JetSimpleNameExpression) { - setStatus(STRONG_ERROR); - } - else { - setStatus(ERROR); - } - } - } - private void putVararg( ValueParameterDescriptor valueParameterDescriptor, ValueArgument valueArgument diff --git a/compiler/testData/diagnostics/tests/callableReference/function/extensionInClassDisallowed.kt b/compiler/testData/diagnostics/tests/callableReference/function/extensionInClassDisallowed.kt index 82fd291a47e..03ce8655046 100644 --- a/compiler/testData/diagnostics/tests/callableReference/function/extensionInClassDisallowed.kt +++ b/compiler/testData/diagnostics/tests/callableReference/function/extensionInClassDisallowed.kt @@ -4,12 +4,12 @@ class A { fun A.extA(x: String) = x fun main() { - ::extInt + ::extInt ::extA } } fun main() { - A::extInt - A::extA -} \ No newline at end of file + A::extInt + A::extA +} diff --git a/compiler/testData/diagnostics/tests/callableReference/kt7430_wrongClassOnLHS.kt b/compiler/testData/diagnostics/tests/callableReference/kt7430_wrongClassOnLHS.kt new file mode 100644 index 00000000000..0abc63d8894 --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/kt7430_wrongClassOnLHS.kt @@ -0,0 +1,12 @@ +// !DIAGNOSTICS: -UNUSED_EXPRESSION + +class Unrelated() + +class Test(val name: String = "") { + init { + Unrelated::name + Unrelated::foo + } + + fun foo() {} +} diff --git a/compiler/testData/diagnostics/tests/callableReference/kt7430_wrongClassOnLHS.txt b/compiler/testData/diagnostics/tests/callableReference/kt7430_wrongClassOnLHS.txt new file mode 100644 index 00000000000..042bc3596c8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/kt7430_wrongClassOnLHS.txt @@ -0,0 +1,17 @@ +package + +internal final class Test { + public constructor Test(/*0*/ name: kotlin.String = ...) + internal final val name: kotlin.String + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + internal final fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +internal final class Unrelated { + public constructor Unrelated() + 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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/callableReference/property/kt7945_unrelatedClass.kt b/compiler/testData/diagnostics/tests/callableReference/property/kt7945_unrelatedClass.kt new file mode 100644 index 00000000000..f9c917d5be8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/property/kt7945_unrelatedClass.kt @@ -0,0 +1,10 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +import kotlin.reflect.KMemberProperty + +class TestClass(var prop: Int) +open class OtherClass +fun OtherClass.test(prop: KMemberProperty): Unit = throw Exception() +class OtherClass2: OtherClass() { + val result = test(TestClass::result) +} diff --git a/compiler/testData/diagnostics/tests/callableReference/property/kt7945_unrelatedClass.txt b/compiler/testData/diagnostics/tests/callableReference/property/kt7945_unrelatedClass.txt new file mode 100644 index 00000000000..d99d7aa2d2c --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/property/kt7945_unrelatedClass.txt @@ -0,0 +1,26 @@ +package + +internal fun OtherClass.test(/*0*/ prop: kotlin.reflect.KMemberProperty): kotlin.Unit + +internal open class OtherClass { + public constructor OtherClass() + 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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +internal final class OtherClass2 : OtherClass { + public constructor OtherClass2() + internal final val result: kotlin.Unit + 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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +internal final class TestClass { + public constructor TestClass(/*0*/ prop: kotlin.Int) + internal final var prop: kotlin.Int + 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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 74f76731250..c2d72b1543a 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -1122,6 +1122,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/callableReference"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("kt7430_wrongClassOnLHS.kt") + public void testKt7430_wrongClassOnLHS() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/kt7430_wrongClassOnLHS.kt"); + doTest(fileName); + } + @TestMetadata("unused.kt") public void testUnused() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/unused.kt"); @@ -1505,6 +1511,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("kt7945_unrelatedClass.kt") + public void testKt7945_unrelatedClass() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/property/kt7945_unrelatedClass.kt"); + doTest(fileName); + } + @TestMetadata("localVariable.kt") public void testLocalVariable() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/property/localVariable.kt");