diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSupertypesChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSupertypesChecker.kt index bd9e8fc3741..8a769cf526c 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSupertypesChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSupertypesChecker.kt @@ -5,30 +5,33 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration -import org.jetbrains.kotlin.KtFakeSourceElementKind +import com.intellij.psi.impl.source.tree.ElementType +import org.jetbrains.kotlin.* import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.FirFunctionTypeParameter import org.jetbrains.kotlin.fir.analysis.checkers.* import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.declarations.FirClass import org.jetbrains.kotlin.fir.declarations.FirField import org.jetbrains.kotlin.fir.declarations.FirRegularClass -import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass import org.jetbrains.kotlin.fir.declarations.utils.modality import org.jetbrains.kotlin.fir.declarations.utils.visibility import org.jetbrains.kotlin.fir.languageVersionSettings import org.jetbrains.kotlin.fir.resolve.fullyExpandedType -import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.lexer.KtToken +import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.StandardClassIds +import org.jetbrains.kotlin.util.getChildren object FirSupertypesChecker : FirClassChecker() { override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) { @@ -89,6 +92,7 @@ object FirSupertypesChecker : FirClassChecker() { } checkClassCannotBeExtendedDirectly(symbol, reporter, superTypeRef, context) + checkNamedFunctionTypeParameter(superTypeRef, context, reporter) if (coneType.typeArguments.isNotEmpty()) { checkProjectionInImmediateArgumentToSupertype(coneType, superTypeRef, reporter, context) @@ -107,7 +111,7 @@ object FirSupertypesChecker : FirClassChecker() { private fun checkAnnotationOnSuperclass( superTypeRef: FirTypeRef, context: CheckerContext, - reporter: DiagnosticReporter + reporter: DiagnosticReporter, ) { for (annotation in superTypeRef.annotations) { if (annotation.useSiteTarget != null) { @@ -120,7 +124,7 @@ object FirSupertypesChecker : FirClassChecker() { symbol: FirClassifierSymbol<*>?, reporter: DiagnosticReporter, superTypeRef: FirTypeRef, - context: CheckerContext + context: CheckerContext, ) { if (symbol is FirRegularClassSymbol && symbol.classId == StandardClassIds.Enum) { reporter.reportOn(superTypeRef.source, FirErrors.CLASS_CANNOT_BE_EXTENDED_DIRECTLY, symbol, context) @@ -131,7 +135,7 @@ object FirSupertypesChecker : FirClassChecker() { coneType: ConeKotlinType, superTypeRef: FirTypeRef, reporter: DiagnosticReporter, - context: CheckerContext + context: CheckerContext, ) { val typeRefAndSourcesForArguments = extractArgumentsTypeRefAndSource(superTypeRef) ?: return for ((index, typeArgument) in coneType.typeArguments.withIndex()) { @@ -152,7 +156,7 @@ object FirSupertypesChecker : FirClassChecker() { reporter: DiagnosticReporter, superTypeRef: FirTypeRef, coneType: ConeKotlinType, - context: CheckerContext + context: CheckerContext, ) { if (symbol is FirRegularClassSymbol && symbol.classKind == ClassKind.INTERFACE) { for (typeArgument in fullyExpandedType.typeArguments) { @@ -167,7 +171,7 @@ object FirSupertypesChecker : FirClassChecker() { private fun checkDelegationNotToInterface( declaration: FirClass, context: CheckerContext, - reporter: DiagnosticReporter + reporter: DiagnosticReporter, ) { for (subDeclaration in declaration.declarations) { if (subDeclaration is FirField) { @@ -180,4 +184,39 @@ object FirSupertypesChecker : FirClassChecker() { } } } + + private fun checkNamedFunctionTypeParameter( + superTypeRef: FirTypeRef, + context: CheckerContext, + reporter: DiagnosticReporter, + ) { + val delegatedTypeRef = (superTypeRef as? FirResolvedTypeRef)?.delegatedTypeRef ?: return + if (delegatedTypeRef !is FirFunctionTypeRef) return + for (parameter in delegatedTypeRef.parameters) { + if (parameter.name != null) { + val source = parameter.findSourceForParameterName() ?: continue + reporter.reportOn( + source, + FirErrors.UNSUPPORTED, + "named parameter in function type in supertype position", + context + ) + } + } + } + + private fun FirFunctionTypeParameter.findSourceForParameterName(): KtSourceElement? { + val source = this.source ?: return null + val name = this.name ?: return null + val treeStructure = source.treeStructure + val nodes = source.lighterASTNode.getChildren(treeStructure) + val node = nodes.find { it.tokenType == KtTokens.IDENTIFIER && treeStructure.toString(it) == name.identifier } ?: return null + + return node.toKtLightSourceElement( + treeStructure, + startOffset = node.startOffset, + endOffset = node.endOffset + ) + } + } diff --git a/compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.fir.kt b/compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.fir.kt deleted file mode 100644 index 76b787ffc75..00000000000 --- a/compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.fir.kt +++ /dev/null @@ -1,9 +0,0 @@ -abstract class A : Function1 - -abstract class B : (Int)->Unit - -// Named parameter is prohibited because of possible inconsistency between -// type declaration and actual override -class C : (x: Int)->Unit { - override fun invoke(p1: Int): Unit {} -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.kt b/compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.kt index c9567ff0765..99fa65d2186 100644 --- a/compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.kt +++ b/compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL abstract class A : Function1 abstract class B : (Int)->Unit @@ -6,4 +7,14 @@ abstract class B : (Int)->Unit // type declaration and actual override class C : (x: Int)->Unit { override fun invoke(p1: Int): Unit {} -} \ No newline at end of file +} + +class D : (Int: Int)->Unit { + override fun invoke(p1: Int): Unit {} +} + + +class E : ((k: String) -> Unit) -> Unit { + override fun invoke(p1: (k: String) -> Unit) { + } +} diff --git a/compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.txt b/compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.txt index 98fa86d4a6b..8ce2104d62b 100644 --- a/compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.txt +++ b/compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.txt @@ -23,3 +23,20 @@ public final class C : (x: kotlin.Int) -> kotlin.Unit { public open override /*1*/ fun invoke(/*0*/ p1: kotlin.Int): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } + +public final class D : (Int: kotlin.Int) -> kotlin.Unit { + public constructor D() + 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): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class E : ((k: kotlin.String) -> kotlin.Unit) -> kotlin.Unit { + public constructor E() + 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: (k: kotlin.String) -> kotlin.Unit): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + diff --git a/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/funcitonTypes.fir.kt b/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/funcitonTypes.fir.kt deleted file mode 100644 index 36c7d2ced15..00000000000 --- a/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/funcitonTypes.fir.kt +++ /dev/null @@ -1 +0,0 @@ -class A : (categoryName: ) { \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/funcitonTypes.kt b/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/funcitonTypes.kt index 09f9ebd4fff..0909922235b 100644 --- a/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/funcitonTypes.kt +++ b/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/funcitonTypes.kt @@ -1 +1,2 @@ +// FIR_IDENTICAL class A : (categoryName: ) { \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/typeReferenceError.fir.kt b/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/typeReferenceError.fir.kt deleted file mode 100644 index cc8d10e7646..00000000000 --- a/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/typeReferenceError.fir.kt +++ /dev/null @@ -1,3 +0,0 @@ -package typeReferenceError - -class Pair<:(val c: fun main() diff --git a/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/typeReferenceError.kt b/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/typeReferenceError.kt index 4a34a35d2ee..97b188f4873 100644 --- a/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/typeReferenceError.kt +++ b/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/typeReferenceError.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL package typeReferenceError class Pair<:(val c: fun main()