[FIR] Rename canHaveSubtypes() and lowerThanBound() in K2

`lowerThanBound()` was renamed to:

- draw attention to its corner cases
- make its single usage less cryptic

We may want to reserve the pretty name for
a function that, for example, returns `true`
if `argument` suits all the bounds.

Similarly, `canHaveSubtypes()`
does some questionable logic in case of
`INVARIANTxINVARIANT`: some hypothetical
`Inv<Foo>` doesn't have subtypes so
checking "Foo has subtypes strictly above
Nothing || Foo has supertypes strictly below
the parameter bounds" doesn't seem correct.
`Foo` may have some, but `Inv<them>` are
not related to `Inv<Foo>`.
This commit is contained in:
Nikolay Lunyak
2024-02-26 15:08:48 +02:00
committed by Space Team
parent bb812add14
commit a19994b8b6
4 changed files with 18 additions and 11 deletions
@@ -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 {
@@ -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<ConeKotlinType>): 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
@@ -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),
)
}
@@ -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