FIR2IR insert implicit cast on elvis RHS
This commit is contained in:
@@ -292,14 +292,22 @@ class Fir2IrVisitor(
|
||||
)
|
||||
if (initializer != null) {
|
||||
irVariable.initializer =
|
||||
with(implicitCastInserter) {
|
||||
convertToIrExpression(initializer).cast(initializer, initializer.typeRef, variable.returnTypeRef)
|
||||
}
|
||||
convertToIrExpression(initializer)
|
||||
.insertImplicitCast(initializer, initializer.typeRef, variable.returnTypeRef)
|
||||
}
|
||||
annotationGenerator.generate(irVariable, variable)
|
||||
return irVariable
|
||||
}
|
||||
|
||||
private fun IrExpression.insertImplicitCast(
|
||||
baseExpression: FirExpression,
|
||||
valueType: FirTypeRef,
|
||||
expectedType: FirTypeRef
|
||||
) =
|
||||
with(implicitCastInserter) {
|
||||
this@insertImplicitCast.cast(baseExpression, valueType, expectedType)
|
||||
}
|
||||
|
||||
override fun visitProperty(property: FirProperty, data: Any?): IrElement {
|
||||
if (property.isLocal) return visitLocalVariable(property)
|
||||
val irProperty = declarationStorage.getCachedIrProperty(property)!!
|
||||
@@ -707,13 +715,15 @@ class Fir2IrVisitor(
|
||||
val notNullType = originalType.withNullability(ConeNullability.NOT_NULL, session.typeContext)
|
||||
val irBranches = listOf(
|
||||
IrBranchImpl(
|
||||
startOffset, endOffset, primitiveOp2(
|
||||
startOffset, endOffset,
|
||||
primitiveOp2(
|
||||
startOffset, endOffset, irBuiltIns.eqeqSymbol,
|
||||
irBuiltIns.booleanType, IrStatementOrigin.EQEQ,
|
||||
irGetLhsValue(),
|
||||
IrConstImpl.constNull(startOffset, endOffset, irBuiltIns.nothingNType)
|
||||
),
|
||||
convertToIrExpression(elvisExpression.rhs)
|
||||
.insertImplicitCast(elvisExpression, elvisExpression.rhs.typeRef, elvisExpression.typeRef)
|
||||
),
|
||||
IrElseBranchImpl(
|
||||
IrConstImpl.boolean(startOffset, endOffset, irBuiltIns.booleanType, true),
|
||||
@@ -815,9 +825,7 @@ class Fir2IrVisitor(
|
||||
private fun FirWhenBranch.toIrWhenBranch(whenExpressionType: FirTypeRef): IrBranch {
|
||||
return convertWithOffsets { startOffset, endOffset ->
|
||||
val condition = condition
|
||||
val irResult = with(implicitCastInserter) {
|
||||
convertToIrExpression(result).cast(result, result.typeRef, whenExpressionType)
|
||||
}
|
||||
val irResult = convertToIrExpression(result).insertImplicitCast(result, result.typeRef, whenExpressionType)
|
||||
if (condition is FirElseIfTrueCondition) {
|
||||
IrElseBranchImpl(IrConstImpl.boolean(irResult.startOffset, irResult.endOffset, irBuiltIns.booleanType, true), irResult)
|
||||
} else {
|
||||
|
||||
Generated
+6
@@ -2901,6 +2901,12 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest {
|
||||
runTest("compiler/testData/ir/irText/types/nullChecks/implicitNotNullOnPlatformType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nullCheckInElvisRhs.kt")
|
||||
public void testNullCheckInElvisRhs() throws Exception {
|
||||
runTest("compiler/testData/ir/irText/types/nullChecks/nullCheckInElvisRhs.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nullCheckOnInterfaceDelegation.kt")
|
||||
public void testNullCheckOnInterfaceDelegation() throws Exception {
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// FIR status: Fail: should have been an exception in 'bar()'
|
||||
// MODULE: lib
|
||||
// FILE: RightElvisOperand.java
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
Module: lib
|
||||
Module: main
|
||||
FILE fqName:<root> fileName:/nullCheckInElvisRhs.kt
|
||||
FUN name:baz visibility:public modality:FINAL <> () returnType:kotlin.String?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun baz (): kotlin.String? declared in <root>'
|
||||
CONST Null type=kotlin.Nothing? value=null
|
||||
FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.String
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test (): kotlin.String declared in <root>'
|
||||
BLOCK type=kotlin.String origin=ELVIS
|
||||
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.String? [val]
|
||||
CALL 'public final fun baz (): kotlin.String? declared in <root>' type=kotlin.String? origin=null
|
||||
WHEN type=kotlin.String origin=ELVIS
|
||||
BRANCH
|
||||
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||
arg0: GET_VAR 'val tmp_0: kotlin.String? [val] declared in <root>.test' type=kotlin.String? origin=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value=null
|
||||
then: TYPE_OP type=kotlin.String origin=IMPLICIT_NOTNULL typeOperand=kotlin.String
|
||||
CALL 'public/*package*/ open fun foo (): @[FlexibleNullability] kotlin.String? declared in <root>.RightElvisOperand' type=@[FlexibleNullability] kotlin.String? origin=null
|
||||
BRANCH
|
||||
if: CONST Boolean type=kotlin.Boolean value=true
|
||||
then: GET_VAR 'val tmp_0: kotlin.String? [val] declared in <root>.test' type=kotlin.String? origin=null
|
||||
@@ -0,0 +1,17 @@
|
||||
// MODULE: lib
|
||||
// MODULE: main
|
||||
// FILE: nullCheckInElvisRhs.kt
|
||||
|
||||
fun baz(): String? {
|
||||
return null
|
||||
}
|
||||
|
||||
fun test(): String {
|
||||
return { // BLOCK
|
||||
val <elvis>: String? = baz()
|
||||
when {
|
||||
EQEQ(arg0 = <elvis>, arg1 = null) -> foo() /*!! String */
|
||||
else -> <elvis>
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
Module: lib
|
||||
Module: main
|
||||
FILE fqName:<root> fileName:/nullCheckInElvisRhs.kt
|
||||
FUN name:baz visibility:public modality:FINAL <> () returnType:kotlin.String?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun baz (): kotlin.String? declared in <root>'
|
||||
CONST Null type=kotlin.Nothing? value=null
|
||||
FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.String
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test (): kotlin.String declared in <root>'
|
||||
BLOCK type=kotlin.String origin=ELVIS
|
||||
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.String? [val]
|
||||
CALL 'public final fun baz (): kotlin.String? declared in <root>' type=kotlin.String? origin=null
|
||||
WHEN type=kotlin.String origin=null
|
||||
BRANCH
|
||||
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||
arg0: GET_VAR 'val tmp_0: kotlin.String? [val] declared in <root>.test' type=kotlin.String? origin=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value=null
|
||||
then: TYPE_OP type=kotlin.String origin=IMPLICIT_NOTNULL typeOperand=kotlin.String
|
||||
CALL 'public/*package*/ open fun foo (): @[FlexibleNullability] kotlin.String? declared in <root>.RightElvisOperand' type=@[FlexibleNullability] kotlin.String? origin=null
|
||||
BRANCH
|
||||
if: CONST Boolean type=kotlin.Boolean value=true
|
||||
then: GET_VAR 'val tmp_0: kotlin.String? [val] declared in <root>.test' type=kotlin.String? origin=null
|
||||
@@ -0,0 +1,17 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// MODULE: lib
|
||||
// FILE: RightElvisOperand.java
|
||||
|
||||
class RightElvisOperand {
|
||||
static String foo() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// MODULE: main(lib)
|
||||
// FILE: nullCheckInElvisRhs.kt
|
||||
|
||||
fun baz(): String? = null
|
||||
|
||||
fun test(): String = baz() ?: RightElvisOperand.foo()
|
||||
@@ -0,0 +1,18 @@
|
||||
// MODULE: lib
|
||||
// MODULE: main
|
||||
// FILE: nullCheckInElvisRhs.kt
|
||||
|
||||
fun baz(): String? {
|
||||
return null
|
||||
}
|
||||
|
||||
fun test(): String {
|
||||
return { // BLOCK
|
||||
val tmp0_elvis_lhs: String? = baz()
|
||||
when {
|
||||
EQEQ(arg0 = tmp0_elvis_lhs, arg1 = null) -> foo() /*!! String */
|
||||
else -> tmp0_elvis_lhs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+6
@@ -2901,6 +2901,12 @@ public class IrTextTestGenerated extends AbstractIrTextTest {
|
||||
runTest("compiler/testData/ir/irText/types/nullChecks/implicitNotNullOnPlatformType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nullCheckInElvisRhs.kt")
|
||||
public void testNullCheckInElvisRhs() throws Exception {
|
||||
runTest("compiler/testData/ir/irText/types/nullChecks/nullCheckInElvisRhs.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nullCheckOnInterfaceDelegation.kt")
|
||||
public void testNullCheckOnInterfaceDelegation() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user