mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-10 08:31:29 +00:00
[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.Name
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.foldMap
|
||||
|
||||
enum class ProjectionKind {
|
||||
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
|
||||
// (more exactly, invariant type projection contains type)
|
||||
sealed class ConeKotlinType : ConeKotlinTypeProjection(),
|
||||
KotlinTypeMarker,
|
||||
TypeArgumentListMarker {
|
||||
sealed class ConeKotlinType : ConeKotlinTypeProjection(), KotlinTypeMarker, TypeArgumentListMarker {
|
||||
override val kind: ProjectionKind
|
||||
get() = ProjectionKind.INVARIANT
|
||||
|
||||
@@ -63,6 +62,8 @@ sealed class ConeKotlinType : ConeKotlinTypeProjection(),
|
||||
|
||||
abstract val nullability: ConeNullability
|
||||
|
||||
abstract val attributes: ConeAttributes
|
||||
|
||||
final override fun toString(): String {
|
||||
return render()
|
||||
}
|
||||
@@ -91,6 +92,9 @@ class ConeClassErrorType(val reason: String) : ConeClassLikeType() {
|
||||
override val nullability: ConeNullability
|
||||
get() = ConeNullability.UNKNOWN
|
||||
|
||||
override val attributes: ConeAttributes
|
||||
get() = ConeAttributes.Empty
|
||||
|
||||
override fun equals(other: Any?) = this === other
|
||||
override fun hashCode(): Int = System.identityHashCode(this)
|
||||
}
|
||||
@@ -103,8 +107,10 @@ abstract class ConeClassLikeType : ConeLookupTagBasedType() {
|
||||
abstract override val lookupTag: ConeClassLikeLookupTag
|
||||
}
|
||||
|
||||
open class ConeFlexibleType(val lowerBound: ConeKotlinType, val upperBound: ConeKotlinType) : ConeKotlinType(),
|
||||
FlexibleTypeMarker {
|
||||
open class ConeFlexibleType(
|
||||
val lowerBound: ConeKotlinType,
|
||||
val upperBound: ConeKotlinType
|
||||
) : ConeKotlinType(), FlexibleTypeMarker {
|
||||
|
||||
init {
|
||||
val message = { "Bounds violation: $lowerBound, $upperBound" }
|
||||
@@ -118,6 +124,9 @@ open class ConeFlexibleType(val lowerBound: ConeKotlinType, val upperBound: Cone
|
||||
override val nullability: ConeNullability
|
||||
get() = lowerBound.nullability.takeIf { it == upperBound.nullability } ?: ConeNullability.UNKNOWN
|
||||
|
||||
override val attributes: ConeAttributes
|
||||
get() = lowerBound.attributes
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
@@ -151,7 +160,8 @@ data class ConeCapturedType(
|
||||
val captureStatus: CaptureStatus,
|
||||
val lowerType: ConeKotlinType?,
|
||||
override val nullability: ConeNullability = ConeNullability.NOT_NULL,
|
||||
val constructor: ConeCapturedTypeConstructor
|
||||
val constructor: ConeCapturedTypeConstructor,
|
||||
override val attributes: ConeAttributes = ConeAttributes.Empty
|
||||
) : ConeSimpleKotlinType(), CapturedTypeMarker {
|
||||
constructor(
|
||||
captureStatus: CaptureStatus, lowerType: ConeKotlinType?, projection: ConeTypeProjection,
|
||||
@@ -197,14 +207,20 @@ data class ConeTypeVariableType(
|
||||
override val lookupTag: ConeClassifierLookupTag
|
||||
) : ConeLookupTagBasedType() {
|
||||
override val typeArguments: Array<out ConeTypeProjection> get() = emptyArray()
|
||||
|
||||
override val attributes: ConeAttributes get() = ConeAttributes.Empty
|
||||
}
|
||||
|
||||
data class ConeDefinitelyNotNullType(val original: ConeKotlinType) : ConeSimpleKotlinType(), DefinitelyNotNullTypeMarker {
|
||||
override val typeArguments: Array<out ConeTypeProjection>
|
||||
get() = original.typeArguments
|
||||
|
||||
override val nullability: ConeNullability
|
||||
get() = ConeNullability.NOT_NULL
|
||||
|
||||
override val attributes: ConeAttributes
|
||||
get() = ConeAttributes.Empty
|
||||
|
||||
companion object
|
||||
}
|
||||
|
||||
@@ -225,6 +241,11 @@ class ConeIntersectionType(
|
||||
override val nullability: ConeNullability
|
||||
get() = ConeNullability.NOT_NULL
|
||||
|
||||
override val attributes: ConeAttributes = intersectedTypes.foldMap(
|
||||
{ it.attributes },
|
||||
{ a, b -> a.union(b) }
|
||||
)
|
||||
|
||||
private var hashCode = 0
|
||||
|
||||
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>
|
||||
get() = emptyArray()
|
||||
|
||||
override val attributes: ConeAttributes
|
||||
get() = ConeAttributes.Empty
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.types.impl
|
||||
|
||||
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.ConeTypeProjection
|
||||
import org.jetbrains.kotlin.fir.types.ConeNullability
|
||||
@@ -13,7 +14,8 @@ import org.jetbrains.kotlin.fir.types.ConeNullability
|
||||
class ConeClassLikeTypeImpl(
|
||||
override val lookupTag: ConeClassLikeLookupTag,
|
||||
override val typeArguments: Array<out ConeTypeProjection>,
|
||||
isNullable: Boolean
|
||||
isNullable: Boolean,
|
||||
override val attributes: ConeAttributes = ConeAttributes.Empty
|
||||
) : ConeClassLikeType() {
|
||||
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?
|
||||
}
|
||||
|
||||
fun ArrayMap<*>.isEmpty(): Boolean = size == 0
|
||||
fun ArrayMap<*>.isNotEmpty(): Boolean = size != 0
|
||||
|
||||
internal object EmptyArrayMap : ArrayMap<Nothing>() {
|
||||
override val size: Int
|
||||
get() = 0
|
||||
|
||||
@@ -59,4 +59,7 @@ abstract class TypeRegistry<K : Any, V : Any> {
|
||||
fun <T : K> getId(kClass: KClass<T>): Int {
|
||||
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 {
|
||||
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) {
|
||||
possibleTypes = mutableListOf()
|
||||
|
||||
|
||||
@@ -6,13 +6,15 @@
|
||||
package org.jetbrains.kotlin.fir.types.impl
|
||||
|
||||
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.ConeNullability
|
||||
import org.jetbrains.kotlin.fir.types.ConeTypeParameterType
|
||||
|
||||
class ConeTypeParameterTypeImpl(
|
||||
override val lookupTag: ConeTypeParameterLookupTag,
|
||||
isNullable: Boolean
|
||||
isNullable: Boolean,
|
||||
override val attributes: ConeAttributes = ConeAttributes.Empty
|
||||
) : ConeTypeParameterType() {
|
||||
override val typeArguments: Array<out ConeTypeProjection>
|
||||
get() = EMPTY_ARRAY
|
||||
|
||||
@@ -163,4 +163,13 @@ inline fun <T, R> Iterable<T>.same(extractor: (T) -> R): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
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