[FIR] Report inherited java members referencing FunctionN ^KT-60000 Fixed
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt index 22546b3..3cc549c 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt
@@ -657,6 +657,13 @@ token, ) } + add(FirErrors.UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION) { firDiagnostic -> + UnsupportedInheritanceFromJavaMemberReferencingKotlinFunctionImpl( + firSymbolBuilder.buildSymbol(firDiagnostic.a), + firDiagnostic as KtPsiDiagnostic, + token, + ) + } add(FirErrors.CYCLIC_INHERITANCE_HIERARCHY) { firDiagnostic -> CyclicInheritanceHierarchyImpl( firDiagnostic as KtPsiDiagnostic,
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt index 698ed11..6fc3f28 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt
@@ -502,6 +502,11 @@ val reason: String } + interface UnsupportedInheritanceFromJavaMemberReferencingKotlinFunction : KtFirDiagnostic<PsiElement> { + override val diagnosticClass get() = UnsupportedInheritanceFromJavaMemberReferencingKotlinFunction::class + val symbol: KtSymbol + } + interface CyclicInheritanceHierarchy : KtFirDiagnostic<PsiElement> { override val diagnosticClass get() = CyclicInheritanceHierarchy::class }
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index cf65e38..a60fa7a 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt
@@ -590,6 +590,12 @@ token: KtLifetimeToken, ) : KtAbstractFirDiagnostic<KtElement>(firDiagnostic, token), KtFirDiagnostic.SupertypeNotAClassOrInterface +internal class UnsupportedInheritanceFromJavaMemberReferencingKotlinFunctionImpl( + override val symbol: KtSymbol, + firDiagnostic: KtPsiDiagnostic, + token: KtLifetimeToken, +) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.UnsupportedInheritanceFromJavaMemberReferencingKotlinFunction + internal class CyclicInheritanceHierarchyImpl( firDiagnostic: KtPsiDiagnostic, token: KtLifetimeToken,
diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 8f672b0..9c8f261 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt
@@ -248,6 +248,9 @@ val SUPERTYPE_NOT_A_CLASS_OR_INTERFACE by error<KtElement> { parameter<String>("reason") } + val UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION by error<PsiElement>(PositioningStrategy.DECLARATION_NAME) { + parameter<FirBasedSymbol<*>>("symbol") + } val CYCLIC_INHERITANCE_HIERARCHY by error<PsiElement>() val EXPANDED_TYPE_CANNOT_BE_INHERITED by error<KtTypeReference> { parameter<ConeKotlinType>("type")
diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 7e2f195..0513ffb 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt
@@ -214,6 +214,7 @@ val SEALED_INHERITOR_IN_DIFFERENT_MODULE by error0<KtTypeReference>() val CLASS_INHERITS_JAVA_SEALED_CLASS by error0<KtTypeReference>() val SUPERTYPE_NOT_A_CLASS_OR_INTERFACE by error1<KtElement, String>() + val UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION by error1<PsiElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.DECLARATION_NAME) val CYCLIC_INHERITANCE_HIERARCHY by error0<PsiElement>() val EXPANDED_TYPE_CANNOT_BE_INHERITED by error1<KtTypeReference, ConeKotlinType>() val PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE by error0<KtModifierListOwner>(SourceElementPositioningStrategies.VARIANCE_MODIFIER)
diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt index b475c45..6db588e 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt
@@ -105,6 +105,7 @@ FirPrimaryConstructorSuperTypeChecker, FirDynamicSupertypeChecker, FirEnumCompanionInEnumConstructorCallChecker, + FirBadInheritedJavaSignaturesChecker, ) override val regularClassCheckers: Set<FirRegularClassChecker>
diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirBadInheritedJavaSignaturesChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirBadInheritedJavaSignaturesChecker.kt new file mode 100644 index 0000000..83ac51f --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirBadInheritedJavaSignaturesChecker.kt
@@ -0,0 +1,49 @@ +/* + * 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.fir.analysis.checkers.declaration + +import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors +import org.jetbrains.kotlin.fir.declarations.FirClass +import org.jetbrains.kotlin.fir.declarations.isJavaOrEnhancement +import org.jetbrains.kotlin.fir.scopes.processAllCallables +import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.fir.types.classId +import org.jetbrains.kotlin.fir.types.contains +import org.jetbrains.kotlin.name.StandardClassIds.Annotations.FunctionN + +object FirBadInheritedJavaSignaturesChecker : FirClassChecker() { + override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) { + fun containsFunctionN(type: ConeKotlinType) = type.classId == FunctionN + + declaration.unsubstitutedScope(context).processAllCallables { symbol -> + if (!symbol.isJavaOrEnhancement) { + return@processAllCallables + } + + val hasBadReturnType = symbol.resolvedReturnType.contains(::containsFunctionN) + // NB: This case with receiver is not covered with tests + // and was replicated, because it's present in the original + // checker. + val hasBadReceiverType = symbol.resolvedReceiverTypeRef?.type?.contains(::containsFunctionN) == true + val hasBadValueParameter = symbol is FirFunctionSymbol<*> && symbol.valueParameterSymbols.any { valueParameter -> + valueParameter.resolvedReturnType.contains(::containsFunctionN) + } + + if (hasBadReturnType || hasBadReceiverType || hasBadValueParameter) { + reporter.reportOn( + declaration.source, + FirErrors.UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION, + symbol, context, + ) + } + } + } +}
diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt index 02f24aa..0409bbc 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt
@@ -608,6 +608,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_CONTEXTUAL_DECLARATION_CALL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_FEATURE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_SUSPEND_TEST +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNUSED_VARIABLE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_VIOLATED @@ -820,6 +821,11 @@ map.put(CLASS_INHERITS_JAVA_SEALED_CLASS, "Inheritance of Java sealed classes is prohibited") map.put(SUPERTYPE_NOT_A_CLASS_OR_INTERFACE, "Supertype is not a class or interface", TO_STRING) + map.put( + UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION, + "Inheritance of a Java member referencing 'kotlin.jvm.functions.FunctionN': {0} is unsupported", + TO_STRING, + ) map.put(CYCLIC_INHERITANCE_HIERARCHY, "There's a cycle in the inheritance hierarchy for this type") map.put( EXPANDED_TYPE_CANNOT_BE_INHERITED,
diff --git a/compiler/testData/diagnostics/testsWithStdLib/java/inheritedFunctionN.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/java/inheritedFunctionN.fir.kt index 8ca9068..e2037b1 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/java/inheritedFunctionN.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/java/inheritedFunctionN.fir.kt
@@ -1,4 +1,3 @@ - // FILE: A.java import kotlin.jvm.functions.FunctionN; @@ -7,10 +6,16 @@ public void foo(FunctionN<?> w) { } } +public class A2 { + public FunctionN<?> foo() { } +} + // FILE: main.kt -class B : A() +<!UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION!>class B<!> : A() +<!UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION!>class B2<!> : A2() fun foo() { - object : A() {} + <!UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION!>object<!> : A() {} + <!UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION!>object<!> : A2() {} }
diff --git a/compiler/testData/diagnostics/testsWithStdLib/java/inheritedFunctionN.kt b/compiler/testData/diagnostics/testsWithStdLib/java/inheritedFunctionN.kt index cceafb9..793a64c 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/java/inheritedFunctionN.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/java/inheritedFunctionN.kt
@@ -1,4 +1,3 @@ - // FILE: A.java import kotlin.jvm.functions.FunctionN; @@ -7,10 +6,16 @@ public void foo(FunctionN<?> w) { } } +public class A2 { + public FunctionN<?> foo() { } +} + // FILE: main.kt class <!UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION!>B<!> : A() +class <!UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION!>B2<!> : A2() fun foo() { <!UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION!>object<!> : A() {} + <!UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION!>object<!> : A2() {} }
diff --git a/compiler/testData/diagnostics/testsWithStdLib/java/inheritedFunctionN.txt b/compiler/testData/diagnostics/testsWithStdLib/java/inheritedFunctionN.txt deleted file mode 100644 index b07070c..0000000 --- a/compiler/testData/diagnostics/testsWithStdLib/java/inheritedFunctionN.txt +++ /dev/null
@@ -1,19 +0,0 @@ -package - -public fun foo(): kotlin.Unit - -public open class A { - public constructor A() - public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean - public open fun foo(/*0*/ w: kotlin.jvm.functions.FunctionN<*>!): kotlin.Unit - public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int - public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String -} - -public final class B : A { - public constructor B() - public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean - public open override /*1*/ /*fake_override*/ fun foo(/*0*/ w: kotlin.jvm.functions.FunctionN<*>!): kotlin.Unit - public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int - public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String -}
diff --git a/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt b/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt index 223517c..bb492ed 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt
@@ -14,6 +14,7 @@ val BASE_RANGES_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("ranges")) val BASE_JVM_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("jvm")) val BASE_JVM_INTERNAL_PACKAGE = BASE_JVM_PACKAGE.child(Name.identifier("internal")) + val BASE_JVM_FUNCTIONS_PACKAGE = BASE_JVM_PACKAGE.child(Name.identifier("functions")) val BASE_ANNOTATION_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("annotation")) val BASE_INTERNAL_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("internal")) val BASE_INTERNAL_IR_PACKAGE = BASE_INTERNAL_PACKAGE.child(Name.identifier("ir")) @@ -183,6 +184,8 @@ val FlexibleMutability = "FlexibleMutability".internalIrId() val EnhancedNullability = "EnhancedNullability".jvmInternalId() + val FunctionN = "FunctionN".jvmFunctionsId() + val InlineOnly = "InlineOnly".internalId() val OnlyInputTypes = "OnlyInputTypes".internalId() @@ -265,6 +268,7 @@ private fun String.annotationId() = ClassId(StandardClassIds.BASE_ANNOTATION_PACKAGE, Name.identifier(this)) private fun String.jvmId() = ClassId(StandardClassIds.BASE_JVM_PACKAGE, Name.identifier(this)) private fun String.jvmInternalId() = ClassId(StandardClassIds.BASE_JVM_INTERNAL_PACKAGE, Name.identifier(this)) +private fun String.jvmFunctionsId() = ClassId(StandardClassIds.BASE_JVM_FUNCTIONS_PACKAGE, Name.identifier(this)) private fun String.internalId() = ClassId(StandardClassIds.BASE_INTERNAL_PACKAGE, Name.identifier(this)) private fun String.internalIrId() = ClassId(StandardClassIds.BASE_INTERNAL_IR_PACKAGE, Name.identifier(this)) private fun String.coroutinesId() = ClassId(StandardClassIds.BASE_COROUTINES_PACKAGE, Name.identifier(this))