FIR: introduce isPrimitive / isPrimitiveOrNullablePrimitive helpers

This commit is contained in:
Mikhail Glukhikh
2021-05-07 15:59:24 +03:00
parent 6d82aa0bc9
commit 632a9d66d1
9 changed files with 22 additions and 32 deletions
@@ -70,7 +70,7 @@ internal object ConeTypeCompatibilityChecker {
// Next can simply focus on the type hierarchy and don't need to worry about nullability.
val compatibilityUpperBound = when {
all {
it.classId in StandardClassIds.primitiveTypes
it.isPrimitive
} -> Compatibility.SOFT_INCOMPATIBLE // TODO: remove after KT-46383 is fixed
all {
it.isConcreteType()
@@ -21,15 +21,7 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.util.OperatorNameConventions
fun ConeKotlinType.canBeUsedForConstVal(): Boolean {
val classId = if (this is ConeFlexibleType) {
val lb = this.lowerBoundIfFlexible()
if (lb is ConeClassLikeType) lb.lookupTag.classId
else this.classId
} else this.classId
return (classId in StandardClassIds.primitiveTypes || classId in StandardClassIds.unsignedTypes) && !this.isNullable ||
classId == StandardClassIds.String
}
fun ConeKotlinType.canBeUsedForConstVal(): Boolean = with(lowerBoundIfFlexible()) { isPrimitive || isString || isUnsignedType }
internal fun checkConstantArguments(
expression: FirExpression,
@@ -16,8 +16,6 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.name.StandardClassIds.primitiveArrayTypeByElementType
import org.jetbrains.kotlin.name.StandardClassIds.primitiveTypes
import org.jetbrains.kotlin.name.StandardClassIds.unsignedTypes
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.ClassId
@@ -52,10 +50,10 @@ object FirAnnotationClassDeclarationChecker : FirRegularClassChecker() {
coneType.isNullable -> {
reporter.reportOn(typeRef.source, FirErrors.NULLABLE_TYPE_OF_ANNOTATION_MEMBER, context)
}
classId in primitiveTypes -> {
coneType.isPrimitiveOrNullablePrimitive -> {
// DO NOTHING: primitives are allowed as annotation class parameter
}
classId in unsignedTypes -> {
coneType.isUnsignedTypeOrNullableUnsignedType -> {
// TODO: replace with EXPERIMENTAL_UNSIGNED_LITERALS check
}
classId == StandardClassIds.KClass -> {
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter
import org.jetbrains.kotlin.fir.declarations.isLateInit
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.StandardClassIds
object FirInapplicableLateinitChecker : FirPropertyChecker() {
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
@@ -38,7 +37,7 @@ object FirInapplicableLateinitChecker : FirPropertyChecker() {
declaration.isNullable() ->
reporter.reportOn(declaration.source, "is not allowed on properties of a type with nullable upper bound", context)
declaration.returnTypeRef.coneType.classId in StandardClassIds.primitiveTypes -> if (declaration.isLocal) {
declaration.returnTypeRef.coneType.isPrimitiveOrNullablePrimitive -> if (declaration.isLocal) {
reporter.reportOn(declaration.source, "is not allowed on local variables of primitive types", context)
} else {
reporter.reportOn(declaration.source, "is not allowed on properties of primitive types", context)
@@ -19,9 +19,8 @@ import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.fir.types.classId
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.isPrimitive
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
@@ -35,10 +34,9 @@ object CanBeReplacedWithOperatorAssignmentChecker : FirVariableAssignmentChecker
val rValue = expression.rValue as? FirFunctionCall ?: return
if (rValue.source?.kind is FirFakeSourceElementKind) return
val rValueClassId = rValue.explicitReceiver?.typeRef?.coneType?.classId
if (rValueClassId !in StandardClassIds.primitiveTypes) return
if (rValue.explicitReceiver?.typeRef?.coneType?.isPrimitive != true) return
val rValueResolvedSymbol = rValue.toResolvedCallableSymbol() ?: return
if (rValueResolvedSymbol.dispatchReceiverClassOrNull()?.classId !in StandardClassIds.primitiveTypes) return
if (rValueResolvedSymbol.dispatchReceiverTypeOrNull()?.isPrimitive != true) return
var needToReport = false
val assignmentSource = expression.source
@@ -64,6 +64,9 @@ val ConeKotlinType.isNullableNothing: Boolean get() = isBuiltinType(StandardClas
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.isString: Boolean get() = isBuiltinType(StandardClassIds.String, false)
val ConeKotlinType.isPrimitiveOrNullablePrimitive: Boolean get() = isAnyOfBuiltinType(StandardClassIds.primitiveTypes)
val ConeKotlinType.isPrimitive: Boolean get() = isPrimitiveOrNullablePrimitive && nullability == ConeNullability.NOT_NULL
val ConeKotlinType.isArrayType: Boolean
get() {
return isBuiltinType(StandardClassIds.Array, false) ||
@@ -76,8 +79,8 @@ val ConeKotlinType.isNonPrimitiveArray: Boolean
val ConeKotlinType.isPrimitiveArray: Boolean
get() = this is ConeClassLikeType && lookupTag.classId in StandardClassIds.primitiveArrayTypeByElementType.values
private val builtinUnsignedTypes = setOf(StandardClassIds.UInt, StandardClassIds.UByte, StandardClassIds.ULong, StandardClassIds.UShort)
val ConeKotlinType.isUnsignedTypeOrNullableUnsignedType: Boolean get() = isAnyOfBuiltinType(builtinUnsignedTypes)
val ConeKotlinType.isUnsignedTypeOrNullableUnsignedType: Boolean get() = isAnyOfBuiltinType(StandardClassIds.unsignedTypes)
val ConeKotlinType.isUnsignedType: Boolean get() = isUnsignedTypeOrNullableUnsignedType && nullability == ConeNullability.NOT_NULL
private val builtinIntegerTypes = setOf(StandardClassIds.Int, StandardClassIds.Byte, StandardClassIds.Long, StandardClassIds.Short)
val ConeKotlinType.isIntegerTypeOrNullableIntegerTypeOfAnySize: Boolean get() = isAnyOfBuiltinType(builtinIntegerTypes)
@@ -369,7 +369,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
override fun SimpleTypeMarker.isPrimitiveType(): Boolean {
if (this is ConeClassLikeType) {
return StandardClassIds.primitiveTypes.contains(this.lookupTag.classId)
return isPrimitive
}
return false
}
@@ -11,6 +11,10 @@ import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.ConeIntersectionType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
fun FirCallableSymbol<*>.dispatchReceiverTypeOrNull(): ConeKotlinType? =
(fir as? FirCallableMemberDeclaration<*>)?.dispatchReceiverType
fun FirCallableSymbol<*>.dispatchReceiverClassOrNull(): ConeClassLikeLookupTag? =
(fir as? FirCallableMemberDeclaration<*>)?.dispatchReceiverClassOrNull()
@@ -63,17 +63,13 @@ object StandardClassIds {
fun reflectByName(name: String) = name.reflectId()
val primitiveTypes = listOf(
Boolean, Char,
Byte, Short, Int, Long,
Float, Double
)
val primitiveTypes = setOf(Boolean, Char, Byte, Short, Int, Long, Float, Double)
val primitiveArrayTypeByElementType = primitiveTypes.associate { id -> id to id.shortClassName.primitiveArrayId() }
val primitiveArrayTypeByElementType = primitiveTypes.associateWith { id -> id.shortClassName.primitiveArrayId() }
val elementTypeByPrimitiveArrayType = primitiveArrayTypeByElementType.inverseMap()
val unsignedTypes = listOf(UByte, UShort, UInt, ULong)
val unsignedArrayTypeByElementType = unsignedTypes.associate { id -> id to id.shortClassName.primitiveArrayId() }
val unsignedTypes = setOf(UByte, UShort, UInt, ULong)
val unsignedArrayTypeByElementType = unsignedTypes.associateWith { id -> id.shortClassName.primitiveArrayId() }
val elementTypeByUnsignedArrayType = unsignedArrayTypeByElementType.inverseMap()
val constantAllowedTypes = primitiveTypes + unsignedTypes + String