diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CheckIrElementVisitor.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CheckIrElementVisitor.kt
index 4e275f223ca..023f93e4e18 100644
--- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CheckIrElementVisitor.kt
+++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CheckIrElementVisitor.kt
@@ -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()) {
diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt
index 4eb4d64f0e7..ae07eb569b7 100644
--- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt
+++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt
@@ -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() ||
diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt
index df1f6d67991..90a2bdce911 100644
--- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt
+++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt
@@ -291,7 +291,7 @@ open class InsertImplicitCasts(
if (expectedType.isNullableAny()) {
this
} else {
- implicitCast(expectedType, IrTypeOperator.IMPLICIT_CAST)
+ implicitCast(expectedType, IrTypeOperator.IMPLICIT_DYNAMIC_CAST)
}
}
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorCall.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorCall.kt
index f2b3017e84e..35084d48b87 100644
--- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorCall.kt
+++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorCall.kt
@@ -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 {
diff --git a/compiler/ir/serialization.common/src/KotlinIr.proto b/compiler/ir/serialization.common/src/KotlinIr.proto
index dad764c507a..22b08a6d313 100644
--- a/compiler/ir/serialization.common/src/KotlinIr.proto
+++ b/compiler/ir/serialization.common/src/KotlinIr.proto
@@ -512,6 +512,7 @@ enum IrTypeOperator {
INSTANCEOF = 7;
NOT_INSTANCEOF = 8;
SAM_CONVERSION = 9;
+ IMPLICIT_DYNAMIC_CAST = 10;
}
diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrModuleDeserializer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrModuleDeserializer.kt
index dddaf5b87fb..1f43fcd4d0d 100644
--- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrModuleDeserializer.kt
+++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrModuleDeserializer.kt
@@ -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 {
diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrModuleSerializer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrModuleSerializer.kt
index babc8e304d0..57c94c78c19 100644
--- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrModuleSerializer.kt
+++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrModuleSerializer.kt
@@ -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 {
diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIr.java b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIr.java
index 907e08d5e34..9fff85ed649 100644
--- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIr.java
+++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIr.java
@@ -588,6 +588,10 @@ public final class KotlinIr {
* SAM_CONVERSION = 9;
*/
SAM_CONVERSION(8, 9),
+ /**
+ * IMPLICIT_DYNAMIC_CAST = 10;
+ */
+ IMPLICIT_DYNAMIC_CAST(9, 10),
;
/**
@@ -626,6 +630,10 @@ public final class KotlinIr {
* SAM_CONVERSION = 9;
*/
public static final int SAM_CONVERSION_VALUE = 9;
+ /**
+ * IMPLICIT_DYNAMIC_CAST = 10;
+ */
+ 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;
}
}
diff --git a/compiler/testData/ir/irJsText/dynamic/dynamicAndMembersOfAny.txt b/compiler/testData/ir/irJsText/dynamic/dynamicAndMembersOfAny.txt
index 9b5a6780b84..4389ae84ca1 100644
--- a/compiler/testData/ir/irJsText/dynamic/dynamicAndMembersOfAny.txt
+++ b/compiler/testData/ir/irJsText/dynamic/dynamicAndMembersOfAny.txt
@@ -4,20 +4,20 @@ FILE fqName: fileName:/dynamicAndMembersOfAny.kt
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test1 (d: dynamic): kotlin.String declared in '
CALL 'public open fun toString (): kotlin.String declared in kotlin.Any' type=kotlin.String origin=null
- $this: TYPE_OP type=kotlin.Any origin=IMPLICIT_CAST typeOperand=kotlin.Any
+ $this: TYPE_OP type=kotlin.Any origin=IMPLICIT_DYNAMIC_CAST typeOperand=kotlin.Any
GET_VAR 'd: dynamic declared in .test1' type=dynamic origin=null
FUN name:test2 visibility:public modality:FINAL <> (d:dynamic) returnType:kotlin.Int
VALUE_PARAMETER name:d index:0 type:dynamic
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test2 (d: dynamic): kotlin.Int declared in '
CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null
- $this: TYPE_OP type=kotlin.Any origin=IMPLICIT_CAST typeOperand=kotlin.Any
+ $this: TYPE_OP type=kotlin.Any origin=IMPLICIT_DYNAMIC_CAST typeOperand=kotlin.Any
GET_VAR 'd: dynamic declared in .test2' type=dynamic origin=null
FUN name:test3 visibility:public modality:FINAL <> (d:dynamic) returnType:kotlin.Boolean
VALUE_PARAMETER name:d index:0 type:dynamic
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test3 (d: dynamic): kotlin.Boolean declared in '
CALL 'public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Any' type=kotlin.Boolean origin=null
- $this: TYPE_OP type=kotlin.Any origin=IMPLICIT_CAST typeOperand=kotlin.Any
+ $this: TYPE_OP type=kotlin.Any origin=IMPLICIT_DYNAMIC_CAST typeOperand=kotlin.Any
GET_VAR 'd: dynamic declared in .test3' type=dynamic origin=null
other: CONST Int type=kotlin.Int value=42
diff --git a/compiler/testData/ir/irJsText/dynamic/dynamicWithSmartCast.txt b/compiler/testData/ir/irJsText/dynamic/dynamicWithSmartCast.txt
index b3a34717875..8658c394f86 100644
--- a/compiler/testData/ir/irJsText/dynamic/dynamicWithSmartCast.txt
+++ b/compiler/testData/ir/irJsText/dynamic/dynamicWithSmartCast.txt
@@ -8,7 +8,7 @@ FILE fqName: fileName:/dynamicWithSmartCast.kt
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.String
GET_VAR 'd: dynamic declared in .test1' type=dynamic origin=null
then: CALL 'public open fun (): kotlin.Int declared in kotlin.String' type=kotlin.Int origin=GET_PROPERTY
- $this: TYPE_OP type=kotlin.String origin=IMPLICIT_CAST typeOperand=kotlin.String
+ $this: TYPE_OP type=kotlin.String origin=IMPLICIT_DYNAMIC_CAST typeOperand=kotlin.String
GET_VAR 'd: dynamic declared in .test1' type=dynamic origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
@@ -22,7 +22,7 @@ FILE fqName: fileName:/dynamicWithSmartCast.kt
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Array<*>
GET_VAR 'd: dynamic declared in .test2' type=dynamic origin=null
then: CALL 'public final fun (): kotlin.Int declared in kotlin.Array' type=kotlin.Int origin=GET_PROPERTY
- $this: TYPE_OP type=kotlin.Array origin=IMPLICIT_CAST typeOperand=kotlin.Array
+ $this: TYPE_OP type=kotlin.Array origin=IMPLICIT_DYNAMIC_CAST typeOperand=kotlin.Array
GET_VAR 'd: dynamic declared in .test2' type=dynamic origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
diff --git a/compiler/testData/ir/irJsText/dynamic/implicitCastFromDynamic.txt b/compiler/testData/ir/irJsText/dynamic/implicitCastFromDynamic.txt
index e960d9ab169..20ed84e826a 100644
--- a/compiler/testData/ir/irJsText/dynamic/implicitCastFromDynamic.txt
+++ b/compiler/testData/ir/irJsText/dynamic/implicitCastFromDynamic.txt
@@ -11,7 +11,7 @@ FILE fqName: fileName:/implicitCastFromDynamic.kt
PROPERTY name:p visibility:public modality:FINAL [val]
FIELD PROPERTY_BACKING_FIELD name:p type:kotlin.Int visibility:public [final,static]
EXPRESSION_BODY
- TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int
+ TYPE_OP type=kotlin.Int origin=IMPLICIT_DYNAMIC_CAST typeOperand=kotlin.Int
CALL 'public final fun (): dynamic declared in ' type=dynamic origin=GET_PROPERTY
FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Int
correspondingProperty: PROPERTY name:p visibility:public modality:FINAL [val]
@@ -22,13 +22,13 @@ FILE fqName: fileName:/implicitCastFromDynamic.kt
VALUE_PARAMETER name:d index:0 type:dynamic
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test1 (d: dynamic): kotlin.Int declared in '
- TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int
+ TYPE_OP type=kotlin.Int origin=IMPLICIT_DYNAMIC_CAST typeOperand=kotlin.Int
GET_VAR 'd: dynamic declared in .test1' type=dynamic origin=null
FUN name:test2 visibility:public modality:FINAL <> (d:dynamic) returnType:kotlin.Any
VALUE_PARAMETER name:d index:0 type:dynamic
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test2 (d: dynamic): kotlin.Any declared in '
- TYPE_OP type=kotlin.Any origin=IMPLICIT_CAST typeOperand=kotlin.Any
+ TYPE_OP type=kotlin.Any origin=IMPLICIT_DYNAMIC_CAST typeOperand=kotlin.Any
GET_VAR 'd: dynamic declared in .test2' type=dynamic origin=null
FUN name:test3 visibility:public modality:FINAL <> (d:dynamic) returnType:kotlin.Any?
VALUE_PARAMETER name:d index:0 type:dynamic
@@ -39,7 +39,7 @@ FILE fqName: fileName:/implicitCastFromDynamic.kt
VALUE_PARAMETER name:d index:0 type:dynamic
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test4 (d: dynamic): kotlin.String declared in '
- TYPE_OP type=kotlin.String origin=IMPLICIT_CAST typeOperand=kotlin.String
+ TYPE_OP type=kotlin.String origin=IMPLICIT_DYNAMIC_CAST typeOperand=kotlin.String
DYN_OP operator=INVOKE type=dynamic
receiver: DYN_MEMBER memberName='member' type=dynamic
GET_VAR 'd: dynamic declared in .test4' type=dynamic origin=null