[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:
committed by
Space Team
parent
bb812add14
commit
a19994b8b6
+1
-1
@@ -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 {
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user