From 632a9d66d1d8e6ecf2299c895e87d004e0ded9ca Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Fri, 7 May 2021 15:59:24 +0300 Subject: [PATCH] FIR: introduce isPrimitive / isPrimitiveOrNullablePrimitive helpers --- .../checkers/ConeTypeCompatibilityChecker.kt | 2 +- .../kotlin/fir/analysis/checkers/FirConstChecks.kt | 10 +--------- .../FirAnnotationClassDeclarationChecker.kt | 6 ++---- .../declaration/FirInapplicableLateinitChecker.kt | 3 +-- .../CanBeReplacedWithOperatorAssignmentChecker.kt | 8 +++----- .../org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt | 7 +++++-- .../jetbrains/kotlin/fir/types/ConeTypeContext.kt | 2 +- .../src/org/jetbrains/kotlin/fir/ClassMembers.kt | 4 ++++ .../org/jetbrains/kotlin/name/StandardClassIds.kt | 12 ++++-------- 9 files changed, 22 insertions(+), 32 deletions(-) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/ConeTypeCompatibilityChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/ConeTypeCompatibilityChecker.kt index f761e7f53cd..990b195d0eb 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/ConeTypeCompatibilityChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/ConeTypeCompatibilityChecker.kt @@ -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() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConstChecks.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConstChecks.kt index a760d6e7d8a..5ad8756c38d 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConstChecks.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConstChecks.kt @@ -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, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationClassDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationClassDeclarationChecker.kt index caf8ade30dd..baafba7e1e9 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationClassDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationClassDeclarationChecker.kt @@ -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 -> { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInapplicableLateinitChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInapplicableLateinitChecker.kt index a05c55bd9da..8b2135c7b96 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInapplicableLateinitChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInapplicableLateinitChecker.kt @@ -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) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeReplacedWithOperatorAssignmentChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeReplacedWithOperatorAssignmentChecker.kt index c9b198d64fa..3af12232410 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeReplacedWithOperatorAssignmentChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeReplacedWithOperatorAssignmentChecker.kt @@ -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 diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt index 3d0a5e17233..0629b940beb 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt @@ -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) 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 48c37d781f8..df4b38a912d 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 @@ -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 } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/ClassMembers.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/ClassMembers.kt index 47236efb14b..60e1d4705f2 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/ClassMembers.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/ClassMembers.kt @@ -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() diff --git a/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt b/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt index fe5859e1c70..99d11987b2f 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt @@ -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