IrTypes: Implicit casts, take 1
Keep KotlinType along with IrTypes created by psi2ir.
This commit is contained in:
+28
-27
@@ -17,18 +17,18 @@
|
||||
package org.jetbrains.kotlin.psi2ir.transformations
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.util.ScopedTypeParametersResolver
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.TypeTranslator
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.psi2ir.containsNull
|
||||
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.isError
|
||||
@@ -37,27 +37,26 @@ import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
import org.jetbrains.kotlin.types.upperIfFlexible
|
||||
|
||||
fun insertImplicitCasts(builtIns: KotlinBuiltIns, element: IrElement, symbolTable: SymbolTable) {
|
||||
element.transformChildren(InsertImplicitCasts(builtIns, symbolTable), null)
|
||||
fun insertImplicitCasts(element: IrElement, context: GeneratorContext) {
|
||||
element.transformChildren(InsertImplicitCasts(context), null)
|
||||
}
|
||||
|
||||
class InsertImplicitCasts(private val builtIns: KotlinBuiltIns, private val symbolTable: SymbolTable) : IrElementTransformerVoid() {
|
||||
class InsertImplicitCasts(context: GeneratorContext) : IrElementTransformerVoid() {
|
||||
|
||||
private val typeParameterResolver = ScopedTypeParametersResolver()
|
||||
private val builtIns = context.builtIns
|
||||
private val irBuiltIns = context.irBuiltIns
|
||||
private val symbolTable = context.symbolTable
|
||||
|
||||
private val typeTranslator = TypeTranslator(context.moduleDescriptor, symbolTable)
|
||||
private fun KotlinType.toIrType() = typeTranslator.translateType(this)
|
||||
|
||||
private inline fun <T> runInTypeParameterScope(typeParametersContainer: IrTypeParametersContainer, fn: () -> T): T {
|
||||
typeParameterResolver.enterTypeParameterScope(typeParametersContainer)
|
||||
typeTranslator.enterScope(typeParametersContainer)
|
||||
val result = fn()
|
||||
typeParameterResolver.leaveTypeParameterScope()
|
||||
typeTranslator.leaveScope()
|
||||
return result
|
||||
}
|
||||
|
||||
private fun resolveScopedTypeParameter(classifier: ClassifierDescriptor): IrTypeParameterSymbol? =
|
||||
if (classifier is TypeParameterDescriptor)
|
||||
typeParameterResolver.resolveScopedTypeParameter(classifier)
|
||||
else
|
||||
null
|
||||
|
||||
override fun visitCallableReference(expression: IrCallableReference): IrExpression =
|
||||
expression.transformPostfix {
|
||||
transformReceiverArguments()
|
||||
@@ -188,13 +187,16 @@ class InsertImplicitCasts(private val builtIns: KotlinBuiltIns, private val symb
|
||||
expression = expression.cast(expectedType)
|
||||
}
|
||||
|
||||
private fun IrExpression.cast(irType: IrType): IrExpression =
|
||||
cast(irType.originalKotlinType)
|
||||
|
||||
private fun IrExpression.cast(expectedType: KotlinType?): IrExpression {
|
||||
if (expectedType == null) return this
|
||||
if (expectedType.isError) return this
|
||||
|
||||
val notNullableExpectedType = expectedType.makeNotNullable()
|
||||
|
||||
val valueType = this.type
|
||||
val valueType = this.type.originalKotlinType!!
|
||||
|
||||
return when {
|
||||
KotlinBuiltIns.isUnit(expectedType) ->
|
||||
@@ -225,29 +227,28 @@ class InsertImplicitCasts(private val builtIns: KotlinBuiltIns, private val symb
|
||||
targetType: KotlinType,
|
||||
typeOperator: IrTypeOperator
|
||||
): IrExpression {
|
||||
val typeDescriptor = targetType.constructor.declarationDescriptor
|
||||
?: throw AssertionError("No declaration for target type: $targetType")
|
||||
|
||||
val irType = targetType.toIrType()
|
||||
return IrTypeOperatorCallImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
targetType,
|
||||
irType,
|
||||
typeOperator,
|
||||
targetType,
|
||||
resolveScopedTypeParameter(typeDescriptor) ?: symbolTable.referenceClassifier(typeDescriptor),
|
||||
irType, irType.classifierOrFail,
|
||||
this
|
||||
)
|
||||
}
|
||||
|
||||
private fun IrExpression.coerceToUnit(): IrExpression {
|
||||
val valueType = this.type
|
||||
val valueType = this.type.originalKotlinType!!
|
||||
|
||||
return if (KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType, builtIns.unitType))
|
||||
this
|
||||
else
|
||||
IrTypeOperatorCallImpl(
|
||||
startOffset, endOffset, builtIns.unitType,
|
||||
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, builtIns.unitType, symbolTable.referenceClass(builtIns.unit),
|
||||
startOffset, endOffset,
|
||||
irBuiltIns.unitType,
|
||||
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT,
|
||||
irBuiltIns.unitType, irBuiltIns.unitType.classifierOrFail,
|
||||
this
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,27 +8,42 @@ package org.jetbrains.kotlin.ir.types.impl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
class IrSimpleTypeImpl(
|
||||
kotlinType: KotlinType?,
|
||||
override val classifier: IrClassifierSymbol,
|
||||
override val hasQuestionMark: Boolean,
|
||||
override val arguments: List<IrTypeProjection>,
|
||||
annotations: List<IrCall>,
|
||||
variance: Variance
|
||||
) : IrTypeBase(annotations, variance), IrSimpleType, IrTypeProjection {
|
||||
) : IrTypeBase(kotlinType, annotations, variance), IrSimpleType, IrTypeProjection {
|
||||
|
||||
constructor(
|
||||
classifier: IrClassifierSymbol,
|
||||
hasQuestionMark: Boolean,
|
||||
arguments: List<IrTypeProjection>,
|
||||
annotations: List<IrCall>
|
||||
) : this(classifier, hasQuestionMark, arguments, annotations, Variance.INVARIANT)
|
||||
) : this(null, classifier, hasQuestionMark, arguments, annotations, Variance.INVARIANT)
|
||||
|
||||
constructor(
|
||||
kotlinType: KotlinType?,
|
||||
classifier: IrClassifierSymbol,
|
||||
hasQuestionMark: Boolean,
|
||||
arguments: List<IrTypeProjection>,
|
||||
annotations: List<IrCall>
|
||||
) : this(kotlinType, classifier, hasQuestionMark, arguments, annotations, Variance.INVARIANT)
|
||||
|
||||
constructor(
|
||||
other: IrSimpleType,
|
||||
variance: Variance
|
||||
) : this(other.classifier, other.hasQuestionMark, other.arguments, other.annotations, variance)
|
||||
) :
|
||||
this(
|
||||
other.safeAs<IrSimpleTypeImpl>()?.kotlinType,
|
||||
other.classifier, other.hasQuestionMark, other.arguments, other.annotations, variance
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@@ -41,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.annotations, variance)
|
||||
type is IrErrorType -> IrErrorTypeImpl(type.annotations, variance)
|
||||
type is IrDynamicType -> IrDynamicTypeImpl(type.originalKotlinType, type.annotations, variance)
|
||||
type is IrErrorType -> IrErrorTypeImpl(type.originalKotlinType, type.annotations, variance)
|
||||
else -> IrTypeProjectionImpl(type, variance)
|
||||
}
|
||||
@@ -10,9 +10,12 @@ import org.jetbrains.kotlin.ir.types.IrDynamicType
|
||||
import org.jetbrains.kotlin.ir.types.IrErrorType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.IrTypeProjection
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
abstract class IrTypeBase(
|
||||
val kotlinType: KotlinType?,
|
||||
override val annotations: List<IrCall>,
|
||||
override val variance: Variance
|
||||
) : IrType, IrTypeProjection {
|
||||
@@ -22,11 +25,17 @@ abstract class IrTypeBase(
|
||||
}
|
||||
|
||||
class IrErrorTypeImpl(
|
||||
kotlinType: KotlinType?,
|
||||
annotations: List<IrCall>,
|
||||
variance: Variance
|
||||
) : IrTypeBase(annotations, variance), IrErrorType
|
||||
) : IrTypeBase(kotlinType, annotations, variance), IrErrorType
|
||||
|
||||
class IrDynamicTypeImpl(
|
||||
kotlinType: KotlinType?,
|
||||
annotations: List<IrCall>,
|
||||
variance: Variance
|
||||
) : IrTypeBase(annotations, variance), IrDynamicType, IrTypeProjection
|
||||
) : IrTypeBase(kotlinType, annotations, variance), IrDynamicType, IrTypeProjection
|
||||
|
||||
|
||||
val IrType.originalKotlinType: KotlinType?
|
||||
get() = safeAs<IrTypeBase>()?.kotlinType
|
||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.types
|
||||
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
@@ -17,7 +18,7 @@ fun IrType.withHasQuestionMark(hasQuestionMark: Boolean): IrType =
|
||||
if (this.hasQuestionMark == hasQuestionMark)
|
||||
this
|
||||
else
|
||||
IrSimpleTypeImpl(classifier, hasQuestionMark, arguments, annotations)
|
||||
IrSimpleTypeImpl(originalKotlinType, classifier, hasQuestionMark, arguments, annotations)
|
||||
else -> this
|
||||
}
|
||||
|
||||
@@ -30,6 +31,7 @@ val IrType.classifierOrNull: IrClassifierSymbol?
|
||||
fun IrType.makeNotNull() =
|
||||
if (this is IrSimpleType && this.hasQuestionMark)
|
||||
IrSimpleTypeImpl(
|
||||
originalKotlinType,
|
||||
classifier,
|
||||
false,
|
||||
arguments,
|
||||
@@ -42,6 +44,7 @@ fun IrType.makeNotNull() =
|
||||
fun IrType.makeNullable() =
|
||||
if (this is IrSimpleType && !this.hasQuestionMark)
|
||||
IrSimpleTypeImpl(
|
||||
originalKotlinType,
|
||||
classifier,
|
||||
true,
|
||||
arguments,
|
||||
|
||||
@@ -47,9 +47,9 @@ class TypeTranslator(
|
||||
val ktTypeUpper = approximateCapturedTypes(ktType0).upper
|
||||
|
||||
when {
|
||||
ktTypeUpper.isError -> return IrErrorTypeImpl(translateTypeAnnotations(ktTypeUpper.annotations), variance)
|
||||
ktTypeUpper.isError -> return IrErrorTypeImpl(ktTypeUpper, translateTypeAnnotations(ktTypeUpper.annotations), variance)
|
||||
ktTypeUpper.isFlexible() -> return translateType(ktTypeUpper.upperIfFlexible(), variance)
|
||||
ktTypeUpper.isDynamic() -> return IrDynamicTypeImpl(translateTypeAnnotations(ktTypeUpper.annotations), variance)
|
||||
ktTypeUpper.isDynamic() -> return IrDynamicTypeImpl(ktTypeUpper, translateTypeAnnotations(ktTypeUpper.annotations), variance)
|
||||
}
|
||||
|
||||
val ktTypeConstructor = ktTypeUpper.constructor
|
||||
@@ -58,6 +58,7 @@ class TypeTranslator(
|
||||
return when (ktTypeDescriptor) {
|
||||
is TypeParameterDescriptor ->
|
||||
IrSimpleTypeImpl(
|
||||
ktTypeUpper,
|
||||
resolveTypeParameter(ktTypeDescriptor),
|
||||
ktTypeUpper.isMarkedNullable,
|
||||
emptyList(),
|
||||
@@ -67,6 +68,7 @@ class TypeTranslator(
|
||||
|
||||
is ClassDescriptor ->
|
||||
IrSimpleTypeImpl(
|
||||
ktTypeUpper,
|
||||
symbolTable.referenceClass(ktTypeDescriptor),
|
||||
ktTypeUpper.isMarkedNullable,
|
||||
translateTypeArguments(ktTypeUpper.arguments),
|
||||
|
||||
Reference in New Issue
Block a user