[FIR] Split TypeUtils from :resolve to :cones and :tree modules
This commit is contained in:
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.types
|
||||
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.utils.SmartSet
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
@@ -40,4 +41,11 @@ fun ConeClassLikeType.withArguments(typeArguments: Array<out ConeTypeProjection>
|
||||
is ConeClassLikeTypeImpl -> ConeClassLikeTypeImpl(lookupTag, typeArguments, isNullable, attributes)
|
||||
is ConeClassErrorType -> this
|
||||
else -> error("Unknown cone type: ${this::class}")
|
||||
}
|
||||
}
|
||||
|
||||
fun ConeKotlinType.toTypeProjection(variance: Variance): ConeTypeProjection =
|
||||
when (variance) {
|
||||
Variance.INVARIANT -> this
|
||||
Variance.IN_VARIANCE -> ConeKotlinTypeProjectionIn(this)
|
||||
Variance.OUT_VARIANCE -> ConeKotlinTypeProjectionOut(this)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.types
|
||||
|
||||
import org.jetbrains.kotlin.types.AbstractNullabilityChecker
|
||||
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
||||
|
||||
object ConeNullabilityChecker {
|
||||
fun isSubtypeOfAny(context: ConeTypeContext, type: ConeKotlinType): Boolean {
|
||||
val actualType = with(context) { type.lowerBoundIfFlexible() }
|
||||
return with(AbstractNullabilityChecker) {
|
||||
context.newBaseTypeCheckerContext(errorTypesEqualToAnything = false, stubTypesEqualToAnything = true)
|
||||
.hasNotNullSupertype(actualType, AbstractTypeCheckerContext.SupertypesPolicy.LowerIfFlexible)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,28 +7,10 @@ package org.jetbrains.kotlin.fir.types
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator
|
||||
import org.jetbrains.kotlin.types.AbstractNullabilityChecker
|
||||
import org.jetbrains.kotlin.types.AbstractStrictEqualityTypeChecker
|
||||
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
object ConeNullabilityChecker {
|
||||
fun isSubtypeOfAny(context: ConeTypeContext, type: ConeKotlinType): Boolean {
|
||||
val actualType = with(context) { type.lowerBoundIfFlexible() }
|
||||
return with(AbstractNullabilityChecker) {
|
||||
context.newBaseTypeCheckerContext(errorTypesEqualToAnything = false, stubTypesEqualToAnything = true)
|
||||
.hasNotNullSupertype(actualType, AbstractTypeCheckerContext.SupertypesPolicy.LowerIfFlexible)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun ConeInferenceContext.commonSuperTypeOrNull(types: List<ConeKotlinType>): ConeKotlinType? {
|
||||
return when (types.size) {
|
||||
@@ -57,30 +39,6 @@ fun ConeDefinitelyNotNullType.Companion.create(original: ConeKotlinType): ConeDe
|
||||
}
|
||||
}
|
||||
|
||||
fun makesSenseToBeDefinitelyNotNull(type: ConeKotlinType): Boolean =
|
||||
type.canHaveUndefinedNullability() // TODO: also check nullability
|
||||
|
||||
fun ConeKotlinType.canHaveUndefinedNullability(): Boolean {
|
||||
return when (this) {
|
||||
is ConeTypeVariableType,
|
||||
is ConeCapturedType
|
||||
-> true
|
||||
is ConeTypeParameterType -> type.isMarkedNullable || !hasNotNullUpperBound()
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
private fun ConeTypeParameterType.hasNotNullUpperBound(): Boolean {
|
||||
return lookupTag.typeParameterSymbol.fir.bounds.any {
|
||||
val boundType = it.coneType
|
||||
if (boundType is ConeTypeParameterType) {
|
||||
boundType.hasNotNullUpperBound()
|
||||
} else {
|
||||
boundType.nullability == ConeNullability.NOT_NULL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun ConeKotlinType.makeConeTypeDefinitelyNotNullOrNotNull(): ConeKotlinType {
|
||||
if (this is ConeIntersectionType) {
|
||||
return ConeIntersectionType(intersectedTypes.map { it.makeConeTypeDefinitelyNotNullOrNotNull() })
|
||||
@@ -195,50 +153,11 @@ fun coneFlexibleOrSimpleType(
|
||||
}
|
||||
}
|
||||
|
||||
fun ConeKotlinType.toTypeProjection(variance: Variance): ConeTypeProjection =
|
||||
when (variance) {
|
||||
Variance.INVARIANT -> this
|
||||
Variance.IN_VARIANCE -> ConeKotlinTypeProjectionIn(this)
|
||||
Variance.OUT_VARIANCE -> ConeKotlinTypeProjectionOut(this)
|
||||
}
|
||||
|
||||
internal fun FirTypeProjection.toConeTypeProjection(): ConeTypeProjection =
|
||||
when (this) {
|
||||
is FirStarProjection -> ConeStarProjection
|
||||
is FirTypeProjectionWithVariance -> {
|
||||
val type = typeRef.coneType
|
||||
type.toTypeProjection(this.variance)
|
||||
}
|
||||
else -> error("!")
|
||||
}
|
||||
|
||||
fun ConeClassLikeLookupTag.constructClassType(
|
||||
typeArguments: Array<out ConeTypeProjection>,
|
||||
isNullable: Boolean,
|
||||
): ConeClassLikeType {
|
||||
return ConeClassLikeTypeImpl(this, typeArguments, isNullable)
|
||||
}
|
||||
|
||||
fun ClassId.constructClassLikeType(
|
||||
typeArguments: Array<out ConeTypeProjection>,
|
||||
isNullable: Boolean,
|
||||
): ConeClassLikeType {
|
||||
return ConeClassLikeTypeImpl(ConeClassLikeLookupTagImpl(this), typeArguments, isNullable)
|
||||
}
|
||||
|
||||
fun ConeClassifierLookupTag.constructType(typeArguments: Array<out ConeTypeProjection>, isNullable: Boolean): ConeLookupTagBasedType {
|
||||
return when (this) {
|
||||
is ConeTypeParameterLookupTag -> ConeTypeParameterTypeImpl(this, isNullable)
|
||||
is ConeClassLikeLookupTag -> this.constructClassType(typeArguments, isNullable)
|
||||
else -> error("! ${this::class}")
|
||||
}
|
||||
fun ConeKotlinType.isExtensionFunctionType(session: FirSession): Boolean {
|
||||
val type = this.lowerBoundIfFlexible().fullyExpandedType(session)
|
||||
return type.attributes.extensionFunctionType != null
|
||||
}
|
||||
|
||||
fun FirTypeRef.isExtensionFunctionType(session: FirSession): Boolean {
|
||||
return coneTypeSafe<ConeKotlinType>()?.isExtensionFunctionType(session) == true
|
||||
}
|
||||
|
||||
fun ConeKotlinType.isExtensionFunctionType(session: FirSession): Boolean {
|
||||
val type = this.lowerBoundIfFlexible().fullyExpandedType(session)
|
||||
return type.attributes.extensionFunctionType != null
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@ import org.jetbrains.kotlin.name.ClassId
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
|
||||
inline fun <reified T : ConeKotlinType> FirTypeRef.coneTypeUnsafe() = (this as FirResolvedTypeRef).type as T
|
||||
inline fun <reified T : ConeKotlinType> FirTypeRef.coneTypeUnsafe(): T = (this as FirResolvedTypeRef).type as T
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
inline fun <reified T : ConeKotlinType> FirTypeRef.coneTypeSafe(): T? {
|
||||
contract {
|
||||
@@ -21,6 +22,7 @@ inline fun <reified T : ConeKotlinType> FirTypeRef.coneTypeSafe(): T? {
|
||||
}
|
||||
return (this as? FirResolvedTypeRef)?.type as? T
|
||||
}
|
||||
|
||||
inline val FirTypeRef.coneType: ConeKotlinType get() = coneTypeUnsafe()
|
||||
|
||||
val FirTypeRef.isAny: Boolean get() = isBuiltinType(StandardClassIds.Any, false)
|
||||
@@ -59,9 +61,9 @@ val FirFunctionTypeRef.parametersCount: Int
|
||||
const val EXTENSION_FUNCTION_ANNOTATION = "kotlin/ExtensionFunctionType"
|
||||
|
||||
val FirAnnotationCall.isExtensionFunctionAnnotationCall: Boolean
|
||||
get() = (this as? FirAnnotationCall)?.let {
|
||||
(it.annotationTypeRef as? FirResolvedTypeRef)?.let {
|
||||
(it.type as? ConeClassLikeType)?.let {
|
||||
get() = (this as? FirAnnotationCall)?.let { annotationCall ->
|
||||
(annotationCall.annotationTypeRef as? FirResolvedTypeRef)?.let { typeRef ->
|
||||
(typeRef.type as? ConeClassLikeType)?.let {
|
||||
it.lookupTag.classId.asString() == EXTENSION_FUNCTION_ANNOTATION
|
||||
}
|
||||
}
|
||||
@@ -97,4 +99,38 @@ fun List<FirAnnotationCall>.computeTypeAttributes(): ConeAttributes {
|
||||
}
|
||||
}
|
||||
return ConeAttributes.create(attributes)
|
||||
}
|
||||
}
|
||||
|
||||
fun FirTypeProjection.toConeTypeProjection(): ConeTypeProjection =
|
||||
when (this) {
|
||||
is FirStarProjection -> ConeStarProjection
|
||||
is FirTypeProjectionWithVariance -> {
|
||||
val type = typeRef.coneType
|
||||
type.toTypeProjection(this.variance)
|
||||
}
|
||||
else -> error("!")
|
||||
}
|
||||
|
||||
fun makesSenseToBeDefinitelyNotNull(type: ConeKotlinType): Boolean =
|
||||
type.canHaveUndefinedNullability() // TODO: also check nullability
|
||||
|
||||
fun ConeKotlinType.canHaveUndefinedNullability(): Boolean {
|
||||
return when (this) {
|
||||
is ConeTypeVariableType,
|
||||
is ConeCapturedType
|
||||
-> true
|
||||
is ConeTypeParameterType -> type.isMarkedNullable || !hasNotNullUpperBound()
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
private fun ConeTypeParameterType.hasNotNullUpperBound(): Boolean {
|
||||
return lookupTag.typeParameterSymbol.fir.bounds.any {
|
||||
val boundType = it.coneType
|
||||
if (boundType is ConeTypeParameterType) {
|
||||
boundType.hasNotNullUpperBound()
|
||||
} else {
|
||||
boundType.nullability == ConeNullability.NOT_NULL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.types
|
||||
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
|
||||
fun ConeClassifierLookupTag.constructType(
|
||||
typeArguments: Array<out ConeTypeProjection>,
|
||||
isNullable: Boolean
|
||||
): ConeLookupTagBasedType {
|
||||
return when (this) {
|
||||
is ConeTypeParameterLookupTag -> ConeTypeParameterTypeImpl(this, isNullable)
|
||||
is ConeClassLikeLookupTag -> this.constructClassType(typeArguments, isNullable)
|
||||
else -> error("! ${this::class}")
|
||||
}
|
||||
}
|
||||
|
||||
fun ConeClassLikeLookupTag.constructClassType(
|
||||
typeArguments: Array<out ConeTypeProjection>,
|
||||
isNullable: Boolean,
|
||||
): ConeClassLikeType {
|
||||
return ConeClassLikeTypeImpl(this, typeArguments, isNullable)
|
||||
}
|
||||
|
||||
fun ClassId.constructClassLikeType(
|
||||
typeArguments: Array<out ConeTypeProjection>,
|
||||
isNullable: Boolean,
|
||||
): ConeClassLikeType {
|
||||
return ConeClassLikeTypeImpl(ConeClassLikeLookupTagImpl(this), typeArguments, isNullable)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user