diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java index fe3b9bffc04..98b1ac93e21 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java @@ -7797,6 +7797,34 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok } } + @TestMetadata("compiler/testData/diagnostics/tests/funInterface") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class FunInterface extends AbstractFirDiagnosticsSmokeTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInFunInterface() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/funInterface"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("basicFunInterface.kt") + public void testBasicFunInterface() throws Exception { + runTest("compiler/testData/diagnostics/tests/funInterface/basicFunInterface.kt"); + } + + @TestMetadata("basicFunInterfaceConversion.kt") + public void testBasicFunInterfaceConversion() throws Exception { + runTest("compiler/testData/diagnostics/tests/funInterface/basicFunInterfaceConversion.kt"); + } + + @TestMetadata("basicFunInterfaceDisabled.kt") + public void testBasicFunInterfaceDisabled() throws Exception { + runTest("compiler/testData/diagnostics/tests/funInterface/basicFunInterfaceDisabled.kt"); + } + } + @TestMetadata("compiler/testData/diagnostics/tests/functionAsExpression") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SamConversionResolverImpl.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SamConversionResolverImpl.kt index 8b99c1c2a72..99ba96decb2 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SamConversionResolverImpl.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SamConversionResolverImpl.kt @@ -16,8 +16,8 @@ package org.jetbrains.kotlin.load.java.sam +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.load.java.components.SamConversionResolver -import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.types.SimpleType @@ -25,9 +25,9 @@ class SamConversionResolverImpl( storageManager: StorageManager, private val samWithReceiverResolvers: Iterable ): SamConversionResolver { - private val functionTypesForSamInterfaces = storageManager.createCacheWithNullableValues() + private val functionTypesForSamInterfaces = storageManager.createCacheWithNullableValues() - override fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): SimpleType? { + override fun resolveFunctionTypeIfSamInterface(classDescriptor: ClassDescriptor): SimpleType? { return functionTypesForSamInterfaces.computeIfAbsent(classDescriptor) { val abstractMethod = SingleAbstractMethodUtils.getSingleAbstractMethodOrNull(classDescriptor) ?: return@computeIfAbsent null val shouldConvertFirstParameterToDescriptor = samWithReceiverResolvers.any { it.shouldConvertFirstSamParameterToReceiver(abstractMethod) } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SingleAbstractMethodUtils.java b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SingleAbstractMethodUtils.java index 190b1b05701..e8c4e4c2196 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SingleAbstractMethodUtils.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SingleAbstractMethodUtils.java @@ -78,9 +78,12 @@ public class SingleAbstractMethodUtils { // e.g. samType == Comparator? ClassifierDescriptor classifier = samType.getConstructor().getDeclarationDescriptor(); - if (classifier instanceof JavaClassDescriptor) { + if (classifier instanceof ClassDescriptor) { + ClassDescriptor descriptor = (ClassDescriptor) classifier; + if (!(descriptor instanceof JavaClassDescriptor) && !descriptor.isFun()) return null; + // Function2 - SimpleType functionTypeDefault = samResolver.resolveFunctionTypeIfSamInterface((JavaClassDescriptor) classifier); + SimpleType functionTypeDefault = samResolver.resolveFunctionTypeIfSamInterface(descriptor); if (functionTypeDefault != null) { SimpleType noProjectionsSamType = SingleAbstractMethodUtilsKt.nonProjectionParametrization(samType); @@ -131,7 +134,7 @@ public class SingleAbstractMethodUtils { } @Nullable - public static FunctionDescriptor getSingleAbstractMethodOrNull(@NotNull JavaClassDescriptor klass) { + public static FunctionDescriptor getSingleAbstractMethodOrNull(@NotNull ClassDescriptor klass) { // NB: this check MUST BE at start. Please do not touch until following to-do is resolved // Otherwise android data binding can cause resolve re-entrance // For details see KT-18687, KT-16149 @@ -140,7 +143,13 @@ public class SingleAbstractMethodUtils { return null; } - if (klass.isDefinitelyNotSamInterface()) return null; + if (klass instanceof JavaClassDescriptor) { + if (((JavaClassDescriptor) klass).isDefinitelyNotSamInterface()) { + return null; + } + } else if (!klass.isFun()) { + return null; + } List abstractMembers = getAbstractMembers(klass); if (abstractMembers.size() == 1) { @@ -224,6 +233,9 @@ public class SingleAbstractMethodUtils { } public static boolean isSamType(@NotNull KotlinType type) { + ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); + if (descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).isFun()) return true; + return getFunctionTypeForSamType(type, SamConversionResolver.JavaBasedSamConversionResolver.INSTANCE) != null; } diff --git a/compiler/testData/diagnostics/tests/funInterface/basicFunInterfaceConversion.kt b/compiler/testData/diagnostics/tests/funInterface/basicFunInterfaceConversion.kt new file mode 100644 index 00000000000..52e3e01c232 --- /dev/null +++ b/compiler/testData/diagnostics/tests/funInterface/basicFunInterfaceConversion.kt @@ -0,0 +1,12 @@ +// !LANGUAGE: +NewInference +FunctionInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun interface Foo { + fun invoke() +} + +fun foo(f: Foo) {} + +fun test() { + foo {} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/funInterface/basicFunInterfaceConversion.txt b/compiler/testData/diagnostics/tests/funInterface/basicFunInterfaceConversion.txt new file mode 100644 index 00000000000..54f2013b6c4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/funInterface/basicFunInterfaceConversion.txt @@ -0,0 +1,11 @@ +package + +public fun foo(/*0*/ f: Foo): kotlin.Unit +public fun test(): kotlin.Unit + +public interface Foo { + 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 fun invoke(): 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 25200b4bee2..af70a1ea6fa 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -7896,6 +7896,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/funInterface/basicFunInterface.kt"); } + @TestMetadata("basicFunInterfaceConversion.kt") + public void testBasicFunInterfaceConversion() throws Exception { + runTest("compiler/testData/diagnostics/tests/funInterface/basicFunInterfaceConversion.kt"); + } + @TestMetadata("basicFunInterfaceDisabled.kt") public void testBasicFunInterfaceDisabled() throws Exception { runTest("compiler/testData/diagnostics/tests/funInterface/basicFunInterfaceDisabled.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 8ed767a3017..3e5aedcbdef 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -7891,6 +7891,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/funInterface/basicFunInterface.kt"); } + @TestMetadata("basicFunInterfaceConversion.kt") + public void testBasicFunInterfaceConversion() throws Exception { + runTest("compiler/testData/diagnostics/tests/funInterface/basicFunInterfaceConversion.kt"); + } + @TestMetadata("basicFunInterfaceDisabled.kt") public void testBasicFunInterfaceDisabled() throws Exception { runTest("compiler/testData/diagnostics/tests/funInterface/basicFunInterfaceDisabled.kt"); diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/components/SamConversionResolver.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/components/SamConversionResolver.kt index a69469f3c4c..cdd2785f2c2 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/components/SamConversionResolver.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/components/SamConversionResolver.kt @@ -18,20 +18,22 @@ package org.jetbrains.kotlin.load.java.components import org.jetbrains.kotlin.container.DefaultImplementation import org.jetbrains.kotlin.container.PlatformSpecificExtension +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor import org.jetbrains.kotlin.types.SimpleType @DefaultImplementation(impl = SamConversionResolver.Empty::class) interface SamConversionResolver : PlatformSpecificExtension { object Empty : SamConversionResolver { - override fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): SimpleType? = null + override fun resolveFunctionTypeIfSamInterface(classDescriptor: ClassDescriptor): SimpleType? = null } object JavaBasedSamConversionResolver : SamConversionResolver { - override fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): SimpleType? { + override fun resolveFunctionTypeIfSamInterface(classDescriptor: ClassDescriptor): SimpleType? { + if (classDescriptor !is JavaClassDescriptor) return null return classDescriptor.defaultFunctionTypeForSamInterface } } - fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): SimpleType? + fun resolveFunctionTypeIfSamInterface(classDescriptor: ClassDescriptor): SimpleType? }