diff --git a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/CodegenUtil.kt b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/CodegenUtil.kt index 1aa87ecf4f4..3d391c17af2 100644 --- a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/CodegenUtil.kt +++ b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/CodegenUtil.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall +import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver import org.jetbrains.kotlin.types.KotlinType object CodegenUtil { @@ -166,4 +167,12 @@ object CodegenUtil { @JvmStatic fun getActualDeclarations(file: KtFile): List = file.declarations.filterNot(KtDeclaration::hasExpectModifier) + + @JvmStatic + fun findExpectedFunctionForActual(descriptor: FunctionDescriptor): FunctionDescriptor? { + val compatibleExpectedFunctions = with(ExpectedActualResolver) { + descriptor.findCompatibleExpectedForActual(DescriptorUtils.getContainingModule(descriptor)) + } + return compatibleExpectedFunctions.firstOrNull() as FunctionDescriptor? + } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index a0cdbe7cbb7..ee4c5252400 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -12,6 +12,7 @@ import kotlin.collections.CollectionsKt; import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.backend.common.CodegenUtil; import org.jetbrains.kotlin.backend.common.bridges.Bridge; import org.jetbrains.kotlin.backend.common.bridges.ImplKt; import org.jetbrains.kotlin.codegen.annotation.AnnotatedWithOnlyTargetedAnnotations; @@ -73,6 +74,7 @@ import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DEC import static org.jetbrains.kotlin.descriptors.ModalityKt.isOverridable; import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*; import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isEffectivelyInlineOnly; +import static org.jetbrains.kotlin.diagnostics.Errors.EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND; import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor; import static org.jetbrains.kotlin.resolve.DescriptorUtils.*; import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE; @@ -585,8 +587,10 @@ public class FunctionCodegen { methodEnd = new Label(); } else { - FrameMap frameMap = createFrameMap(parentCodegen.state, functionDescriptor, signature, isStaticMethod(context.getContextKind(), - functionDescriptor)); + FrameMap frameMap = createFrameMap( + parentCodegen.state, signature, functionDescriptor.getExtensionReceiverParameter(), + functionDescriptor.getValueParameters(), isStaticMethod(context.getContextKind(), functionDescriptor) + ); if (context.isInlineMethodContext()) { functionFakeIndex = frameMap.enterTemp(Type.INT_TYPE); } @@ -1046,7 +1050,7 @@ public class FunctionCodegen { return; } - if (!isDefaultNeeded(functionDescriptor)) { + if (!isDefaultNeeded(functionDescriptor, function)) { return; } @@ -1106,8 +1110,19 @@ public class FunctionCodegen { GenerationState state = parentCodegen.state; JvmMethodSignature signature = state.getTypeMapper().mapSignatureWithGeneric(functionDescriptor, methodContext.getContextKind()); + List originalParameters = functionDescriptor.getValueParameters(); + List valueParameters; + if (functionDescriptor.isActual() && CollectionsKt.none(originalParameters, ValueParameterDescriptor::declaresDefaultValue)) { + FunctionDescriptor expected = CodegenUtil.findExpectedFunctionForActual(functionDescriptor); + assert expected != null : "Expected function should have been found earlier for " + functionDescriptor; + valueParameters = expected.getValueParameters(); + } + else { + valueParameters = originalParameters; + } + boolean isStatic = isStaticMethod(methodContext.getContextKind(), functionDescriptor); - FrameMap frameMap = createFrameMap(state, functionDescriptor, signature, isStatic); + FrameMap frameMap = createFrameMap(state, signature, functionDescriptor.getExtensionReceiverParameter(), valueParameters, isStatic); ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, signature.getReturnType(), methodContext, state, parentCodegen); @@ -1123,7 +1138,6 @@ public class FunctionCodegen { capturedArgumentsCount++; } - List valueParameters = functionDescriptor.getValueParameters(); assert valueParameters.size() > 0 : "Expecting value parameters to generate default function " + functionDescriptor; int firstMaskIndex = frameMap.enterTemp(Type.INT_TYPE); for (int index = 1; index < valueParameters.size(); index++) { @@ -1191,10 +1205,11 @@ public class FunctionCodegen { } @NotNull - public static FrameMap createFrameMap( + private static FrameMap createFrameMap( @NotNull GenerationState state, - @NotNull FunctionDescriptor function, @NotNull JvmMethodSignature signature, + @Nullable ReceiverParameterDescriptor extensionReceiverParameter, + @NotNull List valueParameters, boolean isStatic ) { FrameMap frameMap = new FrameMap(); @@ -1204,9 +1219,8 @@ public class FunctionCodegen { for (JvmMethodParameterSignature parameter : signature.getValueParameters()) { if (parameter.getKind() == JvmMethodParameterKind.RECEIVER) { - ReceiverParameterDescriptor receiverParameter = function.getExtensionReceiverParameter(); - if (receiverParameter != null) { - frameMap.enter(receiverParameter, state.getTypeMapper().mapType(receiverParameter)); + if (extensionReceiverParameter != null) { + frameMap.enter(extensionReceiverParameter, state.getTypeMapper().mapType(extensionReceiverParameter)); } else { frameMap.enterTemp(parameter.getAsmType()); @@ -1217,7 +1231,7 @@ public class FunctionCodegen { } } - for (ValueParameterDescriptor parameter : function.getValueParameters()) { + for (ValueParameterDescriptor parameter : valueParameters) { frameMap.enter(parameter, state.getTypeMapper().mapType(parameter)); } @@ -1245,17 +1259,23 @@ public class FunctionCodegen { } } - private static boolean isDefaultNeeded(FunctionDescriptor functionDescriptor) { - boolean needed = false; - if (functionDescriptor != null) { - for (ValueParameterDescriptor parameterDescriptor : functionDescriptor.getValueParameters()) { - if (parameterDescriptor.declaresDefaultValue()) { - needed = true; - break; + private boolean isDefaultNeeded(@NotNull FunctionDescriptor descriptor, @Nullable KtNamedFunction function) { + if (descriptor.isActual()) { + FunctionDescriptor expected = CodegenUtil.findExpectedFunctionForActual(descriptor); + if (expected != null && CollectionsKt.any(expected.getValueParameters(), ValueParameterDescriptor::declaresDefaultValue)) { + PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(expected); + if (element == null) { + if (function != null) { + state.getDiagnostics().report(EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND.on(function)); + } + return false; } + + return true; } } - return needed; + + return CollectionsKt.any(descriptor.getValueParameters(), ValueParameterDescriptor::declaresDefaultValue); } private void generateBridge( diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt index fa58b75c0ba..115bf9de262 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt @@ -280,8 +280,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid val parentContext = context.parentContext ?: error("Context has no parent: " + context) val methodContext = parentContext.intoFunction(callableDescriptor) - val smap: SMAP - if (callDefault) { + val smap = if (callDefault) { val implementationOwner = state.typeMapper.mapImplementationOwner(callableDescriptor) val parentCodegen = FakeMemberCodegen( codegen.parentCodegen, inliningFunction!!, methodContext.parentContext as FieldOwnerContext<*>, @@ -293,13 +292,13 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid throw IllegalStateException("Property accessors with default parameters not supported " + callableDescriptor) } FunctionCodegen.generateDefaultImplBody( - methodContext, callableDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT, - inliningFunction as KtNamedFunction?, parentCodegen, asmMethod + methodContext, callableDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT, + inliningFunction as KtNamedFunction?, parentCodegen, asmMethod ) - smap = createSMAPWithDefaultMapping(inliningFunction, parentCodegen.orCreateSourceMapper.resultMappings) + createSMAPWithDefaultMapping(inliningFunction, parentCodegen.orCreateSourceMapper.resultMappings) } else { - smap = generateMethodBody(maxCalcAdapter, callableDescriptor, methodContext, inliningFunction!!, jvmSignature, null) + generateMethodBody(maxCalcAdapter, callableDescriptor, methodContext, inliningFunction!!, jvmSignature, null) } maxCalcAdapter.visitMaxs(-1, -1) maxCalcAdapter.visitEnd() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index c4735ef249d..e60fb1d0d3a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -561,7 +561,6 @@ public interface Errors { // Multi-platform projects DiagnosticFactory0 EXPECTED_DECLARATION_WITH_BODY = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); - DiagnosticFactory0 EXPECTED_DECLARATION_WITH_DEFAULT_PARAMETER = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 EXPECTED_CLASS_CONSTRUCTOR_DELEGATION_CALL = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 EXPECTED_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER = DiagnosticFactory0.create(ERROR); DiagnosticFactory0> EXPECTED_ENUM_CONSTRUCTOR = DiagnosticFactory0.create(ERROR); @@ -571,7 +570,6 @@ public interface Errors { DiagnosticFactory0 EXPECTED_LATEINIT_PROPERTY = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 SUPERTYPE_INITIALIZED_IN_EXPECTED_CLASS = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 EXPECTED_PRIVATE_DECLARATION = DiagnosticFactory0.create(ERROR); - DiagnosticFactory0 IMPLEMENTATION_BY_DELEGATION_IN_EXPECT_CLASS = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 ACTUAL_TYPE_ALIAS_NOT_TO_CLASS = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); @@ -579,6 +577,9 @@ public interface Errors { ACTUAL_TYPE_ALIAS_TO_CLASS_WITH_DECLARATION_SITE_VARIANCE = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); DiagnosticFactory0 ACTUAL_TYPE_ALIAS_WITH_USE_SITE_VARIANCE = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); DiagnosticFactory0 ACTUAL_TYPE_ALIAS_WITH_COMPLEX_SUBSTITUTION = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); + DiagnosticFactory0 ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS = DiagnosticFactory0.create(ERROR); + + DiagnosticFactory0 EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND = DiagnosticFactory0.create(ERROR); DiagnosticFactory3>> NO_ACTUAL_FOR_EXPECT = diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index 2ee4539f0e9..210d9eab6cb 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -157,8 +157,7 @@ object PositioningStrategies { callableDeclaration?.let { it.receiverTypeReference ?: it.valueParameterList } } ParameterCount, ParameterTypes, ParameterNames, - ValueParameterHasDefault, ValueParameterVararg, - ValueParameterNoinline, ValueParameterCrossinline -> { + ValueParameterVararg, ValueParameterNoinline, ValueParameterCrossinline -> { callableDeclaration?.valueParameterList } ReturnType -> { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index ffced010554..a64979730cd 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -236,7 +236,6 @@ public class DefaultErrorMessages { MAP.put(FORBIDDEN_VARARG_PARAMETER_TYPE, "Forbidden vararg parameter type: {0}", RENDER_TYPE); MAP.put(EXPECTED_DECLARATION_WITH_BODY, "Expected declaration must not have a body"); - MAP.put(EXPECTED_DECLARATION_WITH_DEFAULT_PARAMETER, "Expected declaration cannot have parameters with default values"); MAP.put(EXPECTED_CLASS_CONSTRUCTOR_DELEGATION_CALL, "Explicit delegation call for constructor of an expected class is not allowed"); MAP.put(EXPECTED_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER, "Expected class constructor cannot have a property parameter"); MAP.put(EXPECTED_ENUM_CONSTRUCTOR, "Expected enum class cannot have a constructor"); @@ -253,6 +252,11 @@ public class DefaultErrorMessages { MAP.put(ACTUAL_TYPE_ALIAS_TO_CLASS_WITH_DECLARATION_SITE_VARIANCE, "Aliased class should not have type parameters with declaration-site variance"); MAP.put(ACTUAL_TYPE_ALIAS_WITH_USE_SITE_VARIANCE, "Right-hand side of actual type alias cannot contain use-site variance or star projections"); MAP.put(ACTUAL_TYPE_ALIAS_WITH_COMPLEX_SUBSTITUTION, "Type arguments in the right-hand side of actual type alias should be its type parameters in the same order, e.g. 'actual typealias Foo = Bar'"); + MAP.put(ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS, "Actual function cannot have default argument values, they should be declared in the expected function"); + + MAP.put(EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND, + "Expected function source is not found, therefore it's impossible to generate default argument values declared there. " + + "Please add the corresponding file to compilation sources"); MAP.put(NO_ACTUAL_FOR_EXPECT, "Expected {0} has no actual declaration in module{1}{2}", DECLARATION_NAME_WITH_KIND, PLATFORM, PlatformIncompatibilityDiagnosticRenderer.TEXT); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt index 336b019318d..edd95b947f7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt @@ -37,6 +37,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveOpenMembers import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator import org.jetbrains.kotlin.resolve.checkers.PlatformDiagnosticSuppressor import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns +import org.jetbrains.kotlin.resolve.descriptorUtil.declaresOrInheritsDefaultValue import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal import org.jetbrains.kotlin.resolve.source.KotlinSourceElement import org.jetbrains.kotlin.types.* @@ -246,6 +247,10 @@ class DeclarationsChecker( checkVarargParameters(trace, constructorDescriptor) checkConstructorVisibility(constructorDescriptor, declaration) checkExpectedClassConstructor(constructorDescriptor, declaration) + + if (constructorDescriptor.isActual) { + checkActualFunction(declaration, constructorDescriptor) + } } private fun checkExpectedClassConstructor(constructorDescriptor: ClassConstructorDescriptor, declaration: KtConstructor<*>) { @@ -765,6 +770,9 @@ class DeclarationsChecker( if (functionDescriptor.isExpect) { checkExpectedFunction(function, functionDescriptor) } + if (functionDescriptor.isActual) { + checkActualFunction(function, functionDescriptor) + } shadowedExtensionChecker.checkDeclaration(function, functionDescriptor) } @@ -774,13 +782,17 @@ class DeclarationsChecker( trace.report(EXPECTED_DECLARATION_WITH_BODY.on(function)) } - for (parameter in function.valueParameters) { - if (parameter.hasDefaultValue()) { - trace.report(EXPECTED_DECLARATION_WITH_DEFAULT_PARAMETER.on(parameter)) + checkPrivateExpectedDeclaration(function, functionDescriptor) + } + + private fun checkActualFunction(element: KtDeclaration, functionDescriptor: FunctionDescriptor) { + for (valueParameter in functionDescriptor.valueParameters) { + if (valueParameter.declaresDefaultValue()) { + trace.report( + ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS.on(DescriptorToSourceUtils.descriptorToDeclaration(valueParameter) ?: element) + ) } } - - checkPrivateExpectedDeclaration(function, functionDescriptor) } private fun checkImplicitCallableType(declaration: KtCallableDeclaration, descriptor: CallableDescriptor) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineAnalyzerExtension.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineAnalyzerExtension.kt index d99a0e497d9..2165b3db7d2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineAnalyzerExtension.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineAnalyzerExtension.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.resolve.AnalyzerExtensions import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue +import org.jetbrains.kotlin.resolve.descriptorUtil.declaresOrInheritsDefaultValue class InlineAnalyzerExtension( private val reasonableInlineRules: Iterable, @@ -95,9 +96,9 @@ class InlineAnalyzerExtension( if (parameter.hasDefaultValue()) { val ktParameter = ktParameters[parameter.index] //Always report unsupported error on functional parameter with inherited default (there are some problems with inlining) - val inheritDefaultValues = !parameter.declaresDefaultValue() - if (checkInlinableParameter(parameter, ktParameter, functionDescriptor, null) || inheritDefaultValues) { - if (inheritDefaultValues || !languageVersionSettings.supportsFeature(LanguageFeature.InlineDefaultFunctionalParameters)) { + val inheritsDefaultValue = !parameter.declaresDefaultValue() && parameter.declaresOrInheritsDefaultValue() + if (checkInlinableParameter(parameter, ktParameter, functionDescriptor, null) || inheritsDefaultValue) { + if (inheritsDefaultValue || !languageVersionSettings.supportsFeature(LanguageFeature.InlineDefaultFunctionalParameters)) { trace.report( Errors.NOT_YET_SUPPORTED_IN_INLINE.on( ktParameter, diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ArgumentsUtils.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ArgumentsUtils.kt index 081596cb96e..0c5adaa8c8d 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ArgumentsUtils.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ArgumentsUtils.kt @@ -19,16 +19,19 @@ package org.jetbrains.kotlin.resolve.calls.components import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings +import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.ParameterDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.resolve.calls.model.CollectionLiteralKotlinCallArgument import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument -import org.jetbrains.kotlin.resolve.descriptorUtil.declaresOrInheritsDefaultValue import org.jetbrains.kotlin.resolve.descriptorUtil.isParameterOfAnnotation +import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.checker.intersectWrappedTypes +import org.jetbrains.kotlin.utils.DFS import org.jetbrains.kotlin.utils.addToStdlib.safeAs internal fun unexpectedArgument(argument: KotlinCallArgument): Nothing = @@ -59,12 +62,29 @@ val ValueParameterDescriptor.isVararg: Boolean get() = varargElementType != null val ParameterDescriptor.isVararg: Boolean get() = this.safeAs()?.isVararg ?: false /** - * @return `true` iff the parameter has a default value, i.e. declares it or inherits by overriding a parameter which has a default value. + * @return `true` iff the parameter has a default value, i.e. declares it, inherits it by overriding a parameter which has a default value, + * or is a parameter of an 'actual' declaration, such that the corresponding 'expect' parameter has a default value. */ fun ValueParameterDescriptor.hasDefaultValue(): Boolean { - return declaresOrInheritsDefaultValue() + return DFS.ifAny( + listOf(this), + { current -> current.overriddenDescriptors.map(ValueParameterDescriptor::getOriginal) }, + { it.declaresDefaultValue() || it.isActualParameterWithExpectedDefault } + ) } +private val ValueParameterDescriptor.isActualParameterWithExpectedDefault: Boolean + get() { + val function = containingDeclaration + if (function is FunctionDescriptor && function.isActual) { + with(ExpectedActualResolver) { + val expected = function.findCompatibleExpectedForActual(function.module).firstOrNull() + return expected is FunctionDescriptor && expected.valueParameters[index].hasDefaultValue() + } + } + return false + } + private fun KotlinCallArgument.isArrayAssignedAsNamedArgumentInAnnotation( parameter: ParameterDescriptor, languageVersionSettings: LanguageVersionSettings diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt index 7a6cd1f2882..a4703b7f2cd 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt @@ -172,7 +172,6 @@ object ExpectedActualResolver { object ParameterNames : Incompatible("parameter names are different") object TypeParameterNames : Incompatible("names of type parameters are different") - object ValueParameterHasDefault : Incompatible("some parameters have default values") object ValueParameterVararg : Incompatible("some value parameter is vararg in one declaration and non-vararg in the other") object ValueParameterNoinline : Incompatible("some value parameter is noinline in one declaration and not noinline in the other") object ValueParameterCrossinline : Incompatible("some value parameter is crossinline in one declaration and not crossinline in the other") @@ -257,7 +256,6 @@ object ExpectedActualResolver { areCompatibleTypeParameters(aTypeParams, bTypeParams, platformModule, substitutor).let { if (it != Compatible) return it } - if (!equalsBy(aParams, bParams, ValueParameterDescriptor::declaresDefaultValue)) return Incompatible.ValueParameterHasDefault if (!equalsBy(aParams, bParams, { p -> listOf(p.varargElementType != null) })) return Incompatible.ValueParameterVararg // Adding noinline/crossinline to parameters is disallowed, except if the expected declaration was not inline at all diff --git a/compiler/testData/codegen/box/multiplatform/defaultArguments/constructor.kt b/compiler/testData/codegen/box/multiplatform/defaultArguments/constructor.kt new file mode 100644 index 00000000000..b9ecb11356c --- /dev/null +++ b/compiler/testData/codegen/box/multiplatform/defaultArguments/constructor.kt @@ -0,0 +1,21 @@ +// !LANGUAGE: +MultiPlatformProjects +// WITH_RUNTIME +// FILE: common.kt + +expect class Foo(a: String, b: Int = 0, c: Double? = null) + +// FILE: jvm.kt + +import kotlin.test.assertEquals + +actual class Foo actual constructor(a: String, b: Int, c: Double?) { + val result: String = a + "," + b + "," + c +} + +fun box(): String { + assertEquals("OK,0,null", Foo("OK").result) + assertEquals("OK,42,null", Foo("OK", 42).result) + assertEquals("OK,42,3.14", Foo("OK", 42, 3.14).result) + + return "OK" +} diff --git a/compiler/testData/codegen/box/multiplatform/defaultArguments/function.kt b/compiler/testData/codegen/box/multiplatform/defaultArguments/function.kt new file mode 100644 index 00000000000..ba521667c6c --- /dev/null +++ b/compiler/testData/codegen/box/multiplatform/defaultArguments/function.kt @@ -0,0 +1,32 @@ +// !LANGUAGE: +MultiPlatformProjects +// WITH_RUNTIME +// FILE: common.kt + +expect fun topLevel(a: String, b: Int = 0, c: Double? = null): String + +expect class Foo() { + fun member(a: String, b: Int = 0, c: Double? = null): String +} + +// FILE: jvm.kt + +import kotlin.test.assertEquals + +actual fun topLevel(a: String, b: Int, c: Double?): String = a + "," + b + "," + c + +actual class Foo actual constructor() { + actual fun member(a: String, b: Int, c: Double?): String = a + "," + b + "," + c +} + +fun box(): String { + assertEquals("OK,0,null", topLevel("OK")) + assertEquals("OK,42,null", topLevel("OK", 42)) + assertEquals("OK,42,3.14", topLevel("OK", 42, 3.14)) + + val foo = Foo() + assertEquals("OK,0,null", foo.member("OK")) + assertEquals("OK,42,null", foo.member("OK", 42)) + assertEquals("OK,42,3.14", foo.member("OK", 42, 3.14)) + + return "OK" +} diff --git a/compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromCommonClass.kt b/compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromCommonClass.kt new file mode 100644 index 00000000000..d1482e4be44 --- /dev/null +++ b/compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromCommonClass.kt @@ -0,0 +1,24 @@ +// !LANGUAGE: +MultiPlatformProjects +// WITH_RUNTIME +// FILE: common.kt + +open class A() { + fun member(a: String, b: Int = 0, c: Double? = null): String = a + "," + b + "," + c +} + +expect class B() : A + +// FILE: jvm.kt + +import kotlin.test.assertEquals + +actual class B actual constructor() : A() + +fun box(): String { + val b = B() + assertEquals("OK,0,null", b.member("OK")) + assertEquals("OK,42,null", b.member("OK", 42)) + assertEquals("OK,42,3.14", b.member("OK", 42, 3.14)) + + return "OK" +} diff --git a/compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedClass.kt b/compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedClass.kt new file mode 100644 index 00000000000..0c4d319f8e3 --- /dev/null +++ b/compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedClass.kt @@ -0,0 +1,28 @@ +// !LANGUAGE: +MultiPlatformProjects +// WITH_RUNTIME +// FILE: common.kt + +expect open class A() { + fun member(a: String, b: Int = 0, c: Double? = null): String +} + +expect class B() : A + +// FILE: jvm.kt + +import kotlin.test.assertEquals + +actual open class A actual constructor() { + actual fun member(a: String, b: Int, c: Double?): String = a + "," + b + "," + c +} + +actual class B actual constructor() : A() + +fun box(): String { + val b = B() + assertEquals("OK,0,null", b.member("OK")) + assertEquals("OK,42,null", b.member("OK", 42)) + assertEquals("OK,42,3.14", b.member("OK", 42, 3.14)) + + return "OK" +} diff --git a/compiler/testData/codegen/box/multiplatform/defaultArguments/inlineFunctionWithDefaultLambda.kt b/compiler/testData/codegen/box/multiplatform/defaultArguments/inlineFunctionWithDefaultLambda.kt new file mode 100644 index 00000000000..42cde751292 --- /dev/null +++ b/compiler/testData/codegen/box/multiplatform/defaultArguments/inlineFunctionWithDefaultLambda.kt @@ -0,0 +1,32 @@ +// !LANGUAGE: +MultiPlatformProjects +// WITH_RUNTIME +// FILE: common.kt + +expect inline fun topLevel(a: String, b: Int = 0, c: () -> Double? = { null }): String + +expect class Foo() { + inline fun member(a: String, b: Int = 0, c: () -> Double? = { null }): String +} + +// FILE: jvm.kt + +import kotlin.test.assertEquals + +actual inline fun topLevel(a: String, b: Int, c: () -> Double?): String = a + "," + b + "," + c() + +actual class Foo actual constructor() { + actual inline fun member(a: String, b: Int, c: () -> Double?): String = a + "," + b + "," + c() +} + +fun box(): String { + assertEquals("OK,0,null", topLevel("OK")) + assertEquals("OK,42,null", topLevel("OK", 42)) + assertEquals("OK,42,3.14", topLevel("OK", 42, { 3.14 })) + + val foo = Foo() + assertEquals("OK,0,null", foo.member("OK")) + assertEquals("OK,42,null", foo.member("OK", 42)) + assertEquals("OK,42,3.14", foo.member("OK", 42, { 3.14 })) + + return "OK" +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/constructor.kt b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/constructor.kt new file mode 100644 index 00000000000..b10a772353f --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/constructor.kt @@ -0,0 +1,23 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +expect class Ok(x: Int, y: String = "") + +expect class FailX(x: Int, y: String = "") + +expect class FailY(x: Int, y: String = "") + +fun test() { + Ok(42) + Ok(42, "OK") +} + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt + +actual class Ok actual constructor(x: Int, y: String) + +actual class FailX actual constructor(x: Int = 0, y: String) + +actual class FailY actual constructor(x: Int, y: String = "") diff --git a/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/constructor.txt b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/constructor.txt new file mode 100644 index 00000000000..38f39d5c190 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/constructor.txt @@ -0,0 +1,52 @@ +// -- Module: -- +package + +public fun test(): kotlin.Unit + +public final expect class FailX { + public constructor FailX(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...) + 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 +} + +public final expect class FailY { + public constructor FailY(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...) + 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 +} + +public final expect class Ok { + public constructor Ok(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...) + 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 +} + + +// -- Module: -- +package + +public fun test(): kotlin.Unit + +public final actual class FailX { + public constructor FailX(/*0*/ x: kotlin.Int = ..., /*1*/ y: kotlin.String) + 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 +} + +public final actual class FailY { + public constructor FailY(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...) + 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 +} + +public final actual class Ok { + public constructor Ok(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String) + 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/multiplatform/defaultArguments/expectedDeclaresDefaultArguments.kt b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedDeclaresDefaultArguments.kt new file mode 100644 index 00000000000..91c0ba6c62d --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedDeclaresDefaultArguments.kt @@ -0,0 +1,41 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +expect fun ok(x: Int, y: String = "") + +expect fun failX(x: Int, y: String = "") + +expect fun failY(x: Int, y: String = "") + +expect open class Foo { + fun ok(x: Int, y: String = "") + + fun failX(x: Int, y: String = "") + + fun failY(x: Int, y: String = "") +} + +fun test(foo: Foo) { + ok(42) + ok(42, "OK") + foo.ok(42) + foo.ok(42, "OK") +} + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt + +actual fun ok(x: Int, y: String) {} + +actual fun failX(x: Int = 0, y: String) {} + +actual fun failY(x: Int, y: String = "") {} + +actual open class Foo { + actual fun ok(x: Int, y: String) {} + + actual fun failX(x: Int = 0, y: String) {} + + actual fun failY(x: Int, y: String = "") {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedDeclaresDefaultArguments.txt b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedDeclaresDefaultArguments.txt new file mode 100644 index 00000000000..f690612136f --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedDeclaresDefaultArguments.txt @@ -0,0 +1,35 @@ +// -- Module: -- +package + +public expect fun failX(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit +public expect fun failY(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit +public expect fun ok(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit +public fun test(/*0*/ foo: Foo): kotlin.Unit + +public open expect class Foo { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final expect fun failX(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit + public final expect fun failY(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final expect fun ok(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + + +// -- Module: -- +package + +public actual fun failX(/*0*/ x: kotlin.Int = ..., /*1*/ y: kotlin.String): kotlin.Unit +public actual fun failY(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit +public actual fun ok(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String): kotlin.Unit +public fun test(/*0*/ foo: Foo): kotlin.Unit + +public open actual class Foo { + public constructor Foo() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final actual fun failX(/*0*/ x: kotlin.Int = ..., /*1*/ y: kotlin.String): kotlin.Unit + public final actual fun failY(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final actual fun ok(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedInheritsDefaultArguments.kt b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedInheritsDefaultArguments.kt new file mode 100644 index 00000000000..a262fcb7075 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedInheritsDefaultArguments.kt @@ -0,0 +1,37 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +interface Foo { + fun ok(x: Int, y: String = "") + + fun failX(x: Int, y: String = "") + + fun failY(x: Int, y: String = "") +} + +expect class Bar : Foo { + override fun ok(x: Int, y: String) + + override fun failX(x: Int, y: String) + + override fun failY(x: Int, y: String) +} + +fun test(foo: Foo, bar: Bar) { + foo.ok(42) + foo.ok(42, "OK") + bar.ok(42) + bar.ok(42, "OK") +} + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt + +actual class Bar : Foo { + actual override fun ok(x: Int, y: String) {} + + actual override fun failX(x: Int = 0, y: String) {} + + actual override fun failY(x: Int, y: String = "") {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedInheritsDefaultArguments.txt b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedInheritsDefaultArguments.txt new file mode 100644 index 00000000000..ff2fdefea14 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedInheritsDefaultArguments.txt @@ -0,0 +1,47 @@ +// -- Module: -- +package + +public fun test(/*0*/ foo: Foo, /*1*/ bar: Bar): kotlin.Unit + +public final expect class Bar : Foo { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open expect override /*1*/ fun failX(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit + public open expect override /*1*/ fun failY(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open expect override /*1*/ fun ok(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface Foo { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract fun failX(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit + public abstract fun failY(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public abstract fun ok(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + + +// -- Module: -- +package + +public fun test(/*0*/ foo: Foo, /*1*/ bar: Bar): kotlin.Unit + +public final actual class Bar : Foo { + public constructor Bar() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open actual override /*1*/ fun failX(/*0*/ x: kotlin.Int = ..., /*1*/ y: kotlin.String = ...): kotlin.Unit + public open actual override /*1*/ fun failY(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open actual override /*1*/ fun ok(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface Foo { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract fun failX(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit + public abstract fun failY(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public abstract fun ok(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedVsNonExpectedWithDefaults.kt b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedVsNonExpectedWithDefaults.kt new file mode 100644 index 00000000000..6dabd1d749d --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedVsNonExpectedWithDefaults.kt @@ -0,0 +1,17 @@ +// !LANGUAGE: +MultiPlatformProjects +// !DIAGNOSTICS: -UNUSED_PARAMETER +// MODULE: m1-common +// FILE: common.kt + +expect fun ok(x: Int, y: String = "") + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt + +actual fun ok(x: Int, y: String) {} + +fun ok(x: Int, y: Long = 1L) {} + +fun test() { + ok(1) +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedVsNonExpectedWithDefaults.txt b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedVsNonExpectedWithDefaults.txt new file mode 100644 index 00000000000..8b641a4f8ae --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedVsNonExpectedWithDefaults.txt @@ -0,0 +1,12 @@ +// -- Module: -- +package + +public expect fun ok(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit + + +// -- Module: -- +package + +public fun ok(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Long = ...): kotlin.Unit +public actual fun ok(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String): kotlin.Unit +public fun test(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/headerClassWithFunctionBody.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/headerClassWithFunctionBody.kt index 95c5c8f89c3..01c34793518 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/headerClassWithFunctionBody.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/headerClassWithFunctionBody.kt @@ -21,8 +21,6 @@ expect class Foo( get() = "no" set(value) {} - fun defaultArg(value: String = "no") - fun functionWithBody(x: Int): Int { return x + 1 } diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/headerClassWithFunctionBody.txt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/headerClassWithFunctionBody.txt index 049a8ff806e..5d45419bb36 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/headerClassWithFunctionBody.txt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/headerClassWithFunctionBody.txt @@ -7,7 +7,6 @@ public final expect class Foo { public expect final val constructorProperty: kotlin.String public expect final var getSet: kotlin.String public expect final val prop: kotlin.String = "no" - public final expect fun defaultArg(/*0*/ value: kotlin.String = ...): kotlin.Unit public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final expect fun functionWithBody(/*0*/ x: kotlin.Int): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/defaultArguments.kt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/defaultArguments.kt deleted file mode 100644 index b38d03f9260..00000000000 --- a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/defaultArguments.kt +++ /dev/null @@ -1,5 +0,0 @@ -// !LANGUAGE: +MultiPlatformProjects -// MODULE: m1-common -// FILE: common.kt - -expect fun foo(x: Int, y: String = "") diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/defaultArguments.txt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/defaultArguments.txt deleted file mode 100644 index 5e8b0516acb..00000000000 --- a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/defaultArguments.txt +++ /dev/null @@ -1,3 +0,0 @@ -package - -public expect fun foo(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit diff --git a/compiler/testData/multiplatform/incompatibleCallables/output.txt b/compiler/testData/multiplatform/incompatibleCallables/output.txt index 7379739d9e7..b7ae225d0ab 100644 --- a/compiler/testData/multiplatform/incompatibleCallables/output.txt +++ b/compiler/testData/multiplatform/incompatibleCallables/output.txt @@ -164,12 +164,9 @@ The following declaration is incompatible because some type parameter is reified actual inline fun f14() {} ^ -compiler/testData/multiplatform/incompatibleCallables/jvm.kt:26:15: error: actual function 'f16' has no corresponding expected declaration -The following declaration is incompatible because some parameters have default values: - public expect fun f16(s: String): Unit - +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:26:16: error: actual function cannot have default argument values, they should be declared in the expected function actual fun f16(s: String = "") {} - ^ + ^ compiler/testData/multiplatform/incompatibleCallables/jvm.kt:28:15: error: actual function 'f17' has no corresponding expected declaration The following declaration is incompatible because some value parameter is vararg in one declaration and non-vararg in the other: public expect fun f17(vararg s: String): Unit diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index cf593f41aa7..7f7a7f4f0d7 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -12646,6 +12646,54 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes } } + @TestMetadata("compiler/testData/codegen/box/multiplatform") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Multiplatform extends AbstractIrBlackBoxCodegenTest { + public void testAllFilesPresentInMultiplatform() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/multiplatform"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class DefaultArguments extends AbstractIrBlackBoxCodegenTest { + public void testAllFilesPresentInDefaultArguments() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/multiplatform/defaultArguments"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("constructor.kt") + public void testConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments/constructor.kt"); + doTest(fileName); + } + + @TestMetadata("function.kt") + public void testFunction() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments/function.kt"); + doTest(fileName); + } + + @TestMetadata("inheritedFromCommonClass.kt") + public void testInheritedFromCommonClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromCommonClass.kt"); + doTest(fileName); + } + + @TestMetadata("inheritedFromExpectedClass.kt") + public void testInheritedFromExpectedClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedClass.kt"); + doTest(fileName); + } + + @TestMetadata("inlineFunctionWithDefaultLambda.kt") + public void testInlineFunctionWithDefaultLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments/inlineFunctionWithDefaultLambda.kt"); + doTest(fileName); + } + } + } + @TestMetadata("compiler/testData/codegen/box/nonLocalReturns") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index ea1aa8f1936..369032d8bb8 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -14228,6 +14228,39 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/defaultArguments") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class DefaultArguments extends AbstractDiagnosticsTest { + public void testAllFilesPresentInDefaultArguments() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform/defaultArguments"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("constructor.kt") + public void testConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/constructor.kt"); + doTest(fileName); + } + + @TestMetadata("expectedDeclaresDefaultArguments.kt") + public void testExpectedDeclaresDefaultArguments() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedDeclaresDefaultArguments.kt"); + doTest(fileName); + } + + @TestMetadata("expectedInheritsDefaultArguments.kt") + public void testExpectedInheritsDefaultArguments() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedInheritsDefaultArguments.kt"); + doTest(fileName); + } + + @TestMetadata("expectedVsNonExpectedWithDefaults.kt") + public void testExpectedVsNonExpectedWithDefaults() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedVsNonExpectedWithDefaults.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/deprecated") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -14545,12 +14578,6 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } - @TestMetadata("defaultArguments.kt") - public void testDefaultArguments() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun/defaultArguments.kt"); - doTest(fileName); - } - @TestMetadata("functionModifiers.kt") public void testFunctionModifiers() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun/functionModifiers.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index f070b5d9bca..5bce717d9d2 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -14228,6 +14228,39 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing doTest(fileName); } + @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/defaultArguments") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class DefaultArguments extends AbstractDiagnosticsUsingJavacTest { + public void testAllFilesPresentInDefaultArguments() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform/defaultArguments"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("constructor.kt") + public void testConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/constructor.kt"); + doTest(fileName); + } + + @TestMetadata("expectedDeclaresDefaultArguments.kt") + public void testExpectedDeclaresDefaultArguments() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedDeclaresDefaultArguments.kt"); + doTest(fileName); + } + + @TestMetadata("expectedInheritsDefaultArguments.kt") + public void testExpectedInheritsDefaultArguments() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedInheritsDefaultArguments.kt"); + doTest(fileName); + } + + @TestMetadata("expectedVsNonExpectedWithDefaults.kt") + public void testExpectedVsNonExpectedWithDefaults() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedVsNonExpectedWithDefaults.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/deprecated") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -14545,12 +14578,6 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing doTest(fileName); } - @TestMetadata("defaultArguments.kt") - public void testDefaultArguments() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun/defaultArguments.kt"); - doTest(fileName); - } - @TestMetadata("functionModifiers.kt") public void testFunctionModifiers() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun/functionModifiers.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 2ce00dbcd12..983254035c8 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -12646,6 +12646,54 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { } } + @TestMetadata("compiler/testData/codegen/box/multiplatform") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Multiplatform extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInMultiplatform() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/multiplatform"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class DefaultArguments extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInDefaultArguments() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/multiplatform/defaultArguments"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("constructor.kt") + public void testConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments/constructor.kt"); + doTest(fileName); + } + + @TestMetadata("function.kt") + public void testFunction() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments/function.kt"); + doTest(fileName); + } + + @TestMetadata("inheritedFromCommonClass.kt") + public void testInheritedFromCommonClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromCommonClass.kt"); + doTest(fileName); + } + + @TestMetadata("inheritedFromExpectedClass.kt") + public void testInheritedFromExpectedClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedClass.kt"); + doTest(fileName); + } + + @TestMetadata("inlineFunctionWithDefaultLambda.kt") + public void testInlineFunctionWithDefaultLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments/inlineFunctionWithDefaultLambda.kt"); + doTest(fileName); + } + } + } + @TestMetadata("compiler/testData/codegen/box/nonLocalReturns") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index e2b9af990a1..11eea361587 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -12646,6 +12646,54 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes } } + @TestMetadata("compiler/testData/codegen/box/multiplatform") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Multiplatform extends AbstractLightAnalysisModeTest { + public void testAllFilesPresentInMultiplatform() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/multiplatform"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class DefaultArguments extends AbstractLightAnalysisModeTest { + public void testAllFilesPresentInDefaultArguments() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/multiplatform/defaultArguments"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("constructor.kt") + public void testConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments/constructor.kt"); + doTest(fileName); + } + + @TestMetadata("function.kt") + public void testFunction() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments/function.kt"); + doTest(fileName); + } + + @TestMetadata("inheritedFromCommonClass.kt") + public void testInheritedFromCommonClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromCommonClass.kt"); + doTest(fileName); + } + + @TestMetadata("inheritedFromExpectedClass.kt") + public void testInheritedFromExpectedClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedClass.kt"); + doTest(fileName); + } + + @TestMetadata("inlineFunctionWithDefaultLambda.kt") + public void testInlineFunctionWithDefaultLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments/inlineFunctionWithDefaultLambda.kt"); + doTest(fileName); + } + } + } + @TestMetadata("compiler/testData/codegen/box/nonLocalReturns") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/MigrateDiagnosticSuppressionInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/MigrateDiagnosticSuppressionInspection.kt index bae06179f56..9b745f29382 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/MigrateDiagnosticSuppressionInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/MigrateDiagnosticSuppressionInspection.kt @@ -63,7 +63,6 @@ class MigrateDiagnosticSuppressionInspection : AbstractKotlinInspection(), Clean private val MIGRATION_MAP = mapOf( "HEADER_DECLARATION_WITH_BODY" to EXPECTED_DECLARATION_WITH_BODY, - "HEADER_DECLARATION_WITH_DEFAULT_PARAMETER" to EXPECTED_DECLARATION_WITH_DEFAULT_PARAMETER, "HEADER_CLASS_CONSTRUCTOR_DELEGATION_CALL" to EXPECTED_CLASS_CONSTRUCTOR_DELEGATION_CALL, "HEADER_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER" to EXPECTED_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER, "HEADER_ENUM_CONSTRUCTOR" to EXPECTED_ENUM_CONSTRUCTOR, diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index f69db134b1b..c1cf221094d 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -13732,6 +13732,54 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { } } + @TestMetadata("compiler/testData/codegen/box/multiplatform") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Multiplatform extends AbstractJsCodegenBoxTest { + public void testAllFilesPresentInMultiplatform() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/multiplatform"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true); + } + + @TestMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class DefaultArguments extends AbstractJsCodegenBoxTest { + public void testAllFilesPresentInDefaultArguments() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/multiplatform/defaultArguments"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true); + } + + @TestMetadata("constructor.kt") + public void testConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments/constructor.kt"); + doTest(fileName); + } + + @TestMetadata("function.kt") + public void testFunction() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments/function.kt"); + doTest(fileName); + } + + @TestMetadata("inheritedFromCommonClass.kt") + public void testInheritedFromCommonClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromCommonClass.kt"); + doTest(fileName); + } + + @TestMetadata("inheritedFromExpectedClass.kt") + public void testInheritedFromExpectedClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedClass.kt"); + doTest(fileName); + } + + @TestMetadata("inlineFunctionWithDefaultLambda.kt") + public void testInlineFunctionWithDefaultLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiplatform/defaultArguments/inlineFunctionWithDefaultLambda.kt"); + doTest(fileName); + } + } + } + @TestMetadata("compiler/testData/codegen/box/nonLocalReturns") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/FunctionBodyTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/FunctionBodyTranslator.java index 7cd5664544a..c7ffc9e07e7 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/FunctionBodyTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/FunctionBodyTranslator.java @@ -17,12 +17,15 @@ package org.jetbrains.kotlin.js.translate.utils; import com.intellij.psi.PsiElement; +import kotlin.collections.CollectionsKt; import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.backend.common.CodegenUtil; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.descriptors.FunctionDescriptor; import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; +import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.js.backend.ast.*; import org.jetbrains.kotlin.js.backend.ast.metadata.MetadataProperties; import org.jetbrains.kotlin.js.naming.NameSuggestion; @@ -35,6 +38,7 @@ import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator; import org.jetbrains.kotlin.psi.KtBlockExpression; import org.jetbrains.kotlin.psi.KtDeclarationWithBody; import org.jetbrains.kotlin.psi.KtExpression; +import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt; import org.jetbrains.kotlin.types.KotlinType; @@ -74,18 +78,36 @@ public final class FunctionBodyTranslator extends AbstractTranslator { } @NotNull - public static List setDefaultValueForArguments(@NotNull FunctionDescriptor descriptor, - @NotNull TranslationContext functionBodyContext) { - List valueParameters = descriptor.getValueParameters(); + public static List setDefaultValueForArguments( + @NotNull FunctionDescriptor descriptor, + @NotNull TranslationContext context + ) { + List originalParameters = descriptor.getValueParameters(); + List valueParameters; + if (descriptor.isActual() && CollectionsKt.none(originalParameters, ValueParameterDescriptor::declaresDefaultValue)) { + FunctionDescriptor expected = CodegenUtil.findExpectedFunctionForActual(descriptor); + if (expected != null) { + valueParameters = expected.getValueParameters(); + } + else { + PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(descriptor); + assert element != null : "No element found for descriptor: " + descriptor; + context.bindingTrace().report(Errors.EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND.on(element)); + valueParameters = originalParameters; + } + } + else { + valueParameters = originalParameters; + } List result = new ArrayList<>(valueParameters.size()); for (ValueParameterDescriptor valueParameter : valueParameters) { if (!valueParameter.declaresDefaultValue()) continue; - JsExpression jsNameRef = ReferenceTranslator.translateAsValueReference(valueParameter, functionBodyContext); + JsExpression jsNameRef = ReferenceTranslator.translateAsValueReference(valueParameter, context); KtExpression defaultArgument = BindingUtils.getDefaultArgument(valueParameter); JsBlock defaultArgBlock = new JsBlock(); - JsExpression defaultValue = Translation.translateAsExpression(defaultArgument, functionBodyContext, defaultArgBlock); + JsExpression defaultValue = Translation.translateAsExpression(defaultArgument, context, defaultArgBlock); PsiElement psi = KotlinSourceElementKt.getPsi(valueParameter.getSource()); JsStatement assignStatement = assignment(jsNameRef, defaultValue).source(psi).makeStmt(); JsStatement thenStatement = JsAstUtils.mergeStatementInBlockIfNeeded(assignStatement, defaultArgBlock);