Report error if fun interface method has JVM name getFunctionDelegate
This is needed so that it wouldn't clash with the corresponding member from the kotlin/jvm/internal/FunctionAdapter interface, which all fun interface wrappers will implement to get proper equals/hashCode. The workaround is to rename the fun interface method. #KT-33455
This commit is contained in:
+5
@@ -7944,6 +7944,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
||||
runTest("compiler/testData/diagnostics/tests/funInterface/funIsNotInheritedFromBaseInterface.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionDelegateClashOnJvm.kt")
|
||||
public void testFunctionDelegateClashOnJvm() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/funInterface/functionDelegateClashOnJvm.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("genericSubstitutionForFunInterface.kt")
|
||||
public void testGenericSubstitutionForFunInterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/funInterface/genericSubstitutionForFunInterface.kt");
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.jvm.checkers
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
|
||||
object FunctionDelegateMemberNameClashChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
if (descriptor !is CallableMemberDescriptor) return
|
||||
val container = descriptor.containingDeclaration
|
||||
if (container !is ClassDescriptor || !container.isFun) return
|
||||
if (descriptor.extensionReceiverParameter != null || descriptor.valueParameters.isNotEmpty()) return
|
||||
|
||||
if (descriptor is FunctionDescriptor && descriptor.name.asString() == "getFunctionDelegate" ||
|
||||
descriptor is PropertyDescriptor && descriptor.name.asString() == "functionDelegate"
|
||||
) {
|
||||
val reportOn = (declaration as? KtNamedDeclaration)?.nameIdentifier ?: declaration
|
||||
context.trace.report(ErrorsJvm.FUNCTION_DELEGATE_MEMBER_NAME_CLASH.on(reportOn))
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -156,6 +156,9 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
||||
String spreadOnPolymorphicSignature = "Spread operator is prohibited for arguments to signature-polymorphic calls";
|
||||
MAP.put(SPREAD_ON_SIGNATURE_POLYMORPHIC_CALL, spreadOnPolymorphicSignature);
|
||||
MAP.put(SPREAD_ON_SIGNATURE_POLYMORPHIC_CALL_ERROR, spreadOnPolymorphicSignature);
|
||||
|
||||
MAP.put(FUNCTION_DELEGATE_MEMBER_NAME_CLASH,
|
||||
"Functional interface member cannot have this name on JVM because it clashes with an internal member getFunctionDelegate");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -137,6 +137,8 @@ public interface ErrorsJvm {
|
||||
DiagnosticFactory0<PsiElement> SPREAD_ON_SIGNATURE_POLYMORPHIC_CALL = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory0<PsiElement> SPREAD_ON_SIGNATURE_POLYMORPHIC_CALL_ERROR = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<PsiElement> FUNCTION_DELEGATE_MEMBER_NAME_CLASH = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
Object _initializer = new Object() {
|
||||
{
|
||||
|
||||
+2
-1
@@ -39,7 +39,8 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase(
|
||||
BadInheritedJavaSignaturesChecker,
|
||||
JvmMultifileClassStateChecker,
|
||||
SynchronizedOnInlineMethodChecker,
|
||||
DefaultCheckerInTailrec
|
||||
DefaultCheckerInTailrec,
|
||||
FunctionDelegateMemberNameClashChecker,
|
||||
),
|
||||
|
||||
additionalCallCheckers = listOf(
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
fun interface F1 {
|
||||
val functionDelegate: Function<*>? get() = null
|
||||
fun invoke()
|
||||
}
|
||||
|
||||
fun interface F2 {
|
||||
fun getFunctionDelegate(): Function<*>? = null
|
||||
fun invoke()
|
||||
}
|
||||
|
||||
fun interface F3 {
|
||||
val getFunctionDelegate: Function<*>? get() = null
|
||||
fun invoke()
|
||||
}
|
||||
|
||||
fun interface F4 {
|
||||
fun functionDelegate(): Function<*>? = null
|
||||
fun invoke()
|
||||
}
|
||||
|
||||
fun interface F5 {
|
||||
val functionDelegate: Any? get() = null
|
||||
fun invoke()
|
||||
}
|
||||
|
||||
fun interface F6 {
|
||||
val String.functionDelegate: Function<*>? get() = null
|
||||
fun getFunctionDelegate(x: Any?): Function<*>? = null
|
||||
fun invoke()
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
fun interface F1 {
|
||||
val <!FUNCTION_DELEGATE_MEMBER_NAME_CLASH!>functionDelegate<!>: Function<*>? get() = null
|
||||
fun invoke()
|
||||
}
|
||||
|
||||
fun interface F2 {
|
||||
fun <!FUNCTION_DELEGATE_MEMBER_NAME_CLASH!>getFunctionDelegate<!>(): Function<*>? = null
|
||||
fun invoke()
|
||||
}
|
||||
|
||||
fun interface F3 {
|
||||
val getFunctionDelegate: Function<*>? get() = null
|
||||
fun invoke()
|
||||
}
|
||||
|
||||
fun interface F4 {
|
||||
fun functionDelegate(): Function<*>? = null
|
||||
fun invoke()
|
||||
}
|
||||
|
||||
fun interface F5 {
|
||||
val <!FUNCTION_DELEGATE_MEMBER_NAME_CLASH!>functionDelegate<!>: Any? get() = null
|
||||
fun invoke()
|
||||
}
|
||||
|
||||
fun interface F6 {
|
||||
val String.functionDelegate: Function<*>? get() = null
|
||||
fun getFunctionDelegate(x: Any?): Function<*>? = null
|
||||
fun invoke()
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package
|
||||
|
||||
public fun interface F1 {
|
||||
public open val functionDelegate: kotlin.Function<*>?
|
||||
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
|
||||
}
|
||||
|
||||
public fun interface F2 {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun getFunctionDelegate(): kotlin.Function<*>?
|
||||
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
|
||||
}
|
||||
|
||||
public fun interface F3 {
|
||||
public open val getFunctionDelegate: kotlin.Function<*>?
|
||||
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
|
||||
}
|
||||
|
||||
public fun interface F4 {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun functionDelegate(): kotlin.Function<*>?
|
||||
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
|
||||
}
|
||||
|
||||
public fun interface F5 {
|
||||
public open val functionDelegate: kotlin.Any?
|
||||
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
|
||||
}
|
||||
|
||||
public fun interface F6 {
|
||||
public open val kotlin.String.functionDelegate: kotlin.Function<*>?
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun getFunctionDelegate(/*0*/ x: kotlin.Any?): kotlin.Function<*>?
|
||||
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
|
||||
}
|
||||
@@ -7951,6 +7951,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali
|
||||
runTest("compiler/testData/diagnostics/tests/funInterface/funIsNotInheritedFromBaseInterface.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionDelegateClashOnJvm.kt")
|
||||
public void testFunctionDelegateClashOnJvm() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/funInterface/functionDelegateClashOnJvm.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("genericSubstitutionForFunInterface.kt")
|
||||
public void testGenericSubstitutionForFunInterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/funInterface/genericSubstitutionForFunInterface.kt");
|
||||
|
||||
Generated
+5
@@ -7946,6 +7946,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/funInterface/funIsNotInheritedFromBaseInterface.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionDelegateClashOnJvm.kt")
|
||||
public void testFunctionDelegateClashOnJvm() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/funInterface/functionDelegateClashOnJvm.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("genericSubstitutionForFunInterface.kt")
|
||||
public void testGenericSubstitutionForFunInterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/funInterface/genericSubstitutionForFunInterface.kt");
|
||||
|
||||
Reference in New Issue
Block a user