[IR BE] Use pure IrType instead of KotlinType

* clean up code
This commit is contained in:
Roman Artemev
2019-03-18 19:17:56 +03:00
committed by romanart
parent 1823ba1c48
commit 2ed29d8869
39 changed files with 249 additions and 695 deletions
@@ -170,6 +170,8 @@ class IrBuiltIns(
val throwableType by lazy { builtIns.throwable.defaultType.toIrType() }
val throwableClass by lazy { builtIns.throwable.toIrSymbol() }
val primitiveIrTypes by lazy { listOf(booleanType, charType, byteType, shortType, intType, floatType, longType, doubleType) }
val kCallableClass = builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.kCallable.toSafe()).toIrSymbol()
val kPropertyClass = builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.kPropertyFqName.toSafe()).toIrSymbol()
@@ -43,6 +43,24 @@ fun IrType.isEqualTo(that: IrType): Boolean {
return false
}
fun IrTypeArgument.toHashCode(): Int = when (this) {
is IrTypeProjection -> 31 * type.toHashCode() + variance.hashCode()
is IrStarProjection -> hashCode()
else -> 0
}
fun IrType.toHashCode(): Int {
if (this is IrDynamicType) return -1
if (this is IrErrorType) return 0
require(this is IrSimpleType)
var result = classifier.hashCode()
result = 31 * result + arguments.fold(0) { a, t -> 31 * a + t.toHashCode() }
return 31 * result + if (hasQuestionMark) 1 else 0
}
fun Collection<IrClassifierSymbol>.commonSuperclass(): IrClassifierSymbol {
var superClassifiers: MutableSet<IrClassifierSymbol>? = null
@@ -56,7 +56,7 @@ fun makeTypeProjection(type: IrType, variance: Variance): IrTypeProjection =
when {
type is IrTypeProjection && type.variance == variance -> type
type is IrSimpleType -> IrSimpleTypeImpl(type, variance)
type is IrDynamicType -> IrDynamicTypeImpl(type.originalKotlinType, type.annotations, variance)
type is IrErrorType -> IrErrorTypeImpl(type.originalKotlinType, type.annotations, variance)
type is IrDynamicType -> IrDynamicTypeImpl(null, type.annotations, variance)
type is IrErrorType -> IrErrorTypeImpl(null, type.annotations, variance)
else -> IrTypeProjectionImpl(type, variance)
}
@@ -7,17 +7,12 @@ package org.jetbrains.kotlin.ir.types
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.util.getFqName
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.resolve.DescriptorUtils.getFqName
private fun IrType.isBuiltInClassType(descriptorPredicate: (ClassDescriptor) -> Boolean, hasQuestionMark: Boolean): Boolean {
if (this !is IrSimpleType) return false
if (this.hasQuestionMark != hasQuestionMark) return false
val classSymbol = this.classifier as? IrClassSymbol ?: return false
return descriptorPredicate(classSymbol.descriptor)
}
private fun IrType.isNotNullClassType(fqName: FqNameUnsafe) = isClassType(fqName, hasQuestionMark = false)
private fun IrType.isNullableClassType(fqName: FqNameUnsafe) = isClassType(fqName, hasQuestionMark = true)
@@ -25,25 +20,29 @@ private fun IrType.isClassType(fqName: FqNameUnsafe, hasQuestionMark: Boolean):
if (this !is IrSimpleType) return false
if (this.hasQuestionMark != hasQuestionMark) return false
val classSymbol = this.classifier as? IrClassSymbol ?: return false
return classFqNameEquals(classSymbol.descriptor, fqName)
return classFqNameEquals(classSymbol, fqName)
}
private fun classFqNameEquals(symbol: IrClassSymbol, fqName: FqNameUnsafe): Boolean =
if (symbol.isBound) classFqNameEquals(symbol.owner, fqName) else classFqNameEquals(symbol.descriptor, fqName)
private fun classFqNameEquals(declaration: IrClass, fqName: FqNameUnsafe): Boolean =
declaration.name == fqName.shortName() && fqName == declaration.getFqName()?.toUnsafe()
private fun classFqNameEquals(descriptor: ClassDescriptor, fqName: FqNameUnsafe): Boolean =
descriptor.name == fqName.shortName() && fqName == getFqName(descriptor)
fun IrType.isAny(): Boolean = isBuiltInClassType(KotlinBuiltIns::isAny, hasQuestionMark = false)
fun IrType.isNullableAny(): Boolean = isBuiltInClassType(KotlinBuiltIns::isAny, hasQuestionMark = true)
fun IrType.isAny(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES.any)
fun IrType.isNullableAny(): Boolean = isNullableClassType(KotlinBuiltIns.FQ_NAMES.any)
fun IrType.isString(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES.string)
fun IrType.isNullableString(): Boolean = isNullableClassType(KotlinBuiltIns.FQ_NAMES.string)
fun IrType.isArray(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES.array)
fun IrType.isCollection(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES.collection.toUnsafe())
fun IrType.isNothing(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES.nothing)
fun IrType.isPrimitiveType(): Boolean =
isBuiltInClassType(KotlinBuiltIns::isPrimitiveClass, hasQuestionMark = false)
fun IrType.isNullablePrimitiveType(): Boolean =
isBuiltInClassType(KotlinBuiltIns::isPrimitiveClass, hasQuestionMark = true)
fun IrType.isPrimitiveType(): Boolean = KotlinBuiltIns.FQ_NAMES.fqNameToPrimitiveType.keys.any { isNotNullClassType(it) }
fun IrType.isNullablePrimitiveType(): Boolean = KotlinBuiltIns.FQ_NAMES.fqNameToPrimitiveType.keys.any { isNullableClassType(it) }
fun IrType.isMarkedNullable() = (this as? IrSimpleType)?.hasQuestionMark ?: false
@@ -5,11 +5,9 @@
package org.jetbrains.kotlin.ir.types
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
@@ -19,6 +17,8 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.impl.*
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.types.typeUtil.makeNullable
import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -29,7 +29,7 @@ fun IrType.withHasQuestionMark(hasQuestionMark: Boolean): IrType =
this
else
IrSimpleTypeImpl(
makeKotlinType(classifier, arguments, hasQuestionMark),
originalKotlinType?.run { if (hasQuestionMark) makeNullable() else makeNotNullable() },
classifier,
hasQuestionMark,
arguments,
@@ -44,23 +44,23 @@ val IrType.classifierOrFail: IrClassifierSymbol
val IrType.classifierOrNull: IrClassifierSymbol?
get() = safeAs<IrSimpleType>()?.classifier
fun IrType.makeNotNull(addKotlinType:Boolean = true) =
if (this is IrSimpleType && this.hasQuestionMark)
fun IrType.makeNotNull() =
if (this is IrSimpleType && this.hasQuestionMark) {
IrSimpleTypeImpl(
if (addKotlinType) makeKotlinType(classifier, arguments, false) else null,
originalKotlinType?.makeNotNullable(),
classifier,
false,
arguments,
annotations,
Variance.INVARIANT
)
else
} else
this
fun IrType.makeNullable(addKotlinType:Boolean = true) =
fun IrType.makeNullable() =
if (this is IrSimpleType && !this.hasQuestionMark)
IrSimpleTypeImpl(
if (addKotlinType) makeKotlinType(classifier, arguments, true) else null,
originalKotlinType?.makeNullable(),
classifier,
true,
arguments,
@@ -70,9 +70,6 @@ fun IrType.makeNullable(addKotlinType:Boolean = true) =
else
this
// TODO: get rid of this
var irTypeKotlinBuiltIns: KotlinBuiltIns? = null
fun IrType.toKotlinType(): KotlinType {
originalKotlinType?.let {
return it
@@ -80,7 +77,6 @@ fun IrType.toKotlinType(): KotlinType {
return when (this) {
is IrSimpleType -> makeKotlinType(classifier, arguments, hasQuestionMark)
is IrDynamicType -> createDynamicType(irTypeKotlinBuiltIns!!)
else -> TODO(toString())
}
}
@@ -137,7 +133,7 @@ fun IrClassifierSymbol.typeWith(arguments: List<IrType>): IrSimpleType =
fun IrClass.typeWith(arguments: List<IrType>) = this.symbol.typeWith(arguments)
fun KotlinType.toIrType(symbolTable: SymbolTable? = null): IrType? {
if (isDynamic()) return IrDynamicTypeImpl(this, listOf(), Variance.INVARIANT)
if (isDynamic()) return IrDynamicTypeImpl(null, listOf(), Variance.INVARIANT)
val symbol = constructor.declarationDescriptor?.getSymbol(symbolTable) ?: return null
@@ -151,7 +147,7 @@ fun KotlinType.toIrType(symbolTable: SymbolTable? = null): IrType? {
// TODO
val annotations = listOf()
return IrSimpleTypeImpl(this, symbol, isMarkedNullable, arguments, annotations)
return IrSimpleTypeImpl(null, symbol, isMarkedNullable, arguments, annotations)
}
// TODO: this function creates unbound symbol which is the great source of problems
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.IrTypeProjection
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.IrTypeProjectionImpl
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
class DeepCopyTypeRemapper(
private val symbolRemapper: SymbolRemapper
@@ -43,7 +42,7 @@ class DeepCopyTypeRemapper(
val annotations = type.annotations.map { it.transform(deepCopy, null) as IrCall }
return IrSimpleTypeImpl(
type.originalKotlinType,
null,
symbolRemapper.getReferencedClassifier(type.classifier),
type.hasQuestionMark,
arguments,
@@ -6,22 +6,19 @@
package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.isAny
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
@@ -164,110 +161,9 @@ fun IrExpression.coerceToUnitIfNeeded(valueType: KotlinType, irBuiltIns: IrBuilt
fun IrMemberAccessExpression.usesDefaultArguments(): Boolean =
this.descriptor.valueParameters.any { this.getValueArgument(it) == null }
fun IrFunction.createParameterDeclarations(symbolTable: SymbolTable? = null) {
fun ParameterDescriptor.irValueParameter() = IrValueParameterImpl(
innerStartOffset(this), innerEndOffset(this),
IrDeclarationOrigin.DEFINED,
this,
type.toIrType(symbolTable)!!,
(this as? ValueParameterDescriptor)?.varargElementType?.toIrType(symbolTable)
).also {
it.parent = this@createParameterDeclarations
}
dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.irValueParameter()
extensionReceiverParameter = descriptor.extensionReceiverParameter?.irValueParameter()
assert(valueParameters.isEmpty())
descriptor.valueParameters.mapTo(valueParameters) { it.irValueParameter() }
assert(typeParameters.isEmpty())
descriptor.typeParameters.mapTo(typeParameters) {
IrTypeParameterImpl(
innerStartOffset(it), innerEndOffset(it),
IrDeclarationOrigin.DEFINED,
it
).also { typeParameter ->
typeParameter.parent = this
}
}
}
fun IrClass.createParameterDeclarations() {
thisReceiver = IrValueParameterImpl(
startOffset, endOffset,
IrDeclarationOrigin.INSTANCE_RECEIVER,
descriptor.thisAsReceiverParameter,
this.symbol.typeWith(this.typeParameters.map { it.defaultType }),
null
).also { valueParameter ->
valueParameter.parent = this
}
assert(typeParameters.isEmpty())
assert(descriptor.declaredTypeParameters.isEmpty())
}
//fun IrClass.createParameterDeclarations() {
// descriptor.thisAsReceiverParameter.let {
// thisReceiver = IrValueParameterImpl(
// innerStartOffset(it), innerEndOffset(it),
// IrDeclarationOrigin.INSTANCE_RECEIVER,
// it
// )
// }
//
// assert(typeParameters.isEmpty())
// descriptor.declaredTypeParameters.mapTo(typeParameters) {
// IrTypeParameterImpl(
// innerStartOffset(it), innerEndOffset(it),
// IrDeclarationOrigin.DEFINED,
// it
// )
// }
//}
//
//fun IrClass.addFakeOverrides() {
//
// val startOffset = this.startOffset
// val endOffset = this.endOffset
//
// fun FunctionDescriptor.createFunction(): IrSimpleFunction = IrFunctionImpl(
// startOffset, endOffset,
// IrDeclarationOrigin.FAKE_OVERRIDE, this
// ).apply {
// createParameterDeclarations()
// }
//
// descriptor.unsubstitutedMemberScope.getContributedDescriptors()
// .filterIsInstance<CallableMemberDescriptor>()
// .filter { it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE }
// .mapTo(this.declarations) {
// when (it) {
// is FunctionDescriptor -> it.createFunction()
// is PropertyDescriptor ->
// IrPropertyImpl(startOffset, endOffset, IrDeclarationOrigin.FAKE_OVERRIDE, it).apply {
// // TODO: add field if getter is missing?
// getter = it.getter?.createFunction()
// setter = it.setter?.createFunction()
// }
// else -> TODO(it.toString())
// }
// }
//}
private fun IrElement.innerStartOffset(descriptor: DeclarationDescriptorWithSource): Int =
descriptor.startOffset ?: this.startOffset
private fun IrElement.innerEndOffset(descriptor: DeclarationDescriptorWithSource): Int =
descriptor.endOffset ?: this.endOffset
val DeclarationDescriptorWithSource.startOffset: Int? get() = (this.source as? PsiSourceElement)?.psi?.startOffset
val DeclarationDescriptorWithSource.endOffset: Int? get() = (this.source as? PsiSourceElement)?.psi?.endOffset
val DeclarationDescriptorWithSource.startOffsetOrUndefined: Int get() = startOffset ?: UNDEFINED_OFFSET
val DeclarationDescriptorWithSource.endOffsetOrUndefined: Int get() = endOffset ?: UNDEFINED_OFFSET
val IrClassSymbol.functions: Sequence<IrSimpleFunctionSymbol>
get() = this.owner.declarations.asSequence().filterIsInstance<IrSimpleFunction>().map { it.symbol }
@@ -291,9 +187,9 @@ val IrClass.defaultType: IrSimpleType
val IrSimpleFunction.isReal: Boolean get() = descriptor.kind.isReal
fun IrClass.isImmediateSubClassOf(ancestor: IrClass) = ancestor.symbol in superTypes.mapNotNull {
(it as? IrSimpleType)?.classifier
}
val IrSimpleFunction.isSynthesized: Boolean get() = descriptor.kind == CallableMemberDescriptor.Kind.SYNTHESIZED
val IrSimpleFunction.isFakeOverride: Boolean get() = origin == IrDeclarationOrigin.FAKE_OVERRIDE
fun IrClass.isSubclassOf(ancestor: IrClass): Boolean {
@@ -350,6 +246,22 @@ fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction? {
return collectRealOverrides().singleOrNull { it.modality != Modality.ABSTRACT }
}
fun IrSimpleFunction.isOrOverridesSynthesized(): Boolean {
if (isSynthesized) return true
if (isFakeOverride) return overriddenSymbols.all { it.owner.isOrOverridesSynthesized() }
return false
}
fun IrSimpleFunction.findInterfaceImplementation(): IrSimpleFunction? {
if (isReal) return null
if (isOrOverridesSynthesized()) return null
return resolveFakeOverride()?.run { if (parentAsClass.isInterface) this else null }
}
fun IrField.resolveFakeOverride(): IrField? {
var toVisit = setOf(this)
val nonOverridden = mutableSetOf<IrField>()
@@ -443,39 +355,6 @@ fun IrValueParameter.copy(newDescriptor: ParameterDescriptor): IrValueParameter
)
}
fun createField(
startOffset: Int,
endOffset: Int,
type: IrType,
name: Name,
isMutable: Boolean,
origin: IrDeclarationOrigin,
owner: ClassDescriptor
): IrField {
val descriptor = PropertyDescriptorImpl.create(
/* containingDeclaration = */ owner,
/* annotations = */ Annotations.EMPTY,
/* modality = */ Modality.FINAL,
/* visibility = */ Visibilities.PRIVATE,
/* isVar = */ isMutable,
/* name = */ name,
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
/* source = */ SourceElement.NO_SOURCE,
/* lateInit = */ false,
/* isConst = */ false,
/* isExpect = */ false,
/* isActual = */ false,
/* isExternal = */ false,
/* isDelegated = */ false
).apply {
initialize(null, null)
setType(type.toKotlinType(), emptyList(), owner.thisAsReceiverParameter, null)
}
return IrFieldImpl(startOffset, endOffset, origin, descriptor, type)
}
// In presence of `IrBlock`s, return the expression that actually serves as the value (the last one).
tailrec fun IrExpression.removeBlocks(): IrExpression? = when (this) {
is IrBlock -> (statements.last() as? IrExpression)?.removeBlocks()