IR: IMPLICIT_DYNAMIC_CAST

Generate IMPLICIT_DYNAMIC_CAST for implicit casts from `dynamic` to `T`
This commit is contained in:
Dmitry Petrov
2019-04-16 12:52:22 +03:00
parent 422c13bd03
commit 760806a1ac
11 changed files with 79 additions and 50 deletions
@@ -182,11 +182,15 @@ class CheckIrElementVisitor(
IrTypeOperator.IMPLICIT_NOTNULL,
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT,
IrTypeOperator.IMPLICIT_INTEGER_COERCION,
IrTypeOperator.SAM_CONVERSION -> typeOperand
IrTypeOperator.SAM_CONVERSION,
IrTypeOperator.IMPLICIT_DYNAMIC_CAST ->
typeOperand
IrTypeOperator.SAFE_CAST -> typeOperand.makeNullable()
IrTypeOperator.SAFE_CAST ->
typeOperand.makeNullable()
IrTypeOperator.INSTANCEOF, IrTypeOperator.NOT_INSTANCEOF -> irBuiltIns.booleanType
IrTypeOperator.INSTANCEOF, IrTypeOperator.NOT_INSTANCEOF ->
irBuiltIns.booleanType
}
if (operator == IrTypeOperator.IMPLICIT_COERCION_TO_UNIT && !typeOperand.isUnit()) {
@@ -69,6 +69,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
return when (expression.operator) {
IrTypeOperator.IMPLICIT_CAST -> lowerImplicitCast(expression)
IrTypeOperator.IMPLICIT_DYNAMIC_CAST -> lowerImplicitDynamicCast(expression)
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT -> lowerCoercionToUnit(expression)
IrTypeOperator.IMPLICIT_INTEGER_COERCION -> lowerIntegerCoercion(expression, data)
IrTypeOperator.IMPLICIT_NOTNULL -> lowerImplicitNotNull(expression, data)
@@ -122,6 +123,11 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
argument
}
private fun lowerImplicitDynamicCast(expression: IrTypeOperatorCall) = expression.run {
assert(operator == IrTypeOperator.IMPLICIT_DYNAMIC_CAST)
argument
}
// Note: native `instanceOf` is not used which is important because of null-behaviour
private fun advancedCheckRequired(type: IrType) = type.isInterface() ||
type.isArray() ||
@@ -291,7 +291,7 @@ open class InsertImplicitCasts(
if (expectedType.isNullableAny()) {
this
} else {
implicitCast(expectedType, IrTypeOperator.IMPLICIT_CAST)
implicitCast(expectedType, IrTypeOperator.IMPLICIT_DYNAMIC_CAST)
}
}
@@ -44,7 +44,12 @@ enum class IrTypeOperator {
* SAM conversion: value of functional type F is used where Single Abstract Method interface value is expected.
* Currently this is possible in Kotlin/JVM only, however, there's a big demand for SAM conversion for Kotlin interfaces.
*/
SAM_CONVERSION;
SAM_CONVERSION,
/**
* Implicit dynamic cast: implicit cast from `dynamic` to `T`.
* This currently can happen in Kotlin/JS only.
*/
IMPLICIT_DYNAMIC_CAST;
}
interface IrTypeOperatorCall : IrExpression {
@@ -512,6 +512,7 @@ enum IrTypeOperator {
INSTANCEOF = 7;
NOT_INSTANCEOF = 8;
SAM_CONVERSION = 9;
IMPLICIT_DYNAMIC_CAST = 10;
}
@@ -530,24 +530,26 @@ abstract class IrModuleDeserializer(
}
private fun deserializeTypeOperator(operator: KotlinIr.IrTypeOperator) = when (operator) {
KotlinIr.IrTypeOperator.CAST
-> IrTypeOperator.CAST
KotlinIr.IrTypeOperator.IMPLICIT_CAST
-> IrTypeOperator.IMPLICIT_CAST
KotlinIr.IrTypeOperator.IMPLICIT_NOTNULL
-> IrTypeOperator.IMPLICIT_NOTNULL
KotlinIr.IrTypeOperator.IMPLICIT_COERCION_TO_UNIT
-> IrTypeOperator.IMPLICIT_COERCION_TO_UNIT
KotlinIr.IrTypeOperator.IMPLICIT_INTEGER_COERCION
-> IrTypeOperator.IMPLICIT_INTEGER_COERCION
KotlinIr.IrTypeOperator.SAFE_CAST
-> IrTypeOperator.SAFE_CAST
KotlinIr.IrTypeOperator.INSTANCEOF
-> IrTypeOperator.INSTANCEOF
KotlinIr.IrTypeOperator.NOT_INSTANCEOF
-> IrTypeOperator.NOT_INSTANCEOF
KotlinIr.IrTypeOperator.SAM_CONVERSION
-> IrTypeOperator.SAM_CONVERSION
KotlinIr.IrTypeOperator.CAST ->
IrTypeOperator.CAST
KotlinIr.IrTypeOperator.IMPLICIT_CAST ->
IrTypeOperator.IMPLICIT_CAST
KotlinIr.IrTypeOperator.IMPLICIT_NOTNULL ->
IrTypeOperator.IMPLICIT_NOTNULL
KotlinIr.IrTypeOperator.IMPLICIT_COERCION_TO_UNIT ->
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT
KotlinIr.IrTypeOperator.IMPLICIT_INTEGER_COERCION ->
IrTypeOperator.IMPLICIT_INTEGER_COERCION
KotlinIr.IrTypeOperator.SAFE_CAST ->
IrTypeOperator.SAFE_CAST
KotlinIr.IrTypeOperator.INSTANCEOF ->
IrTypeOperator.INSTANCEOF
KotlinIr.IrTypeOperator.NOT_INSTANCEOF ->
IrTypeOperator.NOT_INSTANCEOF
KotlinIr.IrTypeOperator.SAM_CONVERSION ->
IrTypeOperator.SAM_CONVERSION
KotlinIr.IrTypeOperator.IMPLICIT_DYNAMIC_CAST ->
IrTypeOperator.IMPLICIT_DYNAMIC_CAST
}
private fun deserializeTypeOp(proto: KotlinIr.IrTypeOp, start: Int, end: Int, type: IrType): IrTypeOperatorCall {
@@ -601,24 +601,26 @@ open class IrModuleSerializer(
}
private fun serializeTypeOperator(operator: IrTypeOperator): KotlinIr.IrTypeOperator = when (operator) {
IrTypeOperator.CAST
-> KotlinIr.IrTypeOperator.CAST
IrTypeOperator.IMPLICIT_CAST
-> KotlinIr.IrTypeOperator.IMPLICIT_CAST
IrTypeOperator.IMPLICIT_NOTNULL
-> KotlinIr.IrTypeOperator.IMPLICIT_NOTNULL
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT
-> KotlinIr.IrTypeOperator.IMPLICIT_COERCION_TO_UNIT
IrTypeOperator.IMPLICIT_INTEGER_COERCION
-> KotlinIr.IrTypeOperator.IMPLICIT_INTEGER_COERCION
IrTypeOperator.SAFE_CAST
-> KotlinIr.IrTypeOperator.SAFE_CAST
IrTypeOperator.INSTANCEOF
-> KotlinIr.IrTypeOperator.INSTANCEOF
IrTypeOperator.NOT_INSTANCEOF
-> KotlinIr.IrTypeOperator.NOT_INSTANCEOF
IrTypeOperator.SAM_CONVERSION
-> KotlinIr.IrTypeOperator.SAM_CONVERSION
IrTypeOperator.CAST ->
KotlinIr.IrTypeOperator.CAST
IrTypeOperator.IMPLICIT_CAST ->
KotlinIr.IrTypeOperator.IMPLICIT_CAST
IrTypeOperator.IMPLICIT_NOTNULL ->
KotlinIr.IrTypeOperator.IMPLICIT_NOTNULL
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT ->
KotlinIr.IrTypeOperator.IMPLICIT_COERCION_TO_UNIT
IrTypeOperator.IMPLICIT_INTEGER_COERCION ->
KotlinIr.IrTypeOperator.IMPLICIT_INTEGER_COERCION
IrTypeOperator.SAFE_CAST ->
KotlinIr.IrTypeOperator.SAFE_CAST
IrTypeOperator.INSTANCEOF ->
KotlinIr.IrTypeOperator.INSTANCEOF
IrTypeOperator.NOT_INSTANCEOF ->
KotlinIr.IrTypeOperator.NOT_INSTANCEOF
IrTypeOperator.SAM_CONVERSION ->
KotlinIr.IrTypeOperator.SAM_CONVERSION
IrTypeOperator.IMPLICIT_DYNAMIC_CAST ->
KotlinIr.IrTypeOperator.IMPLICIT_DYNAMIC_CAST
}
private fun serializeTypeOp(expression: IrTypeOperatorCall): KotlinIr.IrTypeOp {
@@ -588,6 +588,10 @@ public final class KotlinIr {
* <code>SAM_CONVERSION = 9;</code>
*/
SAM_CONVERSION(8, 9),
/**
* <code>IMPLICIT_DYNAMIC_CAST = 10;</code>
*/
IMPLICIT_DYNAMIC_CAST(9, 10),
;
/**
@@ -626,6 +630,10 @@ public final class KotlinIr {
* <code>SAM_CONVERSION = 9;</code>
*/
public static final int SAM_CONVERSION_VALUE = 9;
/**
* <code>IMPLICIT_DYNAMIC_CAST = 10;</code>
*/
public static final int IMPLICIT_DYNAMIC_CAST_VALUE = 10;
public final int getNumber() { return value; }
@@ -641,6 +649,7 @@ public final class KotlinIr {
case 7: return INSTANCEOF;
case 8: return NOT_INSTANCEOF;
case 9: return SAM_CONVERSION;
case 10: return IMPLICIT_DYNAMIC_CAST;
default: return null;
}
}