JVM IR: fix the type of IrGetField

The `irGetField` utility uses the field's own type as the type of the
resulting expression. But the field's type does not make sense outside
of the place of declaration of the field if it references a generic type
parameter of the containing class. Using this non-sensical generic type
led, for example, to an error in Ieee754 intrinsic (KT-48648).

The type of the expression should be kept as is in
JvmPropertiesLowering, i.e. taken from `expression` which the lowering
is replacing with the field access.

 #KT-48648 Fixed
This commit is contained in:
Alexander Udalov
2021-10-01 02:57:40 +02:00
parent 279f184703
commit 357f3184bf
7 changed files with 51 additions and 10 deletions
@@ -17734,6 +17734,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/ieee754/inline.kt"); runTest("compiler/testData/codegen/box/ieee754/inline.kt");
} }
@Test
@TestMetadata("kt48648_genericField.kt")
public void testKt48648_genericField() throws Exception {
runTest("compiler/testData/codegen/box/ieee754/kt48648_genericField.kt");
}
@Test @Test
@TestMetadata("lessDouble.kt") @TestMetadata("lessDouble.kt")
public void testLessDouble() throws Exception { public void testLessDouble() throws Exception {
@@ -27,10 +27,8 @@ import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFieldAccessExpression import org.jetbrains.kotlin.ir.expressions.IrFieldAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.isSubtypeOfClass
import org.jetbrains.kotlin.ir.types.makeNotNull
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAbi
@@ -99,19 +97,20 @@ class JvmPropertiesLowering(private val backendContext: JvmBackendContext) : IrE
private fun IrBuilderWithScope.substituteGetter(irProperty: IrProperty, expression: IrCall): IrExpression { private fun IrBuilderWithScope.substituteGetter(irProperty: IrProperty, expression: IrCall): IrExpression {
val backingField = irProperty.resolveFakeOverride()!!.backingField!! val backingField = irProperty.resolveFakeOverride()!!.backingField!!
val value = irGetField(patchFieldAccessReceiver(expression, irProperty), backingField) val patchedReceiver = patchFieldAccessReceiver(expression, irProperty)
return if (irProperty.isLateinit) { return if (irProperty.isLateinit) {
irBlock { irBlock {
val tmpVal = irTemporary(value) val fieldType = expression.type.makeNullable()
val tmpVal = irTemporary(IrGetFieldImpl(startOffset, endOffset, backingField.symbol, fieldType, patchedReceiver))
+irIfNull( +irIfNull(
expression.type.makeNotNull(), expression.type,
irGet(tmpVal), irGet(tmpVal),
backendContext.throwUninitializedPropertyAccessException(this, backingField.name.asString()), backendContext.throwUninitializedPropertyAccessException(this, backingField.name.asString()),
irGet(tmpVal) irGet(tmpVal)
) )
} }
} else { } else {
value IrGetFieldImpl(startOffset, endOffset, backingField.symbol, expression.type, patchedReceiver)
} }
} }
@@ -0,0 +1,21 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
class V1<T : Number>(y: T) {
@JvmField
var x: T = y
}
class V2<T : Number> {
lateinit var x: T
}
fun check(a: V1<Float>, b: V2<Float>): Boolean =
a.x != b.x
fun box(): String {
val v1 = V1(1.0f)
val v2 = V2<Float>()
v2.x = 2.0f
return if (check(v1, v2)) "OK" else "Fail"
}
@@ -1,7 +1,5 @@
// !LANGUAGE: -ProhibitJvmFieldOnOverrideFromInterfaceInPrimaryConstructor // !LANGUAGE: -ProhibitJvmFieldOnOverrideFromInterfaceInPrimaryConstructor
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// ^ generates 'GETFIELD B.x : I' instead of 'GETFIELD BB.x : I'
// WITH_RUNTIME // WITH_RUNTIME
interface A { val x: Int } interface A { val x: Int }
@@ -17614,6 +17614,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/ieee754/inline.kt"); runTest("compiler/testData/codegen/box/ieee754/inline.kt");
} }
@Test
@TestMetadata("kt48648_genericField.kt")
public void testKt48648_genericField() throws Exception {
runTest("compiler/testData/codegen/box/ieee754/kt48648_genericField.kt");
}
@Test @Test
@TestMetadata("lessDouble.kt") @TestMetadata("lessDouble.kt")
public void testLessDouble() throws Exception { public void testLessDouble() throws Exception {
@@ -17734,6 +17734,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/ieee754/inline.kt"); runTest("compiler/testData/codegen/box/ieee754/inline.kt");
} }
@Test
@TestMetadata("kt48648_genericField.kt")
public void testKt48648_genericField() throws Exception {
runTest("compiler/testData/codegen/box/ieee754/kt48648_genericField.kt");
}
@Test @Test
@TestMetadata("lessDouble.kt") @TestMetadata("lessDouble.kt")
public void testLessDouble() throws Exception { public void testLessDouble() throws Exception {
@@ -14588,6 +14588,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/ieee754/inline.kt"); runTest("compiler/testData/codegen/box/ieee754/inline.kt");
} }
@TestMetadata("kt48648_genericField.kt")
public void testKt48648_genericField() throws Exception {
runTest("compiler/testData/codegen/box/ieee754/kt48648_genericField.kt");
}
@TestMetadata("lessDouble.kt") @TestMetadata("lessDouble.kt")
public void testLessDouble() throws Exception { public void testLessDouble() throws Exception {
runTest("compiler/testData/codegen/box/ieee754/lessDouble.kt"); runTest("compiler/testData/codegen/box/ieee754/lessDouble.kt");