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 3d391c17af2..d70875ec983 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 @@ -20,11 +20,14 @@ import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement import org.jetbrains.kotlin.backend.common.bridges.findInterfaceImplementation import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.diagnostics.DiagnosticSink +import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall @@ -175,4 +178,29 @@ object CodegenUtil { } return compatibleExpectedFunctions.firstOrNull() as FunctionDescriptor? } + + @JvmStatic + fun getFunctionParametersForDefaultValueGeneration( + descriptor: FunctionDescriptor, + trace: DiagnosticSink? + ): List { + if (descriptor.isActual) { + val expected = CodegenUtil.findExpectedFunctionForActual(descriptor) + if (expected != null && expected.valueParameters.any(ValueParameterDescriptor::declaresDefaultValue)) { + val element = DescriptorToSourceUtils.descriptorToDeclaration(expected) + if (element == null) { + if (trace != null) { + val actualDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(descriptor) + ?: error("Not a source declaration: $descriptor") + trace.report(Errors.EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND.on(actualDeclaration)) + } + return descriptor.valueParameters + } + + return expected.valueParameters + } + } + + return descriptor.valueParameters + } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index ee4c5252400..c260c817255 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -74,7 +74,6 @@ 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; @@ -1110,16 +1109,9 @@ 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; - } + // 'null' because the "could not find expected declaration" error has been already reported in isDefaultNeeded earlier + List valueParameters = + CodegenUtil.getFunctionParametersForDefaultValueGeneration(functionDescriptor, null); boolean isStatic = isStaticMethod(methodContext.getContextKind(), functionDescriptor); FrameMap frameMap = createFrameMap(state, signature, functionDescriptor.getExtensionReceiverParameter(), valueParameters, isStatic); @@ -1260,22 +1252,9 @@ public class FunctionCodegen { } 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 CollectionsKt.any(descriptor.getValueParameters(), ValueParameterDescriptor::declaresDefaultValue); + List parameters = + CodegenUtil.getFunctionParametersForDefaultValueGeneration(descriptor, state.getDiagnostics()); + return CollectionsKt.any(parameters, ValueParameterDescriptor::declaresDefaultValue); } private void generateBridge( 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 09859db8069..727ee69f9a1 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,7 +17,6 @@ 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; @@ -25,7 +24,6 @@ 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; @@ -38,7 +36,6 @@ 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; @@ -83,22 +80,8 @@ public final class FunctionBodyTranslator extends AbstractTranslator { @NotNull TranslationContext context ) { List valueParameters = descriptor.getValueParameters(); - List valueParametersForDefaultValue; - if (descriptor.isActual() && CollectionsKt.none(valueParameters, ValueParameterDescriptor::declaresDefaultValue)) { - FunctionDescriptor expected = CodegenUtil.findExpectedFunctionForActual(descriptor); - if (expected != null) { - valueParametersForDefaultValue = 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)); - valueParametersForDefaultValue = valueParameters; - } - } - else { - valueParametersForDefaultValue = valueParameters; - } + List valueParametersForDefaultValue = + CodegenUtil.getFunctionParametersForDefaultValueGeneration(descriptor, context.bindingTrace()); List result = new ArrayList<>(valueParameters.size()); for (int i = 0; i < valueParameters.size(); i++) {