psi2ir: Implicit casts with 'dynamic'

This commit is contained in:
Dmitry Petrov
2019-02-06 16:54:35 +03:00
parent 3c8f52b436
commit fc76d0970b
6 changed files with 102 additions and 13 deletions
@@ -37,13 +37,12 @@ import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils
import org.jetbrains.kotlin.psi2ir.containsNull
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.isError
import org.jetbrains.kotlin.types.isNullabilityFlexible
import org.jetbrains.kotlin.types.typeUtil.isNullableAny
import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.types.typeUtil.makeNullable
import org.jetbrains.kotlin.types.upperIfFlexible
fun insertImplicitCasts(element: IrElement, context: GeneratorContext) {
element.transformChildren(InsertImplicitCasts(context.builtIns, context.irBuiltIns, context.typeTranslator), null)
@@ -94,10 +93,10 @@ open class InsertImplicitCasts(
statements.forEachIndexed { i, irStatement ->
if (irStatement is IrExpression) {
statements[i] =
if (i == lastIndex)
irStatement.cast(type)
else
irStatement.coerceToUnit()
if (i == lastIndex)
irStatement.cast(type)
else
irStatement.coerceToUnit()
}
}
}
@@ -219,13 +218,17 @@ open class InsertImplicitCasts(
val valueType = this.type.originalKotlinType!!
return when {
KotlinBuiltIns.isUnit(expectedType) ->
expectedType.isUnit() ->
coerceToUnit()
valueType.isNullabilityFlexible() && valueType.containsNull() && !expectedType.containsNull() -> {
val nonNullValueType = valueType.upperIfFlexible().makeNotNullable()
implicitCast(nonNullValueType, IrTypeOperator.IMPLICIT_NOTNULL).cast(expectedType)
}
valueType.isDynamic() && !expectedType.isDynamic() ->
if (expectedType.isNullableAny())
this
else
implicitCast(expectedType, IrTypeOperator.IMPLICIT_CAST)
valueType.isNullabilityFlexible() && valueType.containsNull() && !expectedType.containsNull() ->
implicitNonNull(valueType, expectedType)
KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType, expectedType.makeNullable()) ->
this
@@ -243,6 +246,11 @@ open class InsertImplicitCasts(
}
}
private fun IrExpression.implicitNonNull(valueType: KotlinType, expectedType: KotlinType): IrExpression {
val nonNullValueType = valueType.upperIfFlexible().makeNotNullable()
return implicitCast(nonNullValueType, IrTypeOperator.IMPLICIT_NOTNULL).cast(expectedType)
}
private fun IrExpression.implicitCast(
targetType: KotlinType,
typeOperator: IrTypeOperator