K2: make type variable based types not class like

#KT-57921 Fixed
#KT-62420 Fixed
This commit is contained in:
Mikhail Glukhikh
2023-11-07 11:03:19 +01:00
committed by Space Team
parent 6053c94c8a
commit 1ceec4d6d7
7 changed files with 23 additions and 26 deletions
@@ -28,7 +28,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.*
import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
@@ -312,8 +311,7 @@ internal object FirCompileTimeConstantEvaluator {
is ConeCapturedType -> lowerType?.toConstantValueKind() ?: constructor.supertypes!!.first().toConstantValueKind() is ConeCapturedType -> lowerType?.toConstantValueKind() ?: constructor.supertypes!!.first().toConstantValueKind()
is ConeDefinitelyNotNullType -> original.toConstantValueKind() is ConeDefinitelyNotNullType -> original.toConstantValueKind()
is ConeIntersectionType -> intersectedTypes.first().toConstantValueKind() is ConeIntersectionType -> intersectedTypes.first().toConstantValueKind()
is ConeStubType -> null is ConeStubType, is ConeIntegerLiteralType, is ConeTypeVariableType -> null
is ConeIntegerLiteralType -> null
} }
private fun String.toConstantValueKind(): ConstantValueKind<*>? = private fun String.toConstantValueKind(): ConstantValueKind<*>? =
@@ -241,16 +241,18 @@ object ConeTypeCompatibilityChecker {
is ConeErrorType -> emptySet() // Ignore error types is ConeErrorType -> emptySet() // Ignore error types
is ConeLookupTagBasedType -> when (this) { is ConeLookupTagBasedType -> when (this) {
is ConeClassLikeType -> setOf(this) is ConeClassLikeType -> setOf(this)
is ConeTypeVariableType -> emptySet()
is ConeTypeParameterType -> emptySet() is ConeTypeParameterType -> emptySet()
else -> throw IllegalStateException("missing branch for ${javaClass.name}") else -> error("missing branch for ${javaClass.name}")
} }
is ConeTypeVariableType -> emptySet()
is ConeDefinitelyNotNullType -> original.collectLowerBounds() is ConeDefinitelyNotNullType -> original.collectLowerBounds()
is ConeIntersectionType -> intersectedTypes.flatMap { it.collectLowerBounds() }.toSet() is ConeIntersectionType -> intersectedTypes.flatMap { it.collectLowerBounds() }.toSet()
is ConeFlexibleType -> lowerBound.collectLowerBounds() is ConeFlexibleType -> lowerBound.collectLowerBounds()
is ConeCapturedType -> constructor.supertypes?.flatMap { it.collectLowerBounds() }?.toSet().orEmpty() is ConeCapturedType -> constructor.supertypes?.flatMap { it.collectLowerBounds() }?.toSet().orEmpty()
is ConeIntegerConstantOperatorType -> setOf(getApproximatedType()) is ConeIntegerConstantOperatorType -> setOf(getApproximatedType())
is ConeStubType, is ConeIntegerLiteralConstantType -> throw IllegalStateException("$this should not reach here") is ConeStubType, is ConeIntegerLiteralConstantType -> {
error("$this should not reach here")
}
} }
} }
@@ -832,22 +832,24 @@ fun ConeKotlinType?.collectUpperBounds(): Set<ConeClassLikeType> {
is ConeErrorType -> return // Ignore error types is ConeErrorType -> return // Ignore error types
is ConeLookupTagBasedType -> when (type) { is ConeLookupTagBasedType -> when (type) {
is ConeClassLikeType -> upperBounds.add(type) is ConeClassLikeType -> upperBounds.add(type)
is ConeTypeVariableType -> {
val symbol = (type.lookupTag.originalTypeParameter as? ConeTypeParameterLookupTag)?.typeParameterSymbol ?: return
symbol.resolvedBounds.forEach { collect(it.coneType) }
}
is ConeTypeParameterType -> { is ConeTypeParameterType -> {
val symbol = type.lookupTag.typeParameterSymbol val symbol = type.lookupTag.typeParameterSymbol
symbol.resolvedBounds.forEach { collect(it.coneType) } symbol.resolvedBounds.forEach { collect(it.coneType) }
} }
else -> throw IllegalStateException("missing branch for ${javaClass.name}") else -> error("missing branch for ${javaClass.name}")
}
is ConeTypeVariableType -> {
val symbol = (type.lookupTag.originalTypeParameter as? ConeTypeParameterLookupTag)?.typeParameterSymbol ?: return
symbol.resolvedBounds.forEach { collect(it.coneType) }
} }
is ConeDefinitelyNotNullType -> collect(type.original) is ConeDefinitelyNotNullType -> collect(type.original)
is ConeIntersectionType -> type.intersectedTypes.forEach(::collect) is ConeIntersectionType -> type.intersectedTypes.forEach(::collect)
is ConeFlexibleType -> collect(type.upperBound) is ConeFlexibleType -> collect(type.upperBound)
is ConeCapturedType -> type.constructor.supertypes?.forEach(::collect) is ConeCapturedType -> type.constructor.supertypes?.forEach(::collect)
is ConeIntegerConstantOperatorType -> upperBounds.add(type.getApproximatedType()) is ConeIntegerConstantOperatorType -> upperBounds.add(type.getApproximatedType())
is ConeStubType, is ConeIntegerLiteralConstantType -> throw IllegalStateException("$type should not reach here") is ConeStubType, is ConeIntegerLiteralConstantType -> {
error("$type should not reach here")
}
} }
} }
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.fir.types package org.jetbrains.kotlin.fir.types
import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.model.* import org.jetbrains.kotlin.types.model.*
@@ -13,10 +12,9 @@ import org.jetbrains.kotlin.types.model.*
class ConeTypeVariableType( class ConeTypeVariableType(
override val nullability: ConeNullability, override val nullability: ConeNullability,
override val lookupTag: ConeTypeVariableTypeConstructor, val lookupTag: ConeTypeVariableTypeConstructor,
override val attributes: ConeAttributes = ConeAttributes.Empty, override val attributes: ConeAttributes = ConeAttributes.Empty,
// TODO: Make ConeSimpleKotlinType. KT-62420 ) : ConeSimpleKotlinType() {
) : ConeLookupTagBasedType() {
override val typeArguments: Array<out ConeTypeProjection> get() = EMPTY_ARRAY override val typeArguments: Array<out ConeTypeProjection> get() = EMPTY_ARRAY
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
@@ -39,9 +37,8 @@ class ConeTypeVariableType(
class ConeTypeVariableTypeConstructor( class ConeTypeVariableTypeConstructor(
val debugName: String, val debugName: String,
val originalTypeParameter: TypeParameterMarker? val originalTypeParameter: TypeParameterMarker?
// TODO: Remove ConeClassifierLookupTag supertype. KT-62420 ) : TypeVariableTypeConstructorMarker {
) : ConeClassifierLookupTag(), TypeVariableTypeConstructorMarker { val name: Name get() = Name.identifier(debugName)
override val name: Name get() = Name.identifier(debugName)
var isContainedInInvariantOrContravariantPositions: Boolean = false var isContainedInInvariantOrContravariantPositions: Boolean = false
private set private set
@@ -237,8 +237,7 @@ class Fir2IrTypeConverter(
val approximated = approximateForIrOrNull()!! val approximated = approximateForIrOrNull()!!
approximated.toIrType(typeOrigin) approximated.toIrType(typeOrigin)
} }
is ConeStubType -> createErrorType() is ConeStubType, is ConeIntegerLiteralType, is ConeTypeVariableType -> createErrorType()
is ConeIntegerLiteralType -> createErrorType()
} }
} }
@@ -40,8 +40,7 @@ fun ConeClassifierLookupTag.toSymbol(useSiteSession: FirSession): FirClassifierS
when (this) { when (this) {
is ConeClassLikeLookupTag -> toSymbol(useSiteSession) is ConeClassLikeLookupTag -> toSymbol(useSiteSession)
is ConeClassifierLookupTagWithFixedSymbol -> this.symbol is ConeClassifierLookupTagWithFixedSymbol -> this.symbol
// TODO: replace null with error(), see KT-57921 else -> error("missing branch for ${javaClass.name}")
else -> null
} }
/** /**
@@ -85,7 +85,7 @@ abstract class AbstractConeSubstitutor(protected val typeContext: ConeTypeContex
private fun ConeKotlinType.substituteRecursive(): ConeKotlinType? { private fun ConeKotlinType.substituteRecursive(): ConeKotlinType? {
return when (this) { return when (this) {
is ConeClassLikeType -> this.substituteArguments() is ConeClassLikeType -> this.substituteArguments()
is ConeLookupTagBasedType -> return null is ConeLookupTagBasedType, is ConeTypeVariableType -> return null
is ConeFlexibleType -> this.substituteBounds()?.let { is ConeFlexibleType -> this.substituteBounds()?.let {
// TODO: may be (?) it's worth adding regular type comparison via AbstractTypeChecker // TODO: may be (?) it's worth adding regular type comparison via AbstractTypeChecker
// However, the simplified check here should be enough for typical flexible types // However, the simplified check here should be enough for typical flexible types
@@ -156,7 +156,7 @@ abstract class AbstractConeSubstitutor(protected val typeContext: ConeTypeContex
return null return null
} }
private fun ConeClassLikeType.substituteArguments(): ConeKotlinType? { private fun ConeSimpleKotlinType.substituteArguments(): ConeKotlinType? {
val newArguments by lazy { arrayOfNulls<ConeTypeProjection>(typeArguments.size) } val newArguments by lazy { arrayOfNulls<ConeTypeProjection>(typeArguments.size) }
var initialized = false var initialized = false
@@ -325,7 +325,7 @@ internal class ConeTypeSubstitutorByTypeConstructor(
private val approximateIntegerLiterals: Boolean private val approximateIntegerLiterals: Boolean
) : AbstractConeSubstitutor(typeContext), TypeSubstitutorMarker { ) : AbstractConeSubstitutor(typeContext), TypeSubstitutorMarker {
override fun substituteType(type: ConeKotlinType): ConeKotlinType? { override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
if (type !is ConeLookupTagBasedType && type !is ConeStubType) return null if (type !is ConeLookupTagBasedType && type !is ConeStubType && type !is ConeTypeVariableType) return null
val new = map[type.typeConstructor(typeContext)] ?: return null val new = map[type.typeConstructor(typeContext)] ?: return null
val approximatedIntegerLiteralType = if (approximateIntegerLiterals) new.approximateIntegerLiteralType() else new val approximatedIntegerLiteralType = if (approximateIntegerLiterals) new.approximateIntegerLiteralType() else new
return approximatedIntegerLiteralType.updateNullabilityIfNeeded(type)?.withCombinedAttributesFrom(type) return approximatedIntegerLiteralType.updateNullabilityIfNeeded(type)?.withCombinedAttributesFrom(type)