diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirCastDiagnosticsHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirCastDiagnosticsHelpers.kt index 1cfd7c64d9d..f7523283a99 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirCastDiagnosticsHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirCastDiagnosticsHelpers.kt @@ -135,7 +135,7 @@ private fun getCorrespondingKotlinClass(type: ConeSimpleKotlinType, session: Fir } private fun isFinal(type: ConeSimpleKotlinType, session: FirSession): Boolean { - return !type.canHaveSubtypes(session) + return !type.canHaveSubtypesAccordingToK1(session) } fun isCastErased(supertype: ConeKotlinType, subtype: ConeKotlinType, context: CheckerContext): Boolean { 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 a86b8f95dc3..c50aab26413 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 @@ -75,7 +75,7 @@ sealed class FirTypeParameterBoundsChecker(mppKind: MppCheckerKind) : FirTypePar if (containingDeclaration is FirProperty && containingDeclaration.isOverride) return declaration.symbol.resolvedBounds.forEach { bound -> - if (!bound.coneType.canHaveSubtypes(context.session)) { + if (!bound.coneType.canHaveSubtypesAccordingToK1(context.session)) { reporter.reportOn(bound.source, FirErrors.FINAL_UPPER_BOUND, bound.coneType, context) } } @@ -148,7 +148,7 @@ sealed class FirTypeParameterBoundsChecker(mppKind: MppCheckerKind) : FirTypePar fun anyConflictingTypes(types: List): Boolean { types.forEach { type -> - if (!type.canHaveSubtypes(context.session)) { + if (!type.canHaveSubtypesAccordingToK1(context.session)) { types.forEach { otherType -> if (type != otherType && !type.isRelated(context.session.typeContext, otherType)) { return true diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirEqualityCompatibilityChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirEqualityCompatibilityChecker.kt index 2c4949004f2..27184d3860a 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirEqualityCompatibilityChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirEqualityCompatibilityChecker.kt @@ -333,7 +333,7 @@ private fun ConeKotlinType.toTypeInfo(session: FirSession): TypeInfo { isValueClass = bounds.any { it.toClassSymbol(session)?.isInline == true }, isFinal = bounds.any { it.toClassSymbol(session)?.isFinalClass == true }, // In K1's intersector, `canHaveSubtypes()` is called for `nullabilityStripped`. - withNullability(ConeNullability.NOT_NULL, session.typeContext).canHaveSubtypes(session), + withNullability(ConeNullability.NOT_NULL, session.typeContext).canHaveSubtypesAccordingToK1(session), ) } diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt index 057d060130f..85e0247f871 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt @@ -584,10 +584,13 @@ fun FirCallableDeclaration.isSubtypeOf( ) } +fun ConeKotlinType.canHaveSubtypesAccordingToK1(session: FirSession): Boolean = + hasSubtypesAboveNothingAccordingToK1(session) + /** * The original K1 function: [org.jetbrains.kotlin.types.TypeUtils.canHaveSubtypes]. */ -fun ConeKotlinType.canHaveSubtypes(session: FirSession): Boolean { +private fun ConeKotlinType.hasSubtypesAboveNothingAccordingToK1(session: FirSession): Boolean { if (this.isMarkedNullable) { return true } @@ -608,12 +611,13 @@ fun ConeKotlinType.canHaveSubtypes(session: FirSession): Boolean { val argument = typeProjection.type!! //safe because it is not a star val canHaveSubtypes = when (typeProjection.variance) { - Variance.OUT_VARIANCE -> argument.canHaveSubtypes(session) - Variance.IN_VARIANCE -> argument.lowerThanBound(typeParameterSymbol, session) + Variance.OUT_VARIANCE -> argument.hasSubtypesAboveNothingAccordingToK1(session) + Variance.IN_VARIANCE -> argument.hasSupertypesBelowParameterBoundsAccordingToK1(typeParameterSymbol, session) Variance.INVARIANT -> when (typeParameterSymbol.variance) { - Variance.OUT_VARIANCE -> argument.canHaveSubtypes(session) - Variance.IN_VARIANCE -> argument.lowerThanBound(typeParameterSymbol, session) - Variance.INVARIANT -> argument.canHaveSubtypes(session) || argument.lowerThanBound(typeParameterSymbol, session) + Variance.OUT_VARIANCE -> argument.hasSubtypesAboveNothingAccordingToK1(session) + Variance.IN_VARIANCE -> argument.hasSupertypesBelowParameterBoundsAccordingToK1(typeParameterSymbol, session) + Variance.INVARIANT -> argument.hasSubtypesAboveNothingAccordingToK1(session) + || argument.hasSupertypesBelowParameterBoundsAccordingToK1(typeParameterSymbol, session) } } @@ -646,7 +650,10 @@ fun ConeClassLikeType.toClassSymbol(session: FirSession): FirClassSymbol<*>? { * This function returns `true` if `argument` suits any bound rather than the * intersection of them all, and it expects there to be at least a single bound. */ -private fun ConeKotlinType.lowerThanBound(typeParameterSymbol: FirTypeParameterSymbol, session: FirSession): Boolean { +private fun ConeKotlinType.hasSupertypesBelowParameterBoundsAccordingToK1( + typeParameterSymbol: FirTypeParameterSymbol, + session: FirSession, +): Boolean { typeParameterSymbol.resolvedBounds.forEach { boundTypeRef -> if (this != boundTypeRef.coneType && isSubtypeOf(session.typeContext, boundTypeRef.coneType)) { return true