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