[FIR] Add ConeAttributes to ConeKotlinType
This commit is contained in:
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* 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.utils.AttributeArrayOwner
|
||||||
|
import org.jetbrains.kotlin.fir.utils.TypeRegistry
|
||||||
|
import org.jetbrains.kotlin.fir.utils.isEmpty
|
||||||
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
import kotlin.properties.ReadOnlyProperty
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
abstract class ConeAttribute<T : ConeAttribute<T>> {
|
||||||
|
abstract fun union(other: @UnsafeVariance T?): T?
|
||||||
|
abstract fun intersect(other: @UnsafeVariance T?): T?
|
||||||
|
abstract fun isSubtypeOf(other: @UnsafeVariance T?): Boolean
|
||||||
|
|
||||||
|
abstract val key: KClass<out T>
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConeAttributes private constructor(attributes: List<ConeAttribute<*>>) : AttributeArrayOwner<ConeAttribute<*>, ConeAttribute<*>>() {
|
||||||
|
companion object : TypeRegistry<ConeAttribute<*>, ConeAttribute<*>>() {
|
||||||
|
inline fun <reified T : ConeAttribute<T>> attributeAccessor(): ReadOnlyProperty<ConeAttributes, T?> {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return generateNullableAccessor<ConeAttribute<*>, T>(T::class) as ReadOnlyProperty<ConeAttributes, T?>
|
||||||
|
}
|
||||||
|
|
||||||
|
val Empty: ConeAttributes = ConeAttributes(emptyList())
|
||||||
|
|
||||||
|
fun create(attributes: List<ConeAttribute<*>>): ConeAttributes {
|
||||||
|
return if (attributes.isEmpty()) {
|
||||||
|
Empty
|
||||||
|
} else {
|
||||||
|
ConeAttributes(attributes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
for (attribute in attributes) {
|
||||||
|
registerComponent(attribute.key, attribute)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun union(other: ConeAttributes): ConeAttributes {
|
||||||
|
return perform(other) { this.union(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun intersect(other: ConeAttributes): ConeAttributes {
|
||||||
|
return perform(other) { this.intersect(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun perform(other: ConeAttributes, op: ConeAttribute<*>.(ConeAttribute<*>?) -> ConeAttribute<*>?): ConeAttributes {
|
||||||
|
if (this.isEmpty() && other.isEmpty()) return this
|
||||||
|
val attributes = mutableListOf<ConeAttribute<*>>()
|
||||||
|
for (index in indices) {
|
||||||
|
val a = arrayMap[index]
|
||||||
|
val b = other.arrayMap[index]
|
||||||
|
val res = when {
|
||||||
|
a == null -> b?.op(a)
|
||||||
|
else -> a.op(b)
|
||||||
|
}
|
||||||
|
attributes.addIfNotNull(res)
|
||||||
|
}
|
||||||
|
return create(attributes)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val typeRegistry: TypeRegistry<ConeAttribute<*>, ConeAttribute<*>>
|
||||||
|
get() = Companion
|
||||||
|
|
||||||
|
private fun isEmpty(): Boolean {
|
||||||
|
return arrayMap.isEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
|
|||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.model.*
|
import org.jetbrains.kotlin.types.model.*
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.foldMap
|
||||||
|
|
||||||
enum class ProjectionKind {
|
enum class ProjectionKind {
|
||||||
STAR, IN, OUT, INVARIANT;
|
STAR, IN, OUT, INVARIANT;
|
||||||
@@ -50,9 +51,7 @@ data class ConeKotlinTypeProjectionOut(override val type: ConeKotlinType) : Cone
|
|||||||
|
|
||||||
// We assume type IS an invariant type projection to prevent additional wrapper here
|
// We assume type IS an invariant type projection to prevent additional wrapper here
|
||||||
// (more exactly, invariant type projection contains type)
|
// (more exactly, invariant type projection contains type)
|
||||||
sealed class ConeKotlinType : ConeKotlinTypeProjection(),
|
sealed class ConeKotlinType : ConeKotlinTypeProjection(), KotlinTypeMarker, TypeArgumentListMarker {
|
||||||
KotlinTypeMarker,
|
|
||||||
TypeArgumentListMarker {
|
|
||||||
override val kind: ProjectionKind
|
override val kind: ProjectionKind
|
||||||
get() = ProjectionKind.INVARIANT
|
get() = ProjectionKind.INVARIANT
|
||||||
|
|
||||||
@@ -63,6 +62,8 @@ sealed class ConeKotlinType : ConeKotlinTypeProjection(),
|
|||||||
|
|
||||||
abstract val nullability: ConeNullability
|
abstract val nullability: ConeNullability
|
||||||
|
|
||||||
|
abstract val attributes: ConeAttributes
|
||||||
|
|
||||||
final override fun toString(): String {
|
final override fun toString(): String {
|
||||||
return render()
|
return render()
|
||||||
}
|
}
|
||||||
@@ -91,6 +92,9 @@ class ConeClassErrorType(val reason: String) : ConeClassLikeType() {
|
|||||||
override val nullability: ConeNullability
|
override val nullability: ConeNullability
|
||||||
get() = ConeNullability.UNKNOWN
|
get() = ConeNullability.UNKNOWN
|
||||||
|
|
||||||
|
override val attributes: ConeAttributes
|
||||||
|
get() = ConeAttributes.Empty
|
||||||
|
|
||||||
override fun equals(other: Any?) = this === other
|
override fun equals(other: Any?) = this === other
|
||||||
override fun hashCode(): Int = System.identityHashCode(this)
|
override fun hashCode(): Int = System.identityHashCode(this)
|
||||||
}
|
}
|
||||||
@@ -103,8 +107,10 @@ abstract class ConeClassLikeType : ConeLookupTagBasedType() {
|
|||||||
abstract override val lookupTag: ConeClassLikeLookupTag
|
abstract override val lookupTag: ConeClassLikeLookupTag
|
||||||
}
|
}
|
||||||
|
|
||||||
open class ConeFlexibleType(val lowerBound: ConeKotlinType, val upperBound: ConeKotlinType) : ConeKotlinType(),
|
open class ConeFlexibleType(
|
||||||
FlexibleTypeMarker {
|
val lowerBound: ConeKotlinType,
|
||||||
|
val upperBound: ConeKotlinType
|
||||||
|
) : ConeKotlinType(), FlexibleTypeMarker {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val message = { "Bounds violation: $lowerBound, $upperBound" }
|
val message = { "Bounds violation: $lowerBound, $upperBound" }
|
||||||
@@ -118,6 +124,9 @@ open class ConeFlexibleType(val lowerBound: ConeKotlinType, val upperBound: Cone
|
|||||||
override val nullability: ConeNullability
|
override val nullability: ConeNullability
|
||||||
get() = lowerBound.nullability.takeIf { it == upperBound.nullability } ?: ConeNullability.UNKNOWN
|
get() = lowerBound.nullability.takeIf { it == upperBound.nullability } ?: ConeNullability.UNKNOWN
|
||||||
|
|
||||||
|
override val attributes: ConeAttributes
|
||||||
|
get() = lowerBound.attributes
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
if (javaClass != other?.javaClass) return false
|
if (javaClass != other?.javaClass) return false
|
||||||
@@ -151,7 +160,8 @@ data class ConeCapturedType(
|
|||||||
val captureStatus: CaptureStatus,
|
val captureStatus: CaptureStatus,
|
||||||
val lowerType: ConeKotlinType?,
|
val lowerType: ConeKotlinType?,
|
||||||
override val nullability: ConeNullability = ConeNullability.NOT_NULL,
|
override val nullability: ConeNullability = ConeNullability.NOT_NULL,
|
||||||
val constructor: ConeCapturedTypeConstructor
|
val constructor: ConeCapturedTypeConstructor,
|
||||||
|
override val attributes: ConeAttributes = ConeAttributes.Empty
|
||||||
) : ConeSimpleKotlinType(), CapturedTypeMarker {
|
) : ConeSimpleKotlinType(), CapturedTypeMarker {
|
||||||
constructor(
|
constructor(
|
||||||
captureStatus: CaptureStatus, lowerType: ConeKotlinType?, projection: ConeTypeProjection,
|
captureStatus: CaptureStatus, lowerType: ConeKotlinType?, projection: ConeTypeProjection,
|
||||||
@@ -197,14 +207,20 @@ data class ConeTypeVariableType(
|
|||||||
override val lookupTag: ConeClassifierLookupTag
|
override val lookupTag: ConeClassifierLookupTag
|
||||||
) : ConeLookupTagBasedType() {
|
) : ConeLookupTagBasedType() {
|
||||||
override val typeArguments: Array<out ConeTypeProjection> get() = emptyArray()
|
override val typeArguments: Array<out ConeTypeProjection> get() = emptyArray()
|
||||||
|
|
||||||
|
override val attributes: ConeAttributes get() = ConeAttributes.Empty
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ConeDefinitelyNotNullType(val original: ConeKotlinType) : ConeSimpleKotlinType(), DefinitelyNotNullTypeMarker {
|
data class ConeDefinitelyNotNullType(val original: ConeKotlinType) : ConeSimpleKotlinType(), DefinitelyNotNullTypeMarker {
|
||||||
override val typeArguments: Array<out ConeTypeProjection>
|
override val typeArguments: Array<out ConeTypeProjection>
|
||||||
get() = original.typeArguments
|
get() = original.typeArguments
|
||||||
|
|
||||||
override val nullability: ConeNullability
|
override val nullability: ConeNullability
|
||||||
get() = ConeNullability.NOT_NULL
|
get() = ConeNullability.NOT_NULL
|
||||||
|
|
||||||
|
override val attributes: ConeAttributes
|
||||||
|
get() = ConeAttributes.Empty
|
||||||
|
|
||||||
companion object
|
companion object
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,6 +241,11 @@ class ConeIntersectionType(
|
|||||||
override val nullability: ConeNullability
|
override val nullability: ConeNullability
|
||||||
get() = ConeNullability.NOT_NULL
|
get() = ConeNullability.NOT_NULL
|
||||||
|
|
||||||
|
override val attributes: ConeAttributes = intersectedTypes.foldMap(
|
||||||
|
{ it.attributes },
|
||||||
|
{ a, b -> a.union(b) }
|
||||||
|
)
|
||||||
|
|
||||||
private var hashCode = 0
|
private var hashCode = 0
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
@@ -253,6 +274,9 @@ class ConeStubType(val variable: ConeTypeVariable, override val nullability: Con
|
|||||||
override val typeArguments: Array<out ConeTypeProjection>
|
override val typeArguments: Array<out ConeTypeProjection>
|
||||||
get() = emptyArray()
|
get() = emptyArray()
|
||||||
|
|
||||||
|
override val attributes: ConeAttributes
|
||||||
|
get() = ConeAttributes.Empty
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
if (javaClass != other?.javaClass) return false
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.fir.types.impl
|
package org.jetbrains.kotlin.fir.types.impl
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeAttributes
|
||||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||||
import org.jetbrains.kotlin.fir.types.ConeTypeProjection
|
import org.jetbrains.kotlin.fir.types.ConeTypeProjection
|
||||||
import org.jetbrains.kotlin.fir.types.ConeNullability
|
import org.jetbrains.kotlin.fir.types.ConeNullability
|
||||||
@@ -13,7 +14,8 @@ import org.jetbrains.kotlin.fir.types.ConeNullability
|
|||||||
class ConeClassLikeTypeImpl(
|
class ConeClassLikeTypeImpl(
|
||||||
override val lookupTag: ConeClassLikeLookupTag,
|
override val lookupTag: ConeClassLikeLookupTag,
|
||||||
override val typeArguments: Array<out ConeTypeProjection>,
|
override val typeArguments: Array<out ConeTypeProjection>,
|
||||||
isNullable: Boolean
|
isNullable: Boolean,
|
||||||
|
override val attributes: ConeAttributes = ConeAttributes.Empty
|
||||||
) : ConeClassLikeType() {
|
) : ConeClassLikeType() {
|
||||||
override val nullability: ConeNullability = ConeNullability.create(isNullable)
|
override val nullability: ConeNullability = ConeNullability.create(isNullable)
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ sealed class ArrayMap<T : Any> : Iterable<T> {
|
|||||||
abstract operator fun get(index: Int): T?
|
abstract operator fun get(index: Int): T?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ArrayMap<*>.isEmpty(): Boolean = size == 0
|
||||||
|
fun ArrayMap<*>.isNotEmpty(): Boolean = size != 0
|
||||||
|
|
||||||
internal object EmptyArrayMap : ArrayMap<Nothing>() {
|
internal object EmptyArrayMap : ArrayMap<Nothing>() {
|
||||||
override val size: Int
|
override val size: Int
|
||||||
get() = 0
|
get() = 0
|
||||||
|
|||||||
@@ -59,4 +59,7 @@ abstract class TypeRegistry<K : Any, V : Any> {
|
|||||||
fun <T : K> getId(kClass: KClass<T>): Int {
|
fun <T : K> getId(kClass: KClass<T>): Int {
|
||||||
return idPerType.getOrPut(kClass) { idPerType.size }
|
return idPerType.getOrPut(kClass) { idPerType.size }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected val indices: Collection<Int>
|
||||||
|
get() = idPerType.values
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
|||||||
class ConeIntegerLiteralTypeImpl : ConeIntegerLiteralType {
|
class ConeIntegerLiteralTypeImpl : ConeIntegerLiteralType {
|
||||||
override val possibleTypes: Collection<ConeClassLikeType>
|
override val possibleTypes: Collection<ConeClassLikeType>
|
||||||
|
|
||||||
|
override val attributes: ConeAttributes
|
||||||
|
get() = ConeAttributes.Empty
|
||||||
|
|
||||||
constructor(value: Long, isUnsigned: Boolean, nullability: ConeNullability = ConeNullability.NOT_NULL) : super(value, isUnsigned, nullability) {
|
constructor(value: Long, isUnsigned: Boolean, nullability: ConeNullability = ConeNullability.NOT_NULL) : super(value, isUnsigned, nullability) {
|
||||||
possibleTypes = mutableListOf()
|
possibleTypes = mutableListOf()
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -6,13 +6,15 @@
|
|||||||
package org.jetbrains.kotlin.fir.types.impl
|
package org.jetbrains.kotlin.fir.types.impl
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeAttributes
|
||||||
import org.jetbrains.kotlin.fir.types.ConeTypeProjection
|
import org.jetbrains.kotlin.fir.types.ConeTypeProjection
|
||||||
import org.jetbrains.kotlin.fir.types.ConeNullability
|
import org.jetbrains.kotlin.fir.types.ConeNullability
|
||||||
import org.jetbrains.kotlin.fir.types.ConeTypeParameterType
|
import org.jetbrains.kotlin.fir.types.ConeTypeParameterType
|
||||||
|
|
||||||
class ConeTypeParameterTypeImpl(
|
class ConeTypeParameterTypeImpl(
|
||||||
override val lookupTag: ConeTypeParameterLookupTag,
|
override val lookupTag: ConeTypeParameterLookupTag,
|
||||||
isNullable: Boolean
|
isNullable: Boolean,
|
||||||
|
override val attributes: ConeAttributes = ConeAttributes.Empty
|
||||||
) : ConeTypeParameterType() {
|
) : ConeTypeParameterType() {
|
||||||
override val typeArguments: Array<out ConeTypeProjection>
|
override val typeArguments: Array<out ConeTypeProjection>
|
||||||
get() = EMPTY_ARRAY
|
get() = EMPTY_ARRAY
|
||||||
|
|||||||
@@ -164,3 +164,12 @@ inline fun <T, R> Iterable<T>.same(extractor: (T) -> R): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline fun <R> runIf(condition: Boolean, block: () -> R): R? = if (condition) block() else null
|
inline fun <R> runIf(condition: Boolean, block: () -> R): R? = if (condition) block() else null
|
||||||
|
|
||||||
|
inline fun <T, R> Collection<T>.foldMap(transform: (T) -> R, operation: (R, R) -> R): R {
|
||||||
|
val iterator = iterator()
|
||||||
|
var result = transform(iterator.next())
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
result = operation(result, transform(iterator.next()))
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user