IrTypes: Implicit casts, take 1

Keep KotlinType along with IrTypes created by psi2ir.
This commit is contained in:
Dmitry Petrov
2018-05-15 10:21:14 +03:00
parent 54e9a2bb7b
commit e8fe788df6
5 changed files with 67 additions and 37 deletions
@@ -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),