JVM_IR fix cast to not-null type

We can't rely on argument type nullability here, because it still can
hold an uninitialized value on JVM.

KT-50577 KT-35272 KT-27427
This commit is contained in:
Dmitry Petrov
2021-12-29 17:05:58 +03:00
committed by teamcity
parent 4a29a8a7af
commit 4ad6cfcf53
15 changed files with 124 additions and 11 deletions
@@ -83,7 +83,11 @@ private class TypeOperatorLowering(private val context: JvmBackendContext) : Fil
private fun lowerCast(argument: IrExpression, type: IrType): IrExpression = when {
type.isReifiedTypeParameter ->
builder.irAs(argument, type)
argument.type.isNullable() && !type.isNullable() ->
argument.type.isInlineClassType() && argument.type.isSubtypeOfClass(type.erasedUpperBound.symbol) ->
argument
type.isNullable() || argument.isDefinitelyNotNull() ->
builder.irAs(argument, type)
else -> {
with(builder) {
irLetS(argument, irType = context.irBuiltIns.anyNType) { valueSymbol ->
irIfNull(
@@ -92,14 +96,30 @@ private class TypeOperatorLowering(private val context: JvmBackendContext) : Fil
irCall(throwTypeCastException).apply {
putValueArgument(0, irString("null cannot be cast to non-null type ${type.render()}"))
},
lowerCast(irGet(valueSymbol.owner), type.makeNullable())
builder.irAs(irGet(valueSymbol.owner), type.makeNullable())
)
}
}
argument.type.isInlineClassType() && argument.type.isSubtypeOfClass(type.erasedUpperBound.symbol) ->
argument
else ->
builder.irAs(argument, type)
}
}
// TODO extract null check elimination on IR somewhere?
private fun IrExpression.isDefinitelyNotNull(): Boolean =
when (this) {
is IrGetValue ->
this.symbol.owner.isDefinitelyNotNullVal()
is IrGetClass,
is IrConstructorCall ->
true
is IrCall ->
this.symbol == context.irBuiltIns.checkNotNullSymbol
else ->
false
}
private fun IrValueDeclaration.isDefinitelyNotNullVal(): Boolean {
val irVariable = this as? IrVariable ?: return false
return !irVariable.isVar && irVariable.initializer?.isDefinitelyNotNull() == true
}
private val jvmIndyLambdaMetafactoryIntrinsic = context.ir.symbols.indyLambdaMetafactoryIntrinsic