diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 9a61b4ff393..01576fbd30a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -2294,22 +2294,11 @@ public class ExpressionCodegen extends KtVisitor impleme descriptor = originalIfSamAdapter; } // $default method is not private, so you need no accessor to call it - return usesDefaultArguments(resolvedCall) + return CallUtilKt.usesDefaultArguments(resolvedCall) ? descriptor : context.accessibleDescriptor(descriptor, getSuperCallTarget(resolvedCall.getCall())); } - private static boolean usesDefaultArguments(@NotNull ResolvedCall resolvedCall) { - List valueArguments = resolvedCall.getValueArgumentsByIndex(); - if (valueArguments == null) return false; - - for (ResolvedValueArgument argument : valueArguments) { - if (argument instanceof DefaultValueArgument) return true; - } - - return false; - } - @NotNull public StackValue invokeFunction(@NotNull ResolvedCall resolvedCall, @NotNull StackValue receiver) { return invokeFunction(resolvedCall.getCall(), resolvedCall, receiver); diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/SuperCallWithDefaultArgumentsChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/SuperCallWithDefaultArgumentsChecker.kt new file mode 100644 index 00000000000..e807a3bc919 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/SuperCallWithDefaultArgumentsChecker.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.resolve.jvm.checkers + +import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getSuperCallExpression +import org.jetbrains.kotlin.resolve.calls.callUtil.usesDefaultArguments +import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker +import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm + +class SuperCallWithDefaultArgumentsChecker : CallChecker { + override fun check(resolvedCall: ResolvedCall, context: BasicCallResolutionContext) { + val superCallExpression = getSuperCallExpression(resolvedCall.call) + if (superCallExpression == null || !resolvedCall.usesDefaultArguments()) return + context.trace.report(ErrorsJvm.SUPER_CALL_WITH_DEFAULT_PARAMETERS.on(superCallExpression.parent, resolvedCall.resultingDescriptor.name.asString())) + } +} \ No newline at end of file diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java index 76a1fa701bf..bfc5c235c16 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java @@ -100,6 +100,8 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension { MAP.put(ErrorsJvm.UPPER_BOUND_CANNOT_BE_ARRAY, "Upper bound of a type parameter cannot be an array"); MAP.put(ErrorsJvm.INAPPLICABLE_JVM_FIELD, "{0}", Renderers.TO_STRING); + + MAP.put(ErrorsJvm.SUPER_CALL_WITH_DEFAULT_PARAMETERS, "Super-calls with default arguments are not allowed. Please specify all arguments of ''super.{0}'' explicitly", Renderers.TO_STRING); } @NotNull diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java index 69abffd183f..653a3f4ceb5 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java @@ -80,6 +80,8 @@ public interface ErrorsJvm { DiagnosticFactory0 UPPER_BOUND_CANNOT_BE_ARRAY = DiagnosticFactory0.create(ERROR); + DiagnosticFactory1 SUPER_CALL_WITH_DEFAULT_PARAMETERS = DiagnosticFactory1.create(ERROR); + enum NullabilityInformationSource { KOTLIN { @NotNull diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt index 1da91f6e047..348ba1bbdd3 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.jvm.RuntimeAssertionsTypeChecker import org.jetbrains.kotlin.load.kotlin.JavaAnnotationCallChecker import org.jetbrains.kotlin.load.kotlin.nativeDeclarations.NativeFunChecker import org.jetbrains.kotlin.resolve.* +import org.jetbrains.kotlin.resolve.jvm.checkers.SuperCallWithDefaultArgumentsChecker import org.jetbrains.kotlin.resolve.jvm.JvmOverloadFilter import org.jetbrains.kotlin.resolve.jvm.checkers.* import org.jetbrains.kotlin.synthetic.JavaSyntheticScopes @@ -48,7 +49,8 @@ object JvmPlatformConfigurator : PlatformConfigurator( TraitDefaultMethodCallChecker(), JavaClassOnCompanionChecker(), ProtectedInSuperClassCompanionCallChecker(), - UnsupportedSyntheticCallableReferenceChecker() + UnsupportedSyntheticCallableReferenceChecker(), + SuperCallWithDefaultArgumentsChecker() ), additionalTypeCheckers = listOf( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/callUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/callUtil.kt index 2d8639d1093..d2863f10be3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/callUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/callUtil.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver import org.jetbrains.kotlin.resolve.calls.CallTransformer import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext import org.jetbrains.kotlin.resolve.calls.model.* +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.sure // resolved call @@ -65,6 +66,11 @@ fun ResolvedCall.getParameterForArgument(valueArgume return (valueArgument?.let { getArgumentMapping(it) } as? ArgumentMatch)?.valueParameter } +fun ResolvedCall.usesDefaultArguments(): Boolean { + return valueArgumentsByIndex?.any { it is DefaultValueArgument } ?: false +} + + // call fun > Call.hasUnresolvedArguments(context: ResolutionContext): Boolean { diff --git a/compiler/testData/diagnostics/tests/defaultArguments/superCall.kt b/compiler/testData/diagnostics/tests/defaultArguments/superCall.kt new file mode 100644 index 00000000000..2ce8f15966f --- /dev/null +++ b/compiler/testData/diagnostics/tests/defaultArguments/superCall.kt @@ -0,0 +1,28 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -ABSTRACT_SUPER_CALL + +abstract class A { + open fun foo(a: String = "default") { + } + + final fun foo2(a: String = "default") { + } + + abstract fun foo3(a: String = "default") +} + +open class B : A() { + fun test() { + super.foo("123") + super.foo() + + super.foo2("123") + super.foo2() + + super.foo3("123") + super.foo3() + } + + override fun foo3(a: String) { + throw UnsupportedOperationException() + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/defaultArguments/superCall.txt b/compiler/testData/diagnostics/tests/defaultArguments/superCall.txt new file mode 100644 index 00000000000..afe198ace05 --- /dev/null +++ b/compiler/testData/diagnostics/tests/defaultArguments/superCall.txt @@ -0,0 +1,22 @@ +package + +public abstract class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun foo(/*0*/ a: kotlin.String = ...): kotlin.Unit + public final fun foo2(/*0*/ a: kotlin.String = ...): kotlin.Unit + public abstract fun foo3(/*0*/ a: kotlin.String = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public open class B : A { + public constructor B() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun foo(/*0*/ a: kotlin.String = ...): kotlin.Unit + public final override /*1*/ /*fake_override*/ fun foo2(/*0*/ a: kotlin.String = ...): kotlin.Unit + public open override /*1*/ fun foo3(/*0*/ a: kotlin.String = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final fun test(): 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 d53b6f52a0a..985d2f0630f 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -4439,6 +4439,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/defaultArguments/kt5232.kt"); doTest(fileName); } + + @TestMetadata("superCall.kt") + public void testSuperCall() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/defaultArguments/superCall.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/diagnostics/tests/delegatedProperty")