diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt index f5b135d176e..e04b741b45d 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt @@ -114,10 +114,33 @@ abstract class ConeFunctionType : ConeClassLikeType() { abstract val returnType: ConeKotlinType } -class ConeFlexibleType(val lowerBound: ConeLookupTagBasedType, val upperBound: ConeLookupTagBasedType) : ConeKotlinType(), FlexibleTypeMarker { +class ConeFlexibleType(val lowerBound: ConeLookupTagBasedType, val upperBound: ConeLookupTagBasedType) : ConeKotlinType(), + FlexibleTypeMarker { override val typeArguments: Array get() = emptyArray() override val nullability: ConeNullability get() = lowerBound.nullability.takeIf { it == upperBound.nullability } ?: ConeNullability.UNKNOWN } + +class ConeCapturedTypeConstructor(val projection: ConeKotlinTypeProjection) : TypeConstructorMarker { + var supertypes: List? = null +} + +class ConeCapturedType( + val captureStatus: CaptureStatus, + val lowerType: ConeKotlinType?, + override val nullability: ConeNullability = ConeNullability.NOT_NULL, + val constructor: ConeCapturedTypeConstructor +) : ConeKotlinType(), SimpleTypeMarker, CapturedTypeMarker { + constructor(captureStatus: CaptureStatus, lowerType: ConeKotlinType?, projection: ConeKotlinTypeProjection) : this( + captureStatus, + lowerType, + constructor = ConeCapturedTypeConstructor( + projection + ) + ) + + override val typeArguments: Array + get() = emptyArray() +} \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt index fadab5c9d40..f413e1905f7 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt @@ -7,11 +7,12 @@ package org.jetbrains.kotlin.fir.types import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.expandedConeType import org.jetbrains.kotlin.fir.declarations.superConeTypes +import org.jetbrains.kotlin.fir.resolve.directExpansionType import org.jetbrains.kotlin.fir.resolve.toSymbol +import org.jetbrains.kotlin.fir.resolve.withArguments import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.ConeClassSymbol import org.jetbrains.kotlin.fir.symbols.ConeSymbol @@ -23,13 +24,8 @@ import org.jetbrains.kotlin.fir.types.impl.ConeAbbreviatedTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeFunctionTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl -import org.jetbrains.kotlin.resolve.calls.inference.CapturedType import org.jetbrains.kotlin.types.AbstractTypeCheckerContext -import org.jetbrains.kotlin.types.DefinitelyNotNullType -import org.jetbrains.kotlin.types.SimpleType -import org.jetbrains.kotlin.types.checker.NewCapturedType import org.jetbrains.kotlin.types.checker.convertVariance -import org.jetbrains.kotlin.types.isError import org.jetbrains.kotlin.types.model.* @@ -40,7 +36,12 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext { override fun KotlinTypeMarker.asSimpleType(): SimpleTypeMarker? { assert(this is ConeKotlinType) - return this as? ConeLookupTagBasedType + return when (this) { + is ConeAbbreviatedType -> directExpansionType(session) + is ConeCapturedType -> this + is ConeLookupTagBasedType -> this + else -> null + } } override fun KotlinTypeMarker.asFlexibleType(): FlexibleTypeMarker? { @@ -74,25 +75,25 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext { } override fun SimpleTypeMarker.asCapturedType(): CapturedTypeMarker? { - require(this is ConeLookupTagBasedType) - return null // TODO + //require(this is ConeLookupTagBasedType) + return this as? ConeCapturedType } override fun SimpleTypeMarker.asDefinitelyNotNullType(): DefinitelyNotNullTypeMarker? { - require(this is ConeLookupTagBasedType) + require(this is ConeKotlinType) return null // TODO } override fun SimpleTypeMarker.isMarkedNullable(): Boolean { - require(this is ConeLookupTagBasedType) + require(this is ConeKotlinType) return this.nullability.isNullable } override fun SimpleTypeMarker.withNullability(nullable: Boolean): SimpleTypeMarker { - require(this is ConeLookupTagBasedType) + require(this is ConeKotlinType) if (nullability.isNullable == nullable) return this return when (this) { - + is ConeCapturedType -> ConeCapturedType(captureStatus, lowerType, ConeNullability.create(nullable), constructor) is ConeTypeParameterType -> ConeTypeParameterTypeImpl(lookupTag, nullable) is ConeClassErrorType -> this is ConeClassType -> ConeClassTypeImpl(lookupTag, typeArguments, nullable) @@ -108,23 +109,27 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext { lookupTag, nullable ) + else -> error("!") } } override fun SimpleTypeMarker.typeConstructor(): TypeConstructorMarker { - require(this is ConeLookupTagBasedType) - if (this is ConeClassErrorType) return ErrorTypeConstructor("No constructor: $reason") - return this.lookupTag.toSymbol(session) ?: ErrorTypeConstructor("Unresolved: ${this.lookupTag}") + return when (this) { + is ConeCapturedType -> constructor + is ConeLookupTagBasedType -> this.lookupTag.toSymbol(session) ?: ErrorTypeConstructor("Unresolved: ${this.lookupTag}") + else -> error("?: ${this}") + } + } override fun SimpleTypeMarker.argumentsCount(): Int { - require(this is ConeLookupTagBasedType) + require(this is ConeKotlinType) return this.typeArguments.size } override fun SimpleTypeMarker.getArgument(index: Int): TypeArgumentMarker { - require(this is ConeLookupTagBasedType) + require(this is ConeKotlinType) return this.typeArguments[index] } @@ -136,8 +141,8 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext { } override fun CapturedTypeMarker.lowerType(): KotlinTypeMarker? { - require(this is ConeKotlinType) - return null // TODO + require(this is ConeCapturedType) + return this.lowerType } override fun TypeArgumentMarker.isStarProjection(): Boolean { @@ -163,9 +168,9 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext { } override fun TypeConstructorMarker.parametersCount(): Int { - require(this is ConeSymbol) + //require(this is ConeSymbol) return when (this) { - is ConeTypeParameterSymbol -> 0 + is ConeTypeParameterSymbol, is ConeCapturedTypeConstructor, is ErrorTypeConstructor -> 0 is FirClassSymbol -> fir.typeParameters.size is FirTypeAliasSymbol -> fir.typeParameters.size else -> error("?!:10") @@ -173,7 +178,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext { } override fun TypeConstructorMarker.getParameter(index: Int): TypeParameterMarker { - require(this is ConeSymbol) + //require(this is ConeSymbol) return when (this) { is ConeTypeParameterSymbol -> error("?!:11") is FirClassSymbol -> fir.typeParameters[index].symbol @@ -184,11 +189,12 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext { override fun TypeConstructorMarker.supertypes(): Collection { if (this is ErrorTypeConstructor) return emptyList() - require(this is ConeSymbol) + //require(this is ConeSymbol) return when (this) { is ConeTypeParameterSymbol -> emptyList() is FirClassSymbol -> fir.superConeTypes is FirTypeAliasSymbol -> listOfNotNull(fir.expandedConeType) + is ConeCapturedTypeConstructor -> supertypes!! else -> error("?!:13") } } @@ -198,7 +204,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext { } override fun TypeConstructorMarker.isClassTypeConstructor(): Boolean { - assert(this is ConeSymbol) + //assert(this is ConeSymbol) return this is FirClassSymbol } @@ -224,8 +230,9 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext { override fun isEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker): Boolean { if (c1 is ErrorTypeConstructor || c2 is ErrorTypeConstructor) return false - require(c1 is ConeSymbol) - require(c2 is ConeSymbol) + + //assert(c1 is ConeSymbol) + //assert(c2 is ConeSymbol) return c1 == c2 } @@ -234,7 +241,6 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext { } override fun TypeConstructorMarker.isCommonFinalClassConstructor(): Boolean { - require(this is ConeSymbol) val classSymbol = this as? ConeClassSymbol ?: return false val fir = (classSymbol as FirClassSymbol).fir return fir.modality == Modality.FINAL && @@ -243,7 +249,43 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext { } override fun captureFromArguments(type: SimpleTypeMarker, status: CaptureStatus): SimpleTypeMarker? { - return type //TODO + require(type is ConeLookupTagBasedType) { ":( $type" } + val typeConstructor = type.typeConstructor() + if (type.argumentsCount() != typeConstructor.parametersCount()) return null + if (type.asArgumentList().all(this) { !it.isStarProjection() && it.getVariance() == TypeVariance.INV }) return null + val newArguments = Array(type.argumentsCount()) { index -> + val argument = type.getArgument(index) + if (!argument.isStarProjection() && argument.getVariance() == TypeVariance.INV) return@Array argument as ConeKotlinTypeProjection + + val lowerType = if (!argument.isStarProjection() && argument.getVariance() == TypeVariance.IN) { + argument.getType() as ConeKotlinType + } else { + null + } + + ConeCapturedType(status, lowerType, argument as ConeKotlinTypeProjection) + } + + for (index in 0 until type.argumentsCount()) { + val oldArgument = type.getArgument(index) + val newArgument = newArguments[index] + + if (!oldArgument.isStarProjection() && oldArgument.getVariance() == TypeVariance.INV) continue + + val parameter = typeConstructor.getParameter(index) + val upperBounds = (0 until parameter.upperBoundCount()).mapTo(mutableListOf()) { paramIndex -> + parameter.getUpperBound(paramIndex) // TODO: substitution + } + + if (!oldArgument.isStarProjection() && oldArgument.getVariance() == TypeVariance.OUT) { + upperBounds += oldArgument.getType() + } + + require(newArgument is ConeCapturedType) + newArgument.constructor.supertypes = upperBounds as List + } + + return type.withArguments(newArguments) } override fun SimpleTypeMarker.asArgumentList(): TypeArgumentListMarker { @@ -252,8 +294,8 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext { } override fun identicalArguments(a: SimpleTypeMarker, b: SimpleTypeMarker): Boolean { - require(a is ConeLookupTagBasedType) - require(b is ConeLookupTagBasedType) + require(a is ConeKotlinType) + require(b is ConeKotlinType) return a.typeArguments === b.typeArguments } @@ -273,15 +315,16 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext { } - override fun SimpleTypeMarker.isSingleClassifierType(): Boolean { + if (isError()) return false + if (this is ConeCapturedType) return true require(this is ConeLookupTagBasedType) val symbol = this.lookupTag.toSymbol(session) - return !isError() && - (symbol is FirClassSymbol || - symbol is FirTypeParameterSymbol) - // || TODO: (this is CapturedType || this is NewCapturedType || this is DefinitelyNotNullType) + return symbol is FirClassSymbol || + symbol is FirTypeParameterSymbol } + + } class ConeTypeCheckerContext(override val isErrorTypeEqualsToAnything: Boolean, override val session: FirSession) : @@ -300,7 +343,7 @@ class ConeTypeCheckerContext(override val isErrorTypeEqualsToAnything: Boolean, } override fun intersectTypes(types: List): KotlinTypeMarker { - TODO("not implemented") + return types.first() // TODO: proper implementation } override val KotlinTypeMarker.isAllowedTypeVariable: Boolean