diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticData.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticData.kt index b2d10a309a6..0687df22a5f 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticData.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticData.kt @@ -61,6 +61,7 @@ enum class PositioningStrategy(private val strategy: String? = null) { INT_LITERAL_OUT_OF_RANGE, FLOAT_LITERAL_OUT_OF_RANGE, LONG_LITERAL_SUFFIX, + REIFIED_MODIFIER, ; 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 0239c403538..da86f3e6a21 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 @@ -320,7 +320,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() { val BOUND_ON_TYPE_ALIAS_PARAMETER_NOT_ALLOWED by error() - val REIFIED_TYPE_PARAMETER_NO_INLINE by error() + val REIFIED_TYPE_PARAMETER_NO_INLINE by error(PositioningStrategy.REIFIED_MODIFIER) val TYPE_PARAMETERS_NOT_ALLOWED by error() @@ -336,6 +336,8 @@ object DIAGNOSTICS_LIST : DiagnosticList() { val DEPRECATED_TYPE_PARAMETER_SYNTAX by error() val MISPLACED_TYPE_PARAMETER_CONSTRAINTS by warning() + + val DYNAMIC_UPPER_BOUND by error() } val REFLECTION by object : DiagnosticGroup("Reflection") { 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 12e3642a6de..79aa53f0ead 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 @@ -236,13 +236,14 @@ object FirErrors { val CONFLICTING_UPPER_BOUNDS by error1() 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 REIFIED_TYPE_PARAMETER_NO_INLINE by error0(SourceElementPositioningStrategies.REIFIED_MODIFIER) val TYPE_PARAMETERS_NOT_ALLOWED by error0() val TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER by error0() val RETURN_TYPE_MISMATCH by error2(SourceElementPositioningStrategies.WHOLE_ELEMENT) val CYCLIC_GENERIC_UPPER_BOUND by error0() val DEPRECATED_TYPE_PARAMETER_SYNTAX by error0() val MISPLACED_TYPE_PARAMETER_CONSTRAINTS by warning0() + val DYNAMIC_UPPER_BOUND by error0() // Reflection val EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED by error1>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirFunctionTypeParametersChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirFunctionTypeParametersChecker.kt index bed36d194cb..9f4264fba67 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirFunctionTypeParametersChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirFunctionTypeParametersChecker.kt @@ -5,7 +5,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration -import org.jetbrains.kotlin.fir.FirFakeSourceElement +import org.jetbrains.kotlin.fir.FirFakeSourceElementKind import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.diagnostics.* import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction @@ -15,7 +15,7 @@ object FirFunctionTypeParametersChecker : FirSimpleFunctionChecker() { override fun check(declaration: FirSimpleFunction, context: CheckerContext, reporter: DiagnosticReporter) { declaration.source?.let { source -> - if (source is FirFakeSourceElement<*>) return + if (source.kind is FirFakeSourceElementKind) return val typeParamsNode = source.treeStructure.typeParametersList(source.lighterASTNode) val nameNode = source.treeStructure.nameIdentifier(source.lighterASTNode) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirReifiedTypeParameterChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirReifiedTypeParameterChecker.kt index 6b587292bc8..321efdd3dec 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirReifiedTypeParameterChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirReifiedTypeParameterChecker.kt @@ -10,7 +10,6 @@ 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.declarations.* -import org.jetbrains.kotlin.lexer.KtTokens object FirReifiedTypeParameterChecker : FirTypeParameterChecker() { override fun check(declaration: FirTypeParameter, context: CheckerContext, reporter: DiagnosticReporter) { @@ -22,8 +21,7 @@ object FirReifiedTypeParameterChecker : FirTypeParameterChecker() { (containingDeclaration is FirProperty && !containingDeclaration.areAccessorsInline()) if (forbidReified) { - val reportTarget = declaration.getModifier(KtTokens.REIFIED_KEYWORD)?.source - reporter.reportOn(reportTarget, FirErrors.REIFIED_TYPE_PARAMETER_NO_INLINE, context) + reporter.reportOn(declaration.source, FirErrors.REIFIED_TYPE_PARAMETER_NO_INLINE, context) } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTypeParameterBoundsChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTypeParameterBoundsChecker.kt index 529d4ce9605..333e538fcc7 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTypeParameterBoundsChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTypeParameterBoundsChecker.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.* 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.getAncestors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.typeContext @@ -43,6 +44,7 @@ object FirTypeParameterBoundsChecker : FirTypeParameterChecker() { checkConflictingBounds(declaration, context, reporter) checkTypeAliasBound(declaration, containingDeclaration, context, reporter) checkBoundsPlacement(declaration, context, reporter) + checkDynamicBounds(declaration, context, reporter) } private fun checkFinalUpperBounds( @@ -105,7 +107,9 @@ object FirTypeParameterBoundsChecker : FirTypeParameterChecker() { private fun FirTypeRef.isInTypeConstraint(): Boolean { val source = source ?: return false - return source.treeStructure.getParent(source.lighterASTNode)?.tokenType == KtNodeTypes.TYPE_CONSTRAINT + return source.treeStructure.getAncestors(source.lighterASTNode) + .find { it.tokenType == KtNodeTypes.TYPE_CONSTRAINT || it.tokenType == KtNodeTypes.TYPE_PARAMETER } + ?.tokenType == KtNodeTypes.TYPE_CONSTRAINT } @@ -148,6 +152,7 @@ object FirTypeParameterBoundsChecker : FirTypeParameterChecker() { } } + //TODO should be moved to extended checkers (because this is basically a code-style warning) private fun checkBoundsPlacement(declaration: FirTypeParameter, context: CheckerContext, reporter: DiagnosticReporter) { if (declaration.bounds.size < 2) return @@ -157,6 +162,14 @@ object FirTypeParameterBoundsChecker : FirTypeParameterChecker() { } } + private fun checkDynamicBounds(declaration: FirTypeParameter, context: CheckerContext, reporter: DiagnosticReporter) { + declaration.bounds.forEach { bound -> + if (bound is FirDynamicTypeRef) { + reporter.reportOn(bound.source, FirErrors.DYNAMIC_UPPER_BOUND, context) + } + } + } + private fun KotlinTypeMarker.isRelated(context: TypeCheckerProviderContext, type: KotlinTypeMarker?): Boolean = isSubtypeOf(context, type) || isSupertypeOf(context, type) 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 0c83cfdcdaa..bc58da7a650 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 @@ -34,14 +34,13 @@ object FirAnonymousFunctionChecker : FirExpressionChecker() { 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 - ) - } + val source = expression.source ?: return + 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/collectors/AbstractDiagnosticCollector.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollector.kt index 2d26cb9f1ce..89aeb54158f 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollector.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollector.kt @@ -92,7 +92,7 @@ abstract class AbstractDiagnosticCollector( } } - override fun visitTypeAlias(typeAlias: FirTypeAlias, data: Nothing?) { + override fun visitTypeAlias(typeAlias: FirTypeAlias, data: Any?) { withSuppressedDiagnostics(typeAlias) { visitWithDeclaration(typeAlias) } 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 204c18f72fb..c4678d2e108 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 @@ -81,6 +81,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATION_SUPER_ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATED_MODIFIER_PAIR import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATED_TYPE_PARAMETER_SYNTAX import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DESERIALIZATION_ERROR +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DYNAMIC_UPPER_BOUND import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EMPTY_RANGE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ENUM_AS_SUPERTYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ERROR_FROM_JAVA_RESOLUTION @@ -521,6 +522,8 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { "If a type parameter has multiple constraints, they all need to be placed in the 'where' clause" ) + map.put(DYNAMIC_UPPER_BOUND, "Dynamic type can not be used as an upper bound") + // Reflection map.put( EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED, 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 e29f2e9cbd3..7102e86bb72 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 @@ -542,6 +542,9 @@ object LightTreePositioningStrategies { val LONG_LITERAL_SUFFIX = object : LightTreePositioningStrategy() { } + + val REIFIED_MODIFIER: LightTreePositioningStrategy = + ModifierSetBasedLightTreePositioningStrategy(TokenSet.create(KtTokens.REIFIED_KEYWORD)) } fun FirSourceElement.hasValOrVar(): Boolean = @@ -736,6 +739,9 @@ private fun FlyweightCapableTreeStructure.findParentOfType( return null } +internal fun FlyweightCapableTreeStructure.getAncestors(node: LighterASTNode): Sequence = + generateSequence(getParent(node)) { getParent(it) } + private fun FlyweightCapableTreeStructure.firstChild(node: LighterASTNode): LighterASTNode? { val childrenRef = Ref>() getChildren(node, childrenRef) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt index 16369d20bb0..9ae921f3584 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt @@ -192,4 +192,9 @@ object SourceElementPositioningStrategies { LightTreePositioningStrategies.LONG_LITERAL_SUFFIX, PositioningStrategies.LONG_LITERAL_SUFFIX ) + + val REIFIED_MODIFIER = SourceElementPositioningStrategy( + LightTreePositioningStrategies.REIFIED_MODIFIER, + PositioningStrategies.REIFIED_MODIFIER + ) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index 4e920d6b5d0..21ae87d4a4a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -780,6 +780,8 @@ object PositioningStrategies { val REFERENCE_BY_QUALIFIED: PositioningStrategy = FindReferencePositioningStrategy(false) val REFERENCED_NAME_BY_QUALIFIED: PositioningStrategy = FindReferencePositioningStrategy(true) + val REIFIED_MODIFIER: PositioningStrategy = modifierSetPosition(KtTokens.REIFIED_KEYWORD) + val ASSIGNMENT_VALUE: PositioningStrategy = object : PositioningStrategy() { override fun mark(element: PsiElement): List { return markElement(if (element is KtProperty) element.initializer ?: element else element) 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 589fea742ca..32a54c12bc9 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 @@ -1036,6 +1036,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.DYNAMIC_UPPER_BOUND) { firDiagnostic -> + DynamicUpperBoundImpl( + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } add(FirErrors.EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED) { firDiagnostic -> ExtensionInClassReferenceNotAllowedImpl( firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.a as FirCallableDeclaration), 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 ab503de0f16..c3951071c4f 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 @@ -705,7 +705,7 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = BoundOnTypeAliasParameterNotAllowed::class } - abstract class ReifiedTypeParameterNoInline : KtFirDiagnostic() { + abstract class ReifiedTypeParameterNoInline : KtFirDiagnostic() { override val diagnosticClass get() = ReifiedTypeParameterNoInline::class } @@ -735,6 +735,10 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = MisplacedTypeParameterConstraints::class } + abstract class DynamicUpperBound : KtFirDiagnostic() { + override val diagnosticClass get() = DynamicUpperBound::class + } + abstract class ExtensionInClassReferenceNotAllowed : KtFirDiagnostic() { override val diagnosticClass get() = ExtensionInClassReferenceNotAllowed::class abstract val referencedDeclaration: KtCallableSymbol 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 37db64d9847..04ca5ab16ad 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 @@ -1141,7 +1141,7 @@ internal class BoundOnTypeAliasParameterNotAllowedImpl( internal class ReifiedTypeParameterNoInlineImpl( firDiagnostic: FirPsiDiagnostic<*>, override val token: ValidityToken, -) : KtFirDiagnostic.ReifiedTypeParameterNoInline(), KtAbstractFirDiagnostic { +) : KtFirDiagnostic.ReifiedTypeParameterNoInline(), KtAbstractFirDiagnostic { override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } @@ -1189,6 +1189,13 @@ internal class MisplacedTypeParameterConstraintsImpl( override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } +internal class DynamicUpperBoundImpl( + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.DynamicUpperBound(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + internal class ExtensionInClassReferenceNotAllowedImpl( override val referencedDeclaration: KtCallableSymbol, firDiagnostic: FirPsiDiagnostic<*>,