IR: IrSimpleTypeBuilder

This commit is contained in:
Dmitry Petrov
2019-04-11 17:16:20 +03:00
parent 2844d48f9f
commit bf2ab99b61
4 changed files with 97 additions and 105 deletions
@@ -12,8 +12,9 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.types.impl.toBuilder
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
@@ -153,27 +154,22 @@ internal class DeepCopyIrTreeWithSymbolsForInliner(val context: Context,
val substitutedType = typeArguments?.get(type.classifier) val substitutedType = typeArguments?.get(type.classifier)
if (substitutedType != null) { if (substitutedType != null) {
substitutedType as IrSimpleType substitutedType as IrSimpleType
return IrSimpleTypeImpl( return substitutedType.buildSimpleType {
kotlinType = null, kotlinType = null
classifier = substitutedType.classifier, hasQuestionMark = type.hasQuestionMark or substitutedType.isMarkedNullable()
hasQuestionMark = type.hasQuestionMark or substitutedType.isMarkedNullable(), }
arguments = substitutedType.arguments,
annotations = substitutedType.annotations
)
} }
return IrSimpleTypeImpl( return type.buildSimpleType {
kotlinType = null, kotlinType = null
classifier = symbolRemapper.getReferencedClassifier(type.classifier), classifier = symbolRemapper.getReferencedClassifier(type.classifier)
hasQuestionMark = type.hasQuestionMark, arguments = remapTypeArguments(type.arguments)
arguments = remapTypeArguments(type.arguments), annotations = type.annotations.map { it.transform(copier, null) as IrCall }
annotations = type.annotations.map { it.transform(copier, null) as IrCall } }
)
} }
} }
private class SymbolRemapperImpl(descriptorsRemapper: DescriptorsRemapper) private class SymbolRemapperImpl(descriptorsRemapper: DescriptorsRemapper) : DeepCopySymbolRemapper(descriptorsRemapper) {
: DeepCopySymbolRemapper(descriptorsRemapper) {
var typeArguments: Map<IrTypeParameterSymbol, IrType?>? = null var typeArguments: Map<IrTypeParameterSymbol, IrType?>? = null
set(value) { set(value) {
@@ -192,9 +188,6 @@ internal class DeepCopyIrTreeWithSymbolsForInliner(val context: Context,
} }
private val symbolRemapper = SymbolRemapperImpl(DescriptorsToIrRemapper()) private val symbolRemapper = SymbolRemapperImpl(DescriptorsToIrRemapper())
private val copier = DeepCopyIrTreeWithSymbols( private val copier =
symbolRemapper, DeepCopyIrTreeWithSymbols(symbolRemapper, InlinerTypeRemapper(symbolRemapper, typeArguments), InlinerSymbolRenamer())
InlinerTypeRemapper(symbolRemapper, typeArguments),
InlinerSymbolRenamer()
)
} }
@@ -11,53 +11,73 @@ import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class IrSimpleTypeImpl( class IrSimpleTypeImpl(
kotlinType: KotlinType?, kotlinType: KotlinType?,
override val classifier: IrClassifierSymbol, override val classifier: IrClassifierSymbol,
override val hasQuestionMark: Boolean, override val hasQuestionMark: Boolean,
override val arguments: List<IrTypeArgument>, override val arguments: List<IrTypeArgument>,
annotations: List<IrCall>, annotations: List<IrCall>
variance: Variance ) : IrTypeBase(kotlinType, annotations, Variance.INVARIANT), IrSimpleType, IrTypeProjection {
) : IrTypeBase(kotlinType, annotations, variance), IrSimpleType, IrTypeProjection {
constructor( constructor(
classifier: IrClassifierSymbol, classifier: IrClassifierSymbol,
hasQuestionMark: Boolean, hasQuestionMark: Boolean,
arguments: List<IrTypeArgument>, arguments: List<IrTypeArgument>,
annotations: List<IrCall> annotations: List<IrCall>
) : this(null, classifier, hasQuestionMark, arguments, annotations, Variance.INVARIANT) ) : this(null, classifier, hasQuestionMark, arguments, annotations)
constructor(
kotlinType: KotlinType?,
classifier: IrClassifierSymbol,
hasQuestionMark: Boolean,
arguments: List<IrTypeArgument>,
annotations: List<IrCall>
) : this(kotlinType, classifier, hasQuestionMark, arguments, annotations, Variance.INVARIANT)
constructor(
other: IrSimpleType,
variance: Variance
) :
this(
other.safeAs<IrSimpleTypeImpl>()?.kotlinType,
other.classifier, other.hasQuestionMark, other.arguments, other.annotations, variance
)
override fun equals(other: Any?): Boolean = override fun equals(other: Any?): Boolean =
other is IrSimpleTypeImpl && other is IrSimpleTypeImpl &&
FqNameEqualityChecker.areEqual(classifier, other.classifier) && FqNameEqualityChecker.areEqual(classifier, other.classifier) &&
hasQuestionMark == other.hasQuestionMark && hasQuestionMark == other.hasQuestionMark &&
arguments == other.arguments && arguments == other.arguments
variance == other.variance
override fun hashCode(): Int = override fun hashCode(): Int =
((FqNameEqualityChecker.getHashCode(classifier) * 31 + hasQuestionMark.hashCode()) * 31 + (FqNameEqualityChecker.getHashCode(classifier) * 31 +
arguments.hashCode()) * 31 + variance.hashCode() hasQuestionMark.hashCode()) * 31 +
arguments.hashCode()
} }
class IrSimpleTypeBuilder {
var kotlinType: KotlinType? = null
var classifier: IrClassifierSymbol? = null
var hasQuestionMark = false
var arguments: List<IrTypeArgument> = emptyList()
var annotations: List<IrCall> = emptyList()
var variance = Variance.INVARIANT
}
fun IrSimpleType.toBuilder() =
IrSimpleTypeBuilder().also { b ->
b.kotlinType = originalKotlinType
b.classifier = classifier
b.hasQuestionMark = hasQuestionMark
b.arguments = arguments
b.annotations = annotations
}
fun IrSimpleTypeBuilder.buildSimpleType() =
IrSimpleTypeImpl(
kotlinType,
classifier ?: throw AssertionError("Classifier not provided"),
hasQuestionMark,
arguments,
annotations
)
fun IrSimpleTypeBuilder.buildTypeProjection() =
if (variance == Variance.INVARIANT)
buildSimpleType()
else
IrTypeProjectionImpl(buildSimpleType(), variance)
inline fun IrSimpleType.buildSimpleType(b: IrSimpleTypeBuilder.() -> Unit): IrSimpleType =
toBuilder().apply(b).buildSimpleType()
inline fun IrSimpleType.buildTypeProjection(b: IrSimpleTypeBuilder.() -> Unit): IrTypeProjection =
toBuilder().apply(b).buildTypeProjection()
class IrTypeProjectionImpl internal constructor( class IrTypeProjectionImpl internal constructor(
override val type: IrType, override val type: IrType,
override val variance: Variance override val variance: Variance
@@ -72,7 +92,7 @@ class IrTypeProjectionImpl internal constructor(
fun makeTypeProjection(type: IrType, variance: Variance): IrTypeProjection = fun makeTypeProjection(type: IrType, variance: Variance): IrTypeProjection =
when { when {
type is IrTypeProjection && type.variance == variance -> type type is IrTypeProjection && type.variance == variance -> type
type is IrSimpleType -> IrSimpleTypeImpl(type, variance) type is IrSimpleType -> type.toBuilder().apply { this.variance = variance }.buildTypeProjection()
type is IrDynamicType -> IrDynamicTypeImpl(null, type.annotations, variance) type is IrDynamicType -> IrDynamicTypeImpl(null, type.annotations, variance)
type is IrErrorType -> IrErrorTypeImpl(null, type.annotations, variance) type is IrErrorType -> IrErrorTypeImpl(null, type.annotations, variance)
else -> IrTypeProjectionImpl(type, variance) else -> IrTypeProjectionImpl(type, variance)
@@ -6,35 +6,29 @@
package org.jetbrains.kotlin.ir.types package org.jetbrains.kotlin.ir.types
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.impl.* import org.jetbrains.kotlin.ir.types.impl.*
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.types.typeUtil.makeNullable import org.jetbrains.kotlin.types.typeUtil.makeNullable
import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
fun IrType.withHasQuestionMark(hasQuestionMark: Boolean): IrType = fun IrType.withHasQuestionMark(newHasQuestionMark: Boolean): IrType =
when (this) { when (this) {
is IrSimpleType -> is IrSimpleType ->
if (this.hasQuestionMark == hasQuestionMark) if (this.hasQuestionMark == newHasQuestionMark)
this this
else else
IrSimpleTypeImpl( buildSimpleType {
originalKotlinType?.run { if (hasQuestionMark) makeNullable() else makeNotNullable() }, hasQuestionMark = newHasQuestionMark
classifier, kotlinType = originalKotlinType?.run {
hasQuestionMark, if (newHasQuestionMark) makeNullable() else makeNotNullable()
arguments, }
annotations }
)
else -> this else -> this
} }
@@ -49,27 +43,19 @@ val IrType.classOrNull: IrClassSymbol?
fun IrType.makeNotNull() = fun IrType.makeNotNull() =
if (this is IrSimpleType && this.hasQuestionMark) { if (this is IrSimpleType && this.hasQuestionMark) {
IrSimpleTypeImpl( buildSimpleType {
originalKotlinType?.makeNotNullable(), kotlinType = originalKotlinType?.makeNotNullable()
classifier, hasQuestionMark = false
false, }
arguments,
annotations,
Variance.INVARIANT
)
} else } else
this this
fun IrType.makeNullable() = fun IrType.makeNullable() =
if (this is IrSimpleType && !this.hasQuestionMark) if (this is IrSimpleType && !this.hasQuestionMark)
IrSimpleTypeImpl( buildSimpleType {
originalKotlinType?.makeNullable(), kotlinType = originalKotlinType?.makeNullable()
classifier, hasQuestionMark = true
true, }
arguments,
annotations,
Variance.INVARIANT
)
else else
this this
@@ -15,10 +15,7 @@ import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.IrTypeProjection import org.jetbrains.kotlin.ir.types.IrTypeProjection
import org.jetbrains.kotlin.ir.types.impl.IrDynamicTypeImpl import org.jetbrains.kotlin.ir.types.impl.*
import org.jetbrains.kotlin.ir.types.impl.IrErrorTypeImpl
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections
import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes
@@ -78,30 +75,26 @@ class TypeTranslator(
val ktTypeDescriptor = ktTypeConstructor.declarationDescriptor val ktTypeDescriptor = ktTypeConstructor.declarationDescriptor
?: throw AssertionError("No descriptor for type $approximatedType") ?: throw AssertionError("No descriptor for type $approximatedType")
return when (ktTypeDescriptor) { return IrSimpleTypeBuilder().apply {
is TypeParameterDescriptor -> kotlinType = approximatedType
IrSimpleTypeImpl( hasQuestionMark = approximatedType.isMarkedNullable
approximatedType, this.variance = variance
resolveTypeParameter(ktTypeDescriptor), when (ktTypeDescriptor) {
approximatedType.isMarkedNullable, is TypeParameterDescriptor -> {
emptyList(), classifier = resolveTypeParameter(ktTypeDescriptor)
translateTypeAnnotations(approximatedType.annotations), annotations = translateTypeAnnotations(approximatedType.annotations)
variance }
)
is ClassDescriptor -> is ClassDescriptor -> {
IrSimpleTypeImpl( classifier = symbolTable.referenceClass(ktTypeDescriptor)
approximatedType, arguments = translateTypeArguments(approximatedType.arguments)
symbolTable.referenceClass(ktTypeDescriptor), annotations = translateTypeAnnotations(approximatedType.annotations)
approximatedType.isMarkedNullable, }
translateTypeArguments(approximatedType.arguments),
translateTypeAnnotations(approximatedType.annotations),
variance
)
else -> else ->
throw AssertionError("Unexpected type descriptor $ktTypeDescriptor :: ${ktTypeDescriptor::class}") throw AssertionError("Unexpected type descriptor $ktTypeDescriptor :: ${ktTypeDescriptor::class}")
} }
}.buildTypeProjection()
} }
private inner class LegacyTypeApproximation { private inner class LegacyTypeApproximation {