More precise implicit cast generation

If an expression 'x' has a definitely non-null type 'T1',
and is used in position with an expected type 'T2',
cast 'x' to 'T2!!' (most common non-null type T*: T* <: T2).
This commit is contained in:
Dmitry Petrov
2018-02-02 11:11:09 +03:00
parent 9137e68d4e
commit bf18186045
4 changed files with 26 additions and 20 deletions
@@ -172,6 +172,7 @@ class InsertImplicitCasts(val builtIns: KotlinBuiltIns) : IrElementTransformerVo
return when {
KotlinBuiltIns.isUnit(expectedType) ->
coerceToUnit()
valueType.isNullabilityFlexible() && valueType.containsNull() && !expectedType.containsNull() -> {
val nonNullValueType = valueType.upperIfFlexible().makeNotNullable()
IrTypeOperatorCallImpl(
@@ -179,18 +180,23 @@ class InsertImplicitCasts(val builtIns: KotlinBuiltIns) : IrElementTransformerVo
IrTypeOperator.IMPLICIT_NOTNULL, nonNullValueType, this
).cast(expectedType)
}
KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType.makeNotNullable(), expectedType) ->
this
KotlinBuiltIns.isInt(valueType) && notNullableExpectedType.isBuiltInIntegerType() ->
IrTypeOperatorCallImpl(
startOffset, endOffset, notNullableExpectedType,
IrTypeOperator.IMPLICIT_INTEGER_COERCION, notNullableExpectedType, this
)
else ->
else -> {
val targetType = if (!valueType.containsNull()) notNullableExpectedType else expectedType
IrTypeOperatorCallImpl(
startOffset, endOffset, expectedType,
IrTypeOperator.IMPLICIT_CAST, expectedType, this
startOffset, endOffset, targetType,
IrTypeOperator.IMPLICIT_CAST, targetType, this
)
}
}
}
@@ -42,7 +42,7 @@ FILE fqName:<root> fileName:/floatingPointEqeq.kt
GET_VAR 'value-parameter y: Any' type=kotlin.Any origin=null
then: CALL 'ieee754equals(Double?, Double?): Boolean' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'value-parameter x: Double' type=kotlin.Double origin=null
arg1: TYPE_OP type=kotlin.Double? origin=IMPLICIT_CAST typeOperand=kotlin.Double?
arg1: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
GET_VAR 'value-parameter y: Any' type=kotlin.Any origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
@@ -64,9 +64,9 @@ FILE fqName:<root> fileName:/floatingPointEqeq.kt
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST Boolean type=kotlin.Boolean value=false
then: CALL 'ieee754equals(Double?, Double?): Boolean' type=kotlin.Boolean origin=EQEQ
arg0: TYPE_OP type=kotlin.Double? origin=IMPLICIT_CAST typeOperand=kotlin.Double?
arg0: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
GET_VAR 'value-parameter x: Any' type=kotlin.Any origin=null
arg1: TYPE_OP type=kotlin.Double? origin=IMPLICIT_CAST typeOperand=kotlin.Double?
arg1: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
GET_VAR 'value-parameter y: Any' type=kotlin.Any origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
@@ -114,7 +114,7 @@ FILE fqName:<root> fileName:/floatingPointEqeq.kt
GET_VAR 'value-parameter y: Any' type=kotlin.Any origin=null
then: CALL 'ieee754equals(Float?, Float?): Boolean' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'value-parameter x: Float' type=kotlin.Float origin=null
arg1: TYPE_OP type=kotlin.Float? origin=IMPLICIT_CAST typeOperand=kotlin.Float?
arg1: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'value-parameter y: Any' type=kotlin.Any origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
@@ -136,9 +136,9 @@ FILE fqName:<root> fileName:/floatingPointEqeq.kt
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST Boolean type=kotlin.Boolean value=false
then: CALL 'ieee754equals(Float?, Float?): Boolean' type=kotlin.Boolean origin=EQEQ
arg0: TYPE_OP type=kotlin.Float? origin=IMPLICIT_CAST typeOperand=kotlin.Float?
arg0: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'value-parameter x: Any' type=kotlin.Any origin=null
arg1: TYPE_OP type=kotlin.Float? origin=IMPLICIT_CAST typeOperand=kotlin.Float?
arg1: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'value-parameter y: Any' type=kotlin.Any origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
@@ -163,7 +163,7 @@ FILE fqName:<root> fileName:/floatingPointEqeq.kt
arg0: CALL 'toDouble(): Double' type=kotlin.Double origin=null
$this: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'value-parameter x: Any' type=kotlin.Any origin=null
arg1: TYPE_OP type=kotlin.Double? origin=IMPLICIT_CAST typeOperand=kotlin.Double?
arg1: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
GET_VAR 'value-parameter y: Any' type=kotlin.Any origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
@@ -185,7 +185,7 @@ FILE fqName:<root> fileName:/floatingPointEqeq.kt
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST Boolean type=kotlin.Boolean value=false
then: CALL 'ieee754equals(Double?, Double?): Boolean' type=kotlin.Boolean origin=EQEQ
arg0: TYPE_OP type=kotlin.Double? origin=IMPLICIT_CAST typeOperand=kotlin.Double?
arg0: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
GET_VAR 'value-parameter x: Any' type=kotlin.Any origin=null
arg1: CALL 'toDouble(): Double' type=kotlin.Double origin=null
$this: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
@@ -47,7 +47,7 @@ FILE fqName:<root> fileName:/floatingPointExcleq.kt
then: CALL 'NOT(Boolean): Boolean' type=kotlin.Boolean origin=EXCLEQ
arg0: CALL 'ieee754equals(Double?, Double?): Boolean' type=kotlin.Boolean origin=EXCLEQ
arg0: GET_VAR 'value-parameter x: Double' type=kotlin.Double origin=null
arg1: TYPE_OP type=kotlin.Double? origin=IMPLICIT_CAST typeOperand=kotlin.Double?
arg1: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
GET_VAR 'value-parameter y: Any' type=kotlin.Any origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
@@ -70,9 +70,9 @@ FILE fqName:<root> fileName:/floatingPointExcleq.kt
then: CONST Boolean type=kotlin.Boolean value=false
then: CALL 'NOT(Boolean): Boolean' type=kotlin.Boolean origin=EXCLEQ
arg0: CALL 'ieee754equals(Double?, Double?): Boolean' type=kotlin.Boolean origin=EXCLEQ
arg0: TYPE_OP type=kotlin.Double? origin=IMPLICIT_CAST typeOperand=kotlin.Double?
arg0: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
GET_VAR 'value-parameter x: Any' type=kotlin.Any origin=null
arg1: TYPE_OP type=kotlin.Double? origin=IMPLICIT_CAST typeOperand=kotlin.Double?
arg1: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
GET_VAR 'value-parameter y: Any' type=kotlin.Any origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
@@ -125,7 +125,7 @@ FILE fqName:<root> fileName:/floatingPointExcleq.kt
then: CALL 'NOT(Boolean): Boolean' type=kotlin.Boolean origin=EXCLEQ
arg0: CALL 'ieee754equals(Float?, Float?): Boolean' type=kotlin.Boolean origin=EXCLEQ
arg0: GET_VAR 'value-parameter x: Float' type=kotlin.Float origin=null
arg1: TYPE_OP type=kotlin.Float? origin=IMPLICIT_CAST typeOperand=kotlin.Float?
arg1: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'value-parameter y: Any' type=kotlin.Any origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
@@ -148,9 +148,9 @@ FILE fqName:<root> fileName:/floatingPointExcleq.kt
then: CONST Boolean type=kotlin.Boolean value=false
then: CALL 'NOT(Boolean): Boolean' type=kotlin.Boolean origin=EXCLEQ
arg0: CALL 'ieee754equals(Float?, Float?): Boolean' type=kotlin.Boolean origin=EXCLEQ
arg0: TYPE_OP type=kotlin.Float? origin=IMPLICIT_CAST typeOperand=kotlin.Float?
arg0: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'value-parameter x: Any' type=kotlin.Any origin=null
arg1: TYPE_OP type=kotlin.Float? origin=IMPLICIT_CAST typeOperand=kotlin.Float?
arg1: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'value-parameter y: Any' type=kotlin.Any origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
@@ -176,7 +176,7 @@ FILE fqName:<root> fileName:/floatingPointExcleq.kt
arg0: CALL 'toDouble(): Double' type=kotlin.Double origin=null
$this: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'value-parameter x: Any' type=kotlin.Any origin=null
arg1: TYPE_OP type=kotlin.Double? origin=IMPLICIT_CAST typeOperand=kotlin.Double?
arg1: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
GET_VAR 'value-parameter y: Any' type=kotlin.Any origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
@@ -199,7 +199,7 @@ FILE fqName:<root> fileName:/floatingPointExcleq.kt
then: CONST Boolean type=kotlin.Boolean value=false
then: CALL 'NOT(Boolean): Boolean' type=kotlin.Boolean origin=EXCLEQ
arg0: CALL 'ieee754equals(Double?, Double?): Boolean' type=kotlin.Boolean origin=EXCLEQ
arg0: TYPE_OP type=kotlin.Double? origin=IMPLICIT_CAST typeOperand=kotlin.Double?
arg0: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
GET_VAR 'value-parameter x: Any' type=kotlin.Any origin=null
arg1: CALL 'toDouble(): Double' type=kotlin.Double origin=null
$this: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
@@ -16,7 +16,7 @@ FILE fqName:<root> fileName:/Derived.kt
then: BLOCK type=kotlin.Unit origin=null
SET_FIELD 'value: String!' type=kotlin.Unit origin=EQ
receiver: GET_VAR 'this@Derived: Derived' type=Derived origin=null
value: TYPE_OP type=kotlin.String! origin=IMPLICIT_CAST typeOperand=kotlin.String!
value: TYPE_OP type=kotlin.String origin=IMPLICIT_CAST typeOperand=kotlin.String
GET_VAR 'value-parameter v: Any' type=kotlin.Any origin=null
PROPERTY FAKE_OVERRIDE name:value type:kotlin.String! visibility:public modality:FINAL flags:var
FIELD FAKE_OVERRIDE name:value type:kotlin.String! visibility:public