From bc40669598c5da88865893166b1d23fabe08ba7e Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Fri, 26 Jun 2020 08:08:18 +0300 Subject: [PATCH] Prohibit functional interface constructor references #KT-36706 Fixed --- ...irOldFrontendDiagnosticsTestGenerated.java | 5 ++++ .../jetbrains/kotlin/diagnostics/Errors.java | 1 + .../rendering/DefaultErrorMessages.java | 1 + .../resolve/PlatformConfiguratorBase.kt | 2 +- ...FunInterfaceConstructorReferenceChecker.kt | 25 +++++++++++++++++++ ...itFunInterfaceConstructorReferences.fir.kt | 7 ++++++ ...ohibitFunInterfaceConstructorReferences.kt | 7 ++++++ ...hibitFunInterfaceConstructorReferences.txt | 12 +++++++++ .../checkers/DiagnosticsTestGenerated.java | 5 ++++ .../DiagnosticsUsingJavacTestGenerated.java | 5 ++++ 10 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/FunInterfaceConstructorReferenceChecker.kt create mode 100644 compiler/testData/diagnostics/tests/funInterface/prohibitFunInterfaceConstructorReferences.fir.kt create mode 100644 compiler/testData/diagnostics/tests/funInterface/prohibitFunInterfaceConstructorReferences.kt create mode 100644 compiler/testData/diagnostics/tests/funInterface/prohibitFunInterfaceConstructorReferences.txt diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java index d1b98a52684..ab376f9089c 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java @@ -8014,6 +8014,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/funInterface/noCompatibilityResolveForFunInterfaces.kt"); } + @TestMetadata("prohibitFunInterfaceConstructorReferences.kt") + public void testProhibitFunInterfaceConstructorReferences() throws Exception { + runTest("compiler/testData/diagnostics/tests/funInterface/prohibitFunInterfaceConstructorReferences.kt"); + } + @TestMetadata("resolveFunInterfaceWithoutMainMethod.kt") public void testResolveFunInterfaceWithoutMainMethod() throws Exception { runTest("compiler/testData/diagnostics/tests/funInterface/resolveFunInterfaceWithoutMainMethod.kt"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index e904d351bca..68a2bc39667 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -369,6 +369,7 @@ public interface Errors { DiagnosticFactory0 FUN_INTERFACE_CANNOT_HAVE_ABSTRACT_PROPERTIES = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 FUN_INTERFACE_ABSTRACT_METHOD_WITH_TYPE_PARAMETERS = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 FUN_INTERFACE_ABSTRACT_METHOD_WITH_DEFAULT_VALUE = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 FUN_INTERFACE_CONSTRUCTOR_REFERENCE = DiagnosticFactory0.create(ERROR); // Secondary constructors 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 b9379796074..044dff02279 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -709,6 +709,7 @@ public class DefaultErrorMessages { MAP.put(FUN_INTERFACE_CANNOT_HAVE_ABSTRACT_PROPERTIES, "Fun interfaces cannot have abstract properties"); MAP.put(FUN_INTERFACE_ABSTRACT_METHOD_WITH_TYPE_PARAMETERS, "Single abstract member cannot declare type parameters"); MAP.put(FUN_INTERFACE_ABSTRACT_METHOD_WITH_DEFAULT_VALUE, "Single abstract member cannot declare default values"); + MAP.put(FUN_INTERFACE_CONSTRUCTOR_REFERENCE, "Functional interface constructor references are prohibited"); MAP.put(VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED, "Variance annotations are only allowed for type parameters of classes and interfaces"); MAP.put(BOUND_ON_TYPE_ALIAS_PARAMETER_NOT_ALLOWED, "Bounds are not allowed on type alias parameters"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt index 3f342be2f74..6618dc1d24d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt @@ -50,7 +50,7 @@ private val DEFAULT_CALL_CHECKERS = listOf( UselessElvisCallChecker(), ResultTypeWithNullableOperatorsChecker(), NullableVarargArgumentCallChecker, NamedFunAsExpressionChecker, ContractNotAllowedCallChecker, ReifiedTypeParameterSubstitutionChecker(), MissingDependencySupertypeChecker.ForCalls, AbstractClassInstantiationChecker, SuspendConversionCallChecker, - UnitConversionCallChecker + UnitConversionCallChecker, FunInterfaceConstructorReferenceChecker ) private val DEFAULT_TYPE_CHECKERS = emptyList() private val DEFAULT_CLASSIFIER_USAGE_CHECKERS = listOf( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/FunInterfaceConstructorReferenceChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/FunInterfaceConstructorReferenceChecker.kt new file mode 100644 index 00000000000..25c757f3e13 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/FunInterfaceConstructorReferenceChecker.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.resolve.calls.checkers + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.diagnostics.Errors +import org.jetbrains.kotlin.resolve.calls.callUtil.isCallableReference +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.sam.SamConstructorDescriptor + +object FunInterfaceConstructorReferenceChecker : CallChecker { + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { + val resultingDescriptor = resolvedCall.resultingDescriptor + if (resultingDescriptor !is SamConstructorDescriptor || !resolvedCall.call.isCallableReference()) return + + if (resultingDescriptor.baseDescriptorForSynthetic.isFun) { + context.trace.report( + Errors.FUN_INTERFACE_CONSTRUCTOR_REFERENCE.on(reportOn) + ) + } + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/funInterface/prohibitFunInterfaceConstructorReferences.fir.kt b/compiler/testData/diagnostics/tests/funInterface/prohibitFunInterfaceConstructorReferences.fir.kt new file mode 100644 index 00000000000..c8fdd583f33 --- /dev/null +++ b/compiler/testData/diagnostics/tests/funInterface/prohibitFunInterfaceConstructorReferences.fir.kt @@ -0,0 +1,7 @@ +fun interface Foo { + fun run() +} + +val x = ::Foo +val y = Foo { } +val z = ::Runnable \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/funInterface/prohibitFunInterfaceConstructorReferences.kt b/compiler/testData/diagnostics/tests/funInterface/prohibitFunInterfaceConstructorReferences.kt new file mode 100644 index 00000000000..aa4297708f0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/funInterface/prohibitFunInterfaceConstructorReferences.kt @@ -0,0 +1,7 @@ +fun interface Foo { + fun run() +} + +val x = ::Foo +val y = Foo { } +val z = ::Runnable \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/funInterface/prohibitFunInterfaceConstructorReferences.txt b/compiler/testData/diagnostics/tests/funInterface/prohibitFunInterfaceConstructorReferences.txt new file mode 100644 index 00000000000..4dc96ea4dd9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/funInterface/prohibitFunInterfaceConstructorReferences.txt @@ -0,0 +1,12 @@ +package + +public val x: kotlin.reflect.KFunction1<() -> kotlin.Unit, Foo> +public val y: Foo +public val z: kotlin.reflect.KFunction1<() -> kotlin.Unit, java.lang.Runnable> + +public fun 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 run(): 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 9c0d91ced16..51686b96c02 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -8021,6 +8021,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali runTest("compiler/testData/diagnostics/tests/funInterface/noCompatibilityResolveForFunInterfaces.kt"); } + @TestMetadata("prohibitFunInterfaceConstructorReferences.kt") + public void testProhibitFunInterfaceConstructorReferences() throws Exception { + runTest("compiler/testData/diagnostics/tests/funInterface/prohibitFunInterfaceConstructorReferences.kt"); + } + @TestMetadata("resolveFunInterfaceWithoutMainMethod.kt") public void testResolveFunInterfaceWithoutMainMethod() throws Exception { runTest("compiler/testData/diagnostics/tests/funInterface/resolveFunInterfaceWithoutMainMethod.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 76e3d008ee0..ef94c80bf1f 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -8016,6 +8016,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/funInterface/noCompatibilityResolveForFunInterfaces.kt"); } + @TestMetadata("prohibitFunInterfaceConstructorReferences.kt") + public void testProhibitFunInterfaceConstructorReferences() throws Exception { + runTest("compiler/testData/diagnostics/tests/funInterface/prohibitFunInterfaceConstructorReferences.kt"); + } + @TestMetadata("resolveFunInterfaceWithoutMainMethod.kt") public void testResolveFunInterfaceWithoutMainMethod() throws Exception { runTest("compiler/testData/diagnostics/tests/funInterface/resolveFunInterfaceWithoutMainMethod.kt");