diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt index c49453eb414..9d54db61173 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt @@ -16,10 +16,7 @@ package org.jetbrains.kotlin.resolve -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType -import org.jetbrains.kotlin.builtins.getValueParametersFromFunctionType -import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype +import org.jetbrains.kotlin.builtins.* import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.ConstructorDescriptorImpl @@ -220,12 +217,15 @@ class FunctionDescriptorResolver( ) } - private fun KotlinType.functionTypeExpected() = !TypeUtils.noExpectedType(this) && isFunctionTypeOrSubtype + private fun KotlinType.functionTypeExpected() = !TypeUtils.noExpectedType(this) && isFunctionType private fun KotlinType.getReceiverType(): KotlinType? = if (functionTypeExpected()) getReceiverTypeFromFunctionType(this) else null private fun KotlinType.getValueParameters(owner: FunctionDescriptor): List? = - if (functionTypeExpected()) getValueParametersFromFunctionType(owner, this) else null + if (functionTypeExpected()) { + createValueParametersFromFunctionType(owner, getParameterTypeProjectionsFromFunctionType(this)) + } + else null fun resolvePrimaryConstructorDescriptor( scope: LexicalScope, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt index 9e0c117714c..330974a4a33 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt @@ -16,7 +16,10 @@ package org.jetbrains.kotlin.resolve.callableReferences -import org.jetbrains.kotlin.builtins.* +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.builtins.ReflectionTypes +import org.jetbrains.kotlin.builtins.createFunctionType +import org.jetbrains.kotlin.builtins.createValueParametersFromFunctionType import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor @@ -210,11 +213,9 @@ private fun bindFunctionReference(expression: KtCallableReferenceExpression, typ ) functionDescriptor.initialize( - getReceiverTypeFromFunctionType(type), - null, - emptyList(), - getValueParametersFromFunctionType(functionDescriptor, type), - getReturnTypeFromFunctionType(type), + null, null, emptyList(), + createValueParametersFromFunctionType(functionDescriptor, type.arguments.dropLast(1)), + type.arguments.last().type, Modality.FINAL, Visibilities.PUBLIC ) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt index 8cc236916f3..7c7a59cec76 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt @@ -21,7 +21,7 @@ import com.intellij.psi.PsiElement import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.createFunctionType import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType -import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype +import org.jetbrains.kotlin.builtins.isFunctionType import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations @@ -140,7 +140,7 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre if (!expression.functionLiteral.hasBody()) return null val expectedType = context.expectedType - val functionTypeExpected = !noExpectedType(expectedType) && expectedType.isFunctionTypeOrSubtype + val functionTypeExpected = !noExpectedType(expectedType) && expectedType.isFunctionType val functionDescriptor = createFunctionLiteralDescriptor(expression, context) expression.valueParameters.forEach { diff --git a/compiler/testData/diagnostics/testsWithStdLib/regression/ea70485_functionTypeInheritor.kt b/compiler/testData/diagnostics/testsWithStdLib/regression/ea70485_functionTypeInheritor.kt new file mode 100644 index 00000000000..40256400225 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/regression/ea70485_functionTypeInheritor.kt @@ -0,0 +1,17 @@ +class O : Function2 { + override fun invoke(p1: Int, p2: String) { + } +} + +fun test() { + val a = fun(o: O) { + } + a {} +} + +class Ext : String.() -> Unit { +} + +fun test2() { + val f: Ext = {} +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/regression/ea70485_functionTypeInheritor.txt b/compiler/testData/diagnostics/testsWithStdLib/regression/ea70485_functionTypeInheritor.txt new file mode 100644 index 00000000000..dc6f2075ecd --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/regression/ea70485_functionTypeInheritor.txt @@ -0,0 +1,20 @@ +package + +public fun test(): kotlin.Unit +public fun test2(): kotlin.Unit + +public final class Ext : kotlin.String.() -> kotlin.Unit { + public constructor Ext() + 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 abstract override /*1*/ /*fake_override*/ fun invoke(/*0*/ p1: kotlin.String): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class O : (kotlin.Int, kotlin.String) -> kotlin.Unit { + public constructor O() + 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*/ fun invoke(/*0*/ p1: kotlin.Int, /*1*/ p2: kotlin.String): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/regression/kt9820_javaFunctionTypeInheritor.kt b/compiler/testData/diagnostics/testsWithStdLib/regression/kt9820_javaFunctionTypeInheritor.kt new file mode 100644 index 00000000000..d0cee3e8629 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/regression/kt9820_javaFunctionTypeInheritor.kt @@ -0,0 +1,16 @@ +// FILE: J.java + +import kotlin.jvm.functions.Function1; + +public interface J extends Function1 { +} + +// FILE: 1.kt + +fun useJ(j: J) { + j(42) +} + +fun jj() { + useJ({}) +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/regression/kt9820_javaFunctionTypeInheritor.txt b/compiler/testData/diagnostics/testsWithStdLib/regression/kt9820_javaFunctionTypeInheritor.txt new file mode 100644 index 00000000000..e7782edda6a --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/regression/kt9820_javaFunctionTypeInheritor.txt @@ -0,0 +1,12 @@ +package + +public /*synthesized*/ fun J(/*0*/ function: (kotlin.Int!) -> java.lang.Void!): J +public fun jj(): kotlin.Unit +public fun useJ(/*0*/ j: J): kotlin.Unit + +public interface J : (kotlin.Int!) -> java.lang.Void! { + 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 abstract override /*1*/ /*fake_override*/ fun invoke(/*0*/ p1: kotlin.Int!): java.lang.Void! + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java index df740b8c020..40ceef41d4d 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java @@ -1036,6 +1036,12 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW doTest(fileName); } + @TestMetadata("ea70485_functionTypeInheritor.kt") + public void testEa70485_functionTypeInheritor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/regression/ea70485_functionTypeInheritor.kt"); + doTest(fileName); + } + @TestMetadata("ea70880_illegalJvmName.kt") public void testEa70880_illegalJvmName() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/regression/ea70880_illegalJvmName.kt"); @@ -1053,6 +1059,12 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/regression/kt9345.kt"); doTest(fileName); } + + @TestMetadata("kt9820_javaFunctionTypeInheritor.kt") + public void testKt9820_javaFunctionTypeInheritor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/regression/kt9820_javaFunctionTypeInheritor.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/reified") diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/functionTypes.kt b/core/descriptors/src/org/jetbrains/kotlin/builtins/functionTypes.kt index 6690eda58ba..cb54a82a342 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/functionTypes.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/functionTypes.kt @@ -63,16 +63,14 @@ fun isNumberedFunctionClassFqName(fqName: FqNameUnsafe): Boolean { } fun getReceiverTypeFromFunctionType(type: KotlinType): KotlinType? { - assert(type.isFunctionTypeOrSubtype) { type } - if (type.isExtensionFunctionType) { - return type.arguments.first().type - } - return null + assert(type.isFunctionType) { "Not a function type: $type" } + return if (type.isTypeAnnotatedWithExtensionFunctionType) type.arguments.first().type else null } -fun getValueParametersFromFunctionType(functionDescriptor: FunctionDescriptor, type: KotlinType): List { - assert(type.isFunctionTypeOrSubtype) { type } - return getParameterTypeProjectionsFromFunctionType(type).mapIndexed { i, typeProjection -> +fun createValueParametersFromFunctionType( + functionDescriptor: FunctionDescriptor, parameterTypes: List +): List { + return parameterTypes.mapIndexed { i, typeProjection -> ValueParameterDescriptorImpl( functionDescriptor, null, i, Annotations.EMPTY, Name.identifier("p${i + 1}"), typeProjection.type, @@ -85,22 +83,17 @@ fun getValueParametersFromFunctionType(functionDescriptor: FunctionDescriptor, t } fun getReturnTypeFromFunctionType(type: KotlinType): KotlinType { - assert(type.isFunctionTypeOrSubtype) { type } + assert(type.isFunctionType) { "Not a function type: $type" } return type.arguments.last().type } fun getParameterTypeProjectionsFromFunctionType(type: KotlinType): List { - assert(type.isFunctionTypeOrSubtype) { type } + assert(type.isFunctionType) { "Not a function type: $type" } val arguments = type.arguments val first = if (type.isExtensionFunctionType) 1 else 0 - val last = arguments.size - 2 - // TODO: fix bugs associated with this here and in neighboring methods, see KT-9820 - assert(first <= last + 1) { "Not an exact function type: $type" } - val parameterTypes = ArrayList(last - first + 1) - for (i in first..last) { - parameterTypes.add(arguments[i]) - } - return parameterTypes + val last = arguments.size - 1 + assert(first <= last) { "Not an exact function type: $type" } + return arguments.subList(first, last) } fun createFunctionType(