[FIR] Add useful util extensions for cone type

This commit is contained in:
Dmitriy Novozhilov
2021-02-06 11:47:30 +03:00
parent ad677046a8
commit 2a1c9283a4
4 changed files with 31 additions and 8 deletions
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.types
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.types.Variance
@@ -55,3 +56,22 @@ fun ConeClassLikeType.replaceArgumentsWithStarProjections(): ConeClassLikeType {
val newArguments = Array(typeArguments.size) { ConeStarProjection }
return withArguments(newArguments)
}
val ConeKotlinType.isAny: Boolean get() = isBuiltinType(StandardClassIds.Any, false)
val ConeKotlinType.isNullableAny: Boolean get() = isBuiltinType(StandardClassIds.Any, true)
val ConeKotlinType.isNothing: Boolean get() = isBuiltinType(StandardClassIds.Nothing, false)
val ConeKotlinType.isNullableNothing: Boolean get() = isBuiltinType(StandardClassIds.Nothing, true)
val ConeKotlinType.isUnit: Boolean get() = isBuiltinType(StandardClassIds.Unit, false)
val ConeKotlinType.isBoolean: Boolean get() = isBuiltinType(StandardClassIds.Boolean, false)
val ConeKotlinType.isEnum: Boolean get() = isBuiltinType(StandardClassIds.Enum, false)
val ConeKotlinType.isArrayType: Boolean
get() {
return isBuiltinType(StandardClassIds.Array, false) ||
StandardClassIds.primitiveArrayTypeByElementType.values.any { isBuiltinType(it, false) }
}
private fun ConeKotlinType.isBuiltinType(classId: ClassId, isNullable: Boolean): Boolean {
if (this !is ConeClassLikeType) return false
return lookupTag.classId == classId && type.isNullable == isNullable
}
@@ -226,7 +226,7 @@ private fun BodyResolveComponents.getCallableReferenceAdaptation(
}
}
val coercionStrategy = if (returnExpectedType.isUnit && !function.returnTypeRef.isUnit)
val coercionStrategy = if (returnExpectedType.isUnitOrFlexibleUnit && !function.returnTypeRef.isUnit)
CoercionStrategy.COERCION_TO_UNIT
else
CoercionStrategy.NO_COERCION
@@ -288,7 +288,7 @@ private enum class VarargMappingState {
private fun FirFunction<*>.indexOf(valueParameter: FirValueParameter): Int = valueParameters.indexOf(valueParameter)
val ConeKotlinType.isUnit: Boolean
val ConeKotlinType.isUnitOrFlexibleUnit: Boolean
get() {
val type = this.lowerBoundIfFlexible()
if (type.isNullable) return false
@@ -168,14 +168,14 @@ class PostponedArgumentsAnalyzer(
val lastExpression = lambda.atom.body?.statements?.lastOrNull() as? FirExpression
var hasExpressionInReturnArguments = false
// No constraint for return expressions of lambda if it has Unit return type.
val lambdaReturnType = lambda.returnType.let(substitute).takeUnless { it.isUnit }
val lambdaReturnType = lambda.returnType.let(substitute).takeUnless { it.isUnitOrFlexibleUnit }
returnArguments.forEach {
if (it !is FirExpression) return@forEach
hasExpressionInReturnArguments = true
// If it is the last expression, and the expected type is Unit, that expression will be coerced to Unit.
// If the last expression is of Unit type, of course it's not coercion-to-Unit case.
val lastExpressionCoercedToUnit =
it == lastExpression && expectedReturnType?.isUnit == true && !it.typeRef.coneType.isUnit
it == lastExpression && expectedReturnType?.isUnitOrFlexibleUnit == true && !it.typeRef.coneType.isUnitOrFlexibleUnit
// No constraint for the last expression of lambda if it will be coerced to Unit.
if (!lastExpressionCoercedToUnit) {
candidate.resolveArgumentExpression(
@@ -7,13 +7,12 @@ package org.jetbrains.kotlin.fir.types
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.classId
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.fakeElement
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLookupTagWithFixedSymbol
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
@@ -184,6 +183,10 @@ fun ConeKotlinType.isUnsafeVarianceType(session: FirSession): Boolean {
return type.attributes.unsafeVarianceType != null
}
fun ConeKotlinType.toSymbol(session: FirSession): AbstractFirBasedSymbol<*>? {
return (this as? ConeLookupTagBasedType)?.lookupTag?.toSymbol(session)
}
fun FirTypeRef.isUnsafeVarianceType(session: FirSession): Boolean {
return coneTypeSafe<ConeKotlinType>()?.isUnsafeVarianceType(session) == true
}