From 470993ac07a9de24e868a38377548d0ed9a05c02 Mon Sep 17 00:00:00 2001 From: Andrey Zinovyev Date: Mon, 12 Apr 2021 11:18:14 +0300 Subject: [PATCH] [FIR] Add TYPE_PARAMETERS_NOT_ALLOWED check --- .../diagnostics/FirDiagnosticsList.kt | 2 ++ .../fir/analysis/diagnostics/FirErrors.kt | 1 + .../expression/FirAnonymousFunctionChecker.kt | 23 ++++++++++++++++--- .../diagnostics/FirDefaultErrorMessages.kt | 9 ++++++++ .../LightTreePositioningStrategies.kt | 3 +++ .../WithGenericParameters.fir.kt | 16 ++++++------- .../diagnostics/KtFirDataClassConverters.kt | 6 +++++ .../api/fir/diagnostics/KtFirDiagnostics.kt | 4 ++++ .../fir/diagnostics/KtFirDiagnosticsImpl.kt | 7 ++++++ 9 files changed, 60 insertions(+), 11 deletions(-) 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 8061fa16ab8..b06f114faf6 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 @@ -322,6 +322,8 @@ object DIAGNOSTICS_LIST : DiagnosticList() { val REIFIED_TYPE_PARAMETER_NO_INLINE by error() + val TYPE_PARAMETERS_NOT_ALLOWED by error() + val RETURN_TYPE_MISMATCH by error(PositioningStrategy.WHOLE_ELEMENT) { parameter("expected") parameter("actual") 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 12f975a2449..06393686bd7 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 @@ -237,6 +237,7 @@ object FirErrors { val NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER by error2() val BOUND_ON_TYPE_ALIAS_PARAMETER_NOT_ALLOWED by error0() val REIFIED_TYPE_PARAMETER_NO_INLINE by error0() + val TYPE_PARAMETERS_NOT_ALLOWED by error0() val RETURN_TYPE_MISMATCH by error2(SourceElementPositioningStrategies.WHOLE_ELEMENT) // Reflection diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAnonymousFunctionChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAnonymousFunctionChecker.kt index e054e461d9e..0c83cfdcdaa 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAnonymousFunctionChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAnonymousFunctionChecker.kt @@ -6,11 +6,10 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext -import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter -import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors -import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn +import org.jetbrains.kotlin.fir.analysis.diagnostics.* import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction import org.jetbrains.kotlin.fir.expressions.FirStatement +import org.jetbrains.kotlin.fir.toFirLightSourceElement object FirAnonymousFunctionChecker : FirExpressionChecker() { override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) { @@ -26,5 +25,23 @@ object FirAnonymousFunctionChecker : FirExpressionChecker() { reporter.reportOn(source, FirErrors.USELESS_VARARG_ON_PARAMETER, context) } } + + checkTypeParameters(expression, reporter, context) + } + + private fun checkTypeParameters( + expression: FirStatement, + reporter: DiagnosticReporter, + context: CheckerContext + ) { + expression.source?.let { source -> + source.treeStructure.typeParametersList(source.lighterASTNode)?.let { typeParamsNode -> + reporter.reportOn( + typeParamsNode.toFirLightSourceElement(source.treeStructure), + FirErrors.TYPE_PARAMETERS_NOT_ALLOWED, + context + ) + } + } } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index daec1b7fb01..714705d8277 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -44,6 +44,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ASSIGNED_VALUE_IS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ASSIGN_OPERATOR_AMBIGUITY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.BACKING_FIELD_IN_INTERFACE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.BOUNDS_NOT_ALLOWED_IF_BOUNDED_BY_TYPE_PARAMETER +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.BOUND_ON_TYPE_ALIAS_PARAMETER_NOT_ALLOWED import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.BREAK_OR_CONTINUE_OUTSIDE_A_LOOP import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CALLABLE_REFERENCE_LHS_NOT_A_CLASS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CALLABLE_REFERENCE_TO_ANNOTATION_CONSTRUCTOR @@ -196,6 +197,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_SETTER_ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_VISIBILITY_MODIFIER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REIFIED_TYPE_IN_CATCH_CLAUSE +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REIFIED_TYPE_PARAMETER_NO_INLINE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REPEATED_BOUND import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REPEATED_MODIFIER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RESERVED_MEMBER_INSIDE_INLINE_CLASS @@ -223,6 +225,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_CANT_BE_USED import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_MISMATCH import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETERS_IN_ENUM import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETERS_IN_OBJECT +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETERS_NOT_ALLOWED import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_AS_REIFIED import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_IN_CATCH_CLAUSE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_IS_NOT_AN_EXPRESSION @@ -495,6 +498,12 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { NAME ) + map.put(BOUND_ON_TYPE_ALIAS_PARAMETER_NOT_ALLOWED, "Bounds are not allowed on type alias parameters") + + map.put(REIFIED_TYPE_PARAMETER_NO_INLINE, "Only type parameters of inline functions can be reified") + + map.put(TYPE_PARAMETERS_NOT_ALLOWED, "Type parameters are not allowed here") + map.put(RETURN_TYPE_MISMATCH, "Return type mismatch: expected {0}, actual {1}", RENDER_TYPE, RENDER_TYPE) // Reflection diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt index a04d3e543d9..afcb466c748 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt @@ -630,6 +630,9 @@ internal fun FlyweightCapableTreeStructure.modalityModifier(decl internal fun FlyweightCapableTreeStructure.overrideModifier(declaration: LighterASTNode): LighterASTNode? = modifierList(declaration)?.let { findChildByType(it, KtTokens.OVERRIDE_KEYWORD) } +internal fun FlyweightCapableTreeStructure.typeParametersList(declaration: LighterASTNode): LighterASTNode? = + findChildByType(declaration, KtNodeTypes.TYPE_PARAMETER_LIST) + private fun FlyweightCapableTreeStructure.supertypesList(node: LighterASTNode): LighterASTNode? = findChildByType(node, KtNodeTypes.SUPER_TYPE_LIST) diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/WithGenericParameters.fir.kt b/compiler/testData/diagnostics/tests/functionAsExpression/WithGenericParameters.fir.kt index d6e72349531..022fae99769 100644 --- a/compiler/testData/diagnostics/tests/functionAsExpression/WithGenericParameters.fir.kt +++ b/compiler/testData/diagnostics/tests/functionAsExpression/WithGenericParameters.fir.kt @@ -4,16 +4,16 @@ interface A fun devNull(a: Any?){} -val generic_fun = fun(t: T): T = null!! -val extension_generic_fun = funT.(t: T): T = null!! +val generic_fun = fun(t: T): T = null!! +val extension_generic_fun = funT.(t: T): T = null!! -fun fun_with_where() = fun T.(t: T): T where T: A = null!! +fun fun_with_where() = fun T.(t: T): T where T: A = null!! fun outer() { - devNull(fun () {}) - devNull(fun T.() {}) - devNull(fun (): T = null!!) - devNull(fun (t: T) {}) - devNull(fun () where T:A {}) + devNull(fun () {}) + devNull(fun T.() {}) + devNull(fun (): T = null!!) + devNull(fun (t: T) {}) + devNull(fun () where T:A {}) } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt index 21fd72c76da..3b9b3b422db 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -998,6 +998,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.TYPE_PARAMETERS_NOT_ALLOWED) { firDiagnostic -> + TypeParametersNotAllowedImpl( + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } add(FirErrors.RETURN_TYPE_MISMATCH) { firDiagnostic -> ReturnTypeMismatchImpl( firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a), diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt index 28c7b0f8779..ffbd5b2ff4a 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt @@ -709,6 +709,10 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = ReifiedTypeParameterNoInline::class } + abstract class TypeParametersNotAllowed : KtFirDiagnostic() { + override val diagnosticClass get() = TypeParametersNotAllowed::class + } + abstract class ReturnTypeMismatch : KtFirDiagnostic() { override val diagnosticClass get() = ReturnTypeMismatch::class abstract val expected: KtType diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 514d7059c1c..5c27c82301c 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -1145,6 +1145,13 @@ internal class ReifiedTypeParameterNoInlineImpl( override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } +internal class TypeParametersNotAllowedImpl( + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.TypeParametersNotAllowed(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + internal class ReturnTypeMismatchImpl( override val expected: KtType, override val actual: KtType,