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.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.createImportingScopes
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.compose
@@ -60,6 +59,7 @@ class FirTypeResolveTransformer(
regularClass.typeParameters.forEach {
it.accept(this, data)
}
unboundCyclesInTypeParametersSupertypes(regularClass)
}
return resolveNestedClassesSupertypes(regularClass, data)
@@ -101,6 +101,9 @@ class FirTypeResolveTransformer(
property.getter?.transformReturnTypeRef(StoreType, property.returnTypeRef)
property.setter?.valueParameters?.map { it.transformReturnTypeRef(StoreType, property.returnTypeRef) }
}
unboundCyclesInTypeParametersSupertypes(property)
property.compose()
}
}
@@ -108,7 +111,36 @@ class FirTypeResolveTransformer(
override fun transformSimpleFunction(simpleFunction: FirSimpleFunction, data: Nothing?): CompositeTransformResult<FirDeclaration> {
return withScopeCleanup {
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>? {
require(this is ConeKotlinType)
return if (this is ConeIntegerLiteralType) {
supertypes.filter { isEqualTypeConstructors(constructor, it.typeConstructor()) }
} else {
session.correspondingSupertypesCache.getCorrespondingSupertypes(this, constructor)
}
return session.correspondingSupertypesCache.getCorrespondingSupertypes(this, constructor)
}
override fun SimpleTypeMarker.isIntegerLiteralType(): Boolean {
@@ -38,5 +38,7 @@ abstract class FirTypeParameter : FirPureAbstractElement(), FirTypeParameterRef,
abstract override fun replaceResolvePhase(newResolvePhase: FirResolvePhase)
abstract fun replaceBounds(newBounds: List<FirTypeRef>)
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirTypeParameter
}
@@ -60,4 +60,9 @@ internal class FirTypeParameterImpl(
override fun replaceResolvePhase(newResolvePhase: FirResolvePhase) {
resolvePhase = newResolvePhase
}
override fun replaceBounds(newBounds: List<FirTypeRef>) {
bounds.clear()
bounds.addAll(newBounds)
}
}
@@ -291,7 +291,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
+symbol("FirTypeParameterSymbol")
+field(varianceType)
+booleanField("isReified")
+fieldList("bounds", typeRef)
+fieldList("bounds", typeRef, withReplace = true)
+annotations
}