Support constant evaluation of unsigned type constructors

#KT-23816 In Progress
This commit is contained in:
Mikhail Zarechenskiy
2018-05-21 17:30:30 +03:00
parent bf5f710f39
commit 656f6cbded
24 changed files with 569 additions and 11 deletions
@@ -69,12 +69,14 @@ class TypeMappingMode private constructor(
/**
* kotlin.reflect.KClass mapped to java.lang.Class
* primitive types and inline class types are not boxed because types in annotations cannot be nullable
* Other types mapped as DEFAULT
*/
@JvmField
val VALUE_FOR_ANNOTATION = TypeMappingMode(
isForAnnotationParameter = true,
needPrimitiveBoxing = false,
needInlineClassWrapping = false,
genericArgumentMode = TypeMappingMode(isForAnnotationParameter = true, genericArgumentMode = GENERIC_ARGUMENT))
@@ -0,0 +1,35 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. 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.builtins
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType
import kotlin.reflect.KClass
enum class UnsignedType(val typeName: Name) {
UBYTE("UByte"), USHORT("UShort"), UINT("UInt"), ULONG("ULong");
constructor(typeName: String) : this(Name.identifier(typeName))
}
object UnsignedTypes {
val unsignedTypeNames = enumValues<UnsignedType>().map { it.typeName }.toSet()
fun isUnsignedType(type: KotlinType): Boolean {
val descriptor = type.constructor.declarationDescriptor ?: return false
return isUnsignedClass(descriptor)
}
fun isUnsignedClass(descriptor: DeclarationDescriptor): Boolean {
val container = descriptor.containingDeclaration
return container is PackageFragmentDescriptor &&
container.fqName == KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME &&
descriptor.name in UnsignedTypes.unsignedTypeNames
}
}
@@ -19,6 +19,7 @@
package org.jetbrains.kotlin.descriptors
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.UnsignedTypes
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
@@ -26,4 +27,6 @@ object ConstUtil {
@JvmStatic fun canBeUsedForConstVal(type: KotlinType) = type.canBeUsedForConstVal()
}
fun KotlinType.canBeUsedForConstVal() = KotlinBuiltIns.isPrimitiveType(this) && !TypeUtils.isNullableType(this) || KotlinBuiltIns.isString(this)
fun KotlinType.canBeUsedForConstVal() =
(KotlinBuiltIns.isPrimitiveType(this) || UnsignedTypes.isUnsignedType(this)) && !TypeUtils.isNullableType(this) ||
KotlinBuiltIns.isString(this)
@@ -50,4 +50,12 @@ public interface AnnotationArgumentVisitor<R, D> {
R visitAnnotationValue(AnnotationValue value, D data);
R visitKClassValue(KClassValue value, D data);
R visitUByteValue(UByteValue value, D data);
R visitUShortValue(UShortValue value, D data);
R visitUIntValue(UIntValue value, D data);
R visitULongValue(ULongValue value, D data);
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.resolve;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.builtins.UnsignedTypes;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotated;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
@@ -457,7 +458,8 @@ public class DescriptorUtils {
return KotlinBuiltIns.isPrimitiveType(type) ||
KotlinTypeChecker.DEFAULT.equalTypes(builtIns.getStringType(), type) ||
KotlinTypeChecker.DEFAULT.equalTypes(builtIns.getNumber().getDefaultType(), type) ||
KotlinTypeChecker.DEFAULT.equalTypes(builtIns.getAnyType(), type);
KotlinTypeChecker.DEFAULT.equalTypes(builtIns.getAnyType(), type) ||
UnsignedTypes.INSTANCE.isUnsignedType(type);
}
public static boolean classCanHaveAbstractFakeOverride(@NotNull ClassDescriptor classDescriptor) {
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.constants
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.UnsignedType
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
@@ -48,6 +49,16 @@ object ConstantValueFactory {
}
}
fun createUnsignedValue(constantValue: ConstantValue<*>, type: KotlinType): UnsignedValueConstant<*>? {
return when (constantValue) {
is ByteValue -> UByteValue(constantValue, type)
is ShortValue -> UShortValue(constantValue, type)
is IntValue -> UIntValue(constantValue, type)
is LongValue -> ULongValue(constantValue, type)
else -> null
}
}
private fun createArrayValue(value: List<*>, componentType: PrimitiveType): ArrayValue =
ArrayValue(value.toList().mapNotNull(this::createConstantValue)) { module ->
module.builtIns.getPrimitiveArrayKotlinType(componentType)
@@ -40,6 +40,9 @@ abstract class ConstantValue<out T>(open val value: T) {
}
abstract class IntegerValueConstant<out T> protected constructor(value: T) : ConstantValue<T>(value)
abstract class UnsignedValueConstant<out T> protected constructor(value: T, private val kotlinType: KotlinType) : ConstantValue<T>(value) {
override fun getType(module: ModuleDescriptor): KotlinType = kotlinType
}
class AnnotationValue(value: AnnotationDescriptor) : ConstantValue<AnnotationDescriptor>(value) {
override fun getType(module: ModuleDescriptor): KotlinType = value.type
@@ -189,3 +192,27 @@ class StringValue(value: String) : ConstantValue<String>(value) {
override fun toString() = "\"$value\""
}
class UByteValue(byteValue: ByteValue, kotlinType: KotlinType) : UnsignedValueConstant<Byte>(byteValue.value, kotlinType) {
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitUByteValue(this, data)
override fun toString() = "$value.toUByte()"
}
class UShortValue(shortValue: ShortValue, kotlinType: KotlinType) : UnsignedValueConstant<Short>(shortValue.value, kotlinType) {
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitUShortValue(this, data)
override fun toString() = "$value.toUShort()"
}
class UIntValue(intValue: IntValue, kotlinType: KotlinType) : UnsignedValueConstant<Int>(intValue.value, kotlinType) {
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitUIntValue(this, data)
override fun toString() = "$value.toUInt()"
}
class ULongValue(longValue: LongValue, kotlinType: KotlinType) : UnsignedValueConstant<Long>(longValue.value, kotlinType) {
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitULongValue(this, data)
override fun toString() = "$value.toULong()"
}