FIR: Do not leave cyclic upper bounds of type parameters

This commit is contained in:
Denis Zharkov
2020-07-30 15:37:23 +03:00
parent a5a93d00a7
commit 8b71f5e558
5 changed files with 44 additions and 9 deletions
@@ -12,8 +12,7 @@ import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.createImportingScopes import org.jetbrains.kotlin.fir.scopes.createImportingScopes
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.compose import org.jetbrains.kotlin.fir.visitors.compose
@@ -60,6 +59,7 @@ class FirTypeResolveTransformer(
regularClass.typeParameters.forEach { regularClass.typeParameters.forEach {
it.accept(this, data) it.accept(this, data)
} }
unboundCyclesInTypeParametersSupertypes(regularClass)
} }
return resolveNestedClassesSupertypes(regularClass, data) return resolveNestedClassesSupertypes(regularClass, data)
@@ -101,6 +101,9 @@ class FirTypeResolveTransformer(
property.getter?.transformReturnTypeRef(StoreType, property.returnTypeRef) property.getter?.transformReturnTypeRef(StoreType, property.returnTypeRef)
property.setter?.valueParameters?.map { it.transformReturnTypeRef(StoreType, property.returnTypeRef) } property.setter?.valueParameters?.map { it.transformReturnTypeRef(StoreType, property.returnTypeRef) }
} }
unboundCyclesInTypeParametersSupertypes(property)
property.compose() property.compose()
} }
} }
@@ -108,7 +111,36 @@ class FirTypeResolveTransformer(
override fun transformSimpleFunction(simpleFunction: FirSimpleFunction, data: Nothing?): CompositeTransformResult<FirDeclaration> { override fun transformSimpleFunction(simpleFunction: FirSimpleFunction, data: Nothing?): CompositeTransformResult<FirDeclaration> {
return withScopeCleanup { return withScopeCleanup {
simpleFunction.addTypeParametersScope() simpleFunction.addTypeParametersScope()
transformDeclaration(simpleFunction, data) transformDeclaration(simpleFunction, data).also {
unboundCyclesInTypeParametersSupertypes(it.single as FirTypeParametersOwner)
}
}
}
private fun unboundCyclesInTypeParametersSupertypes(typeParametersOwner: FirTypeParameterRefsOwner) {
for (typeParameter in typeParametersOwner.typeParameters) {
if (typeParameter !is FirTypeParameter) continue
if (hasSupertypePathToParameter(typeParameter, typeParameter, mutableSetOf())) {
// TODO: Report diagnostic somewhere
typeParameter.replaceBounds(
listOf(session.builtinTypes.nullableAnyType)
)
}
}
}
private fun hasSupertypePathToParameter(
currentTypeParameter: FirTypeParameter,
typeParameter: FirTypeParameter,
visited: MutableSet<FirTypeParameter>
): Boolean {
if (visited.isNotEmpty() && currentTypeParameter == typeParameter) return true
if (!visited.add(currentTypeParameter)) return false
return currentTypeParameter.bounds.any {
val nextTypeParameter = it.coneTypeSafe<ConeTypeParameterType>()?.lookupTag?.typeParameterSymbol?.fir ?: return@any false
hasSupertypePathToParameter(nextTypeParameter, typeParameter, visited)
} }
} }
@@ -44,11 +44,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
override fun SimpleTypeMarker.fastCorrespondingSupertypes(constructor: TypeConstructorMarker): List<SimpleTypeMarker>? { override fun SimpleTypeMarker.fastCorrespondingSupertypes(constructor: TypeConstructorMarker): List<SimpleTypeMarker>? {
require(this is ConeKotlinType) require(this is ConeKotlinType)
return if (this is ConeIntegerLiteralType) { return session.correspondingSupertypesCache.getCorrespondingSupertypes(this, constructor)
supertypes.filter { isEqualTypeConstructors(constructor, it.typeConstructor()) }
} else {
session.correspondingSupertypesCache.getCorrespondingSupertypes(this, constructor)
}
} }
override fun SimpleTypeMarker.isIntegerLiteralType(): Boolean { override fun SimpleTypeMarker.isIntegerLiteralType(): Boolean {
@@ -38,5 +38,7 @@ abstract class FirTypeParameter : FirPureAbstractElement(), FirTypeParameterRef,
abstract override fun replaceResolvePhase(newResolvePhase: FirResolvePhase) abstract override fun replaceResolvePhase(newResolvePhase: FirResolvePhase)
abstract fun replaceBounds(newBounds: List<FirTypeRef>)
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirTypeParameter abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirTypeParameter
} }
@@ -60,4 +60,9 @@ internal class FirTypeParameterImpl(
override fun replaceResolvePhase(newResolvePhase: FirResolvePhase) { override fun replaceResolvePhase(newResolvePhase: FirResolvePhase) {
resolvePhase = newResolvePhase resolvePhase = newResolvePhase
} }
override fun replaceBounds(newBounds: List<FirTypeRef>) {
bounds.clear()
bounds.addAll(newBounds)
}
} }
@@ -291,7 +291,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
+symbol("FirTypeParameterSymbol") +symbol("FirTypeParameterSymbol")
+field(varianceType) +field(varianceType)
+booleanField("isReified") +booleanField("isReified")
+fieldList("bounds", typeRef) +fieldList("bounds", typeRef, withReplace = true)
+annotations +annotations
} }