[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.fir.types.impl.ConeClassLikeTypeImpl
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.utils.SmartSet
|
import org.jetbrains.kotlin.utils.SmartSet
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
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 ConeClassLikeTypeImpl -> ConeClassLikeTypeImpl(lookupTag, typeArguments, isNullable, attributes)
|
||||||
is ConeClassErrorType -> this
|
is ConeClassErrorType -> this
|
||||||
else -> error("Unknown cone type: ${this::class}")
|
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.FirSession
|
||||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
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.ConeClassLikeTypeImpl
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
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.resolve.calls.NewCommonSuperTypeCalculator
|
||||||
import org.jetbrains.kotlin.types.AbstractNullabilityChecker
|
|
||||||
import org.jetbrains.kotlin.types.AbstractStrictEqualityTypeChecker
|
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? {
|
fun ConeInferenceContext.commonSuperTypeOrNull(types: List<ConeKotlinType>): ConeKotlinType? {
|
||||||
return when (types.size) {
|
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 {
|
fun ConeKotlinType.makeConeTypeDefinitelyNotNullOrNotNull(): ConeKotlinType {
|
||||||
if (this is ConeIntersectionType) {
|
if (this is ConeIntersectionType) {
|
||||||
return ConeIntersectionType(intersectedTypes.map { it.makeConeTypeDefinitelyNotNullOrNotNull() })
|
return ConeIntersectionType(intersectedTypes.map { it.makeConeTypeDefinitelyNotNullOrNotNull() })
|
||||||
@@ -195,50 +153,11 @@ fun coneFlexibleOrSimpleType(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ConeKotlinType.toTypeProjection(variance: Variance): ConeTypeProjection =
|
fun ConeKotlinType.isExtensionFunctionType(session: FirSession): Boolean {
|
||||||
when (variance) {
|
val type = this.lowerBoundIfFlexible().fullyExpandedType(session)
|
||||||
Variance.INVARIANT -> this
|
return type.attributes.extensionFunctionType != null
|
||||||
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 FirTypeRef.isExtensionFunctionType(session: FirSession): Boolean {
|
fun FirTypeRef.isExtensionFunctionType(session: FirSession): Boolean {
|
||||||
return coneTypeSafe<ConeKotlinType>()?.isExtensionFunctionType(session) == true
|
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.ExperimentalContracts
|
||||||
import kotlin.contracts.contract
|
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)
|
@OptIn(ExperimentalContracts::class)
|
||||||
inline fun <reified T : ConeKotlinType> FirTypeRef.coneTypeSafe(): T? {
|
inline fun <reified T : ConeKotlinType> FirTypeRef.coneTypeSafe(): T? {
|
||||||
contract {
|
contract {
|
||||||
@@ -21,6 +22,7 @@ inline fun <reified T : ConeKotlinType> FirTypeRef.coneTypeSafe(): T? {
|
|||||||
}
|
}
|
||||||
return (this as? FirResolvedTypeRef)?.type as? T
|
return (this as? FirResolvedTypeRef)?.type as? T
|
||||||
}
|
}
|
||||||
|
|
||||||
inline val FirTypeRef.coneType: ConeKotlinType get() = coneTypeUnsafe()
|
inline val FirTypeRef.coneType: ConeKotlinType get() = coneTypeUnsafe()
|
||||||
|
|
||||||
val FirTypeRef.isAny: Boolean get() = isBuiltinType(StandardClassIds.Any, false)
|
val FirTypeRef.isAny: Boolean get() = isBuiltinType(StandardClassIds.Any, false)
|
||||||
@@ -59,9 +61,9 @@ val FirFunctionTypeRef.parametersCount: Int
|
|||||||
const val EXTENSION_FUNCTION_ANNOTATION = "kotlin/ExtensionFunctionType"
|
const val EXTENSION_FUNCTION_ANNOTATION = "kotlin/ExtensionFunctionType"
|
||||||
|
|
||||||
val FirAnnotationCall.isExtensionFunctionAnnotationCall: Boolean
|
val FirAnnotationCall.isExtensionFunctionAnnotationCall: Boolean
|
||||||
get() = (this as? FirAnnotationCall)?.let {
|
get() = (this as? FirAnnotationCall)?.let { annotationCall ->
|
||||||
(it.annotationTypeRef as? FirResolvedTypeRef)?.let {
|
(annotationCall.annotationTypeRef as? FirResolvedTypeRef)?.let { typeRef ->
|
||||||
(it.type as? ConeClassLikeType)?.let {
|
(typeRef.type as? ConeClassLikeType)?.let {
|
||||||
it.lookupTag.classId.asString() == EXTENSION_FUNCTION_ANNOTATION
|
it.lookupTag.classId.asString() == EXTENSION_FUNCTION_ANNOTATION
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,4 +99,38 @@ fun List<FirAnnotationCall>.computeTypeAttributes(): ConeAttributes {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ConeAttributes.create(attributes)
|
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