[JVM IR] Copy metadata in IrFieldBuilder.

This fixes an issue with lateinit properties where the metadata from
the original field was not copied to the nullable field in
LateinitLowering. Also consolidated related tests.
This commit is contained in:
Mark Punzalan
2020-01-23 13:59:06 -08:00
committed by Alexander Udalov
parent f5f25224b0
commit e226561150
12 changed files with 109 additions and 66 deletions
@@ -47,6 +47,7 @@ fun IrFieldBuilder.buildField(): IrField {
name, type, visibility, isFinal, isExternal, isStatic, name, type, visibility, isFinal, isExternal, isStatic,
origin == IrDeclarationOrigin.FAKE_OVERRIDE origin == IrDeclarationOrigin.FAKE_OVERRIDE
).also { ).also {
it.metadata = metadata
wrappedDescriptor.bind(it) wrappedDescriptor.bind(it)
} }
} }
@@ -181,7 +181,6 @@ class JvmDeclarationFactory(
initializer = oldField.initializer initializer = oldField.initializer
?.replaceThisByStaticReference(this@JvmDeclarationFactory, oldParent, oldParent.thisReceiver!!) ?.replaceThisByStaticReference(this@JvmDeclarationFactory, oldParent, oldParent.thisReceiver!!)
?.patchDeclarationParents(this) as IrExpressionBody? ?.patchDeclarationParents(this) as IrExpressionBody?
(this as IrFieldImpl).metadata = oldField.metadata
} }
} }
} }
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.ir.builders.declarations package org.jetbrains.kotlin.ir.builders.declarations
import org.jetbrains.kotlin.ir.declarations.IrField import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.MetadataSource
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
class IrFieldBuilder : IrDeclarationBuilder() { class IrFieldBuilder : IrDeclarationBuilder() {
@@ -15,6 +16,7 @@ class IrFieldBuilder : IrDeclarationBuilder() {
var isFinal: Boolean = false var isFinal: Boolean = false
var isExternal: Boolean = false var isExternal: Boolean = false
var isStatic: Boolean = false var isStatic: Boolean = false
var metadata: MetadataSource.Property? = null
fun updateFrom(from: IrField) { fun updateFrom(from: IrField) {
super.updateFrom(from) super.updateFrom(from)
@@ -23,5 +25,6 @@ class IrFieldBuilder : IrDeclarationBuilder() {
isFinal = from.isFinal isFinal = from.isFinal
isExternal = from.isExternal isExternal = from.isExternal
isStatic = from.isStatic isStatic = from.isStatic
metadata = from.metadata
} }
} }
@@ -0,0 +1,33 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
import kotlin.reflect.jvm.*
import kotlin.test.*
class K {
lateinit var value: String
}
fun box(): String {
val p = K::value
assertNotNull(p.javaField, "Fail p field")
val getter = p.javaGetter!!
val setter = p.javaSetter!!
assertEquals(K::class.java.getMethod("getValue"), getter)
assertEquals(K::class.java.getMethod("setValue", String::class.java), setter)
assertNull(p.getter.javaConstructor)
assertNull(p.setter.javaConstructor)
val k = K()
assertFails("Fail k getter") { getter.invoke(k) } // lateinit not yet initialized
setter.invoke(k, "foo")
assertEquals("foo", getter.invoke(k), "Fail k setter")
return "OK"
}
@@ -4,25 +4,28 @@
// WITH_REFLECT // WITH_REFLECT
import kotlin.reflect.jvm.* import kotlin.reflect.jvm.*
import kotlin.test.assertEquals import kotlin.test.*
class K(var value: Long) class K(var value: Long)
fun box(): String { fun box(): String {
val p = K::value val p = K::value
assert(p.javaField != null) { "Fail p field" } assertNotNull(p.javaField, "Fail p field")
val getter = p.javaGetter!! val getter = p.javaGetter!!
val setter = p.javaSetter!! val setter = p.javaSetter!!
assertEquals(getter, K::class.java.getMethod("getValue")) assertEquals(K::class.java.getMethod("getValue"), getter)
assertEquals(setter, K::class.java.getMethod("setValue", Long::class.java)) assertEquals(K::class.java.getMethod("setValue", Long::class.java), setter)
assertNull(p.getter.javaConstructor)
assertNull(p.setter.javaConstructor)
val k = K(42L) val k = K(42L)
assert(getter.invoke(k) == 42L) { "Fail k getter" } assertEquals(42L, getter.invoke(k), "Fail k getter")
setter.invoke(k, -239L) setter.invoke(k, -239L)
assert(getter.invoke(k) == -239L) { "Fail k setter" } assertEquals(-239L, getter.invoke(k), "Fail k setter")
return "OK" return "OK"
} }
@@ -0,0 +1,21 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
import kotlin.reflect.*
import kotlin.reflect.full.*
import kotlin.reflect.jvm.*
import kotlin.test.*
class K(private var value: Long)
fun box(): String {
val p = K::class.declaredMemberProperties.single() as KMutableProperty1<K, Long>
assertNotNull(p.javaField, "Fail p field")
assertNull(p.javaGetter, "Fail p getter")
assertNull(p.javaSetter, "Fail p setter")
return "OK"
}
@@ -1,39 +0,0 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
import kotlin.reflect.jvm.*
import kotlin.test.*
var foo = "foo"
class A {
var bar = "bar"
}
fun box(): String {
val fooGetter = ::foo.getter.javaMethod ?: return "Fail fooGetter"
assertEquals("foo", fooGetter.invoke(null))
val fooSetter = ::foo.setter.javaMethod ?: return "Fail fooSetter"
fooSetter.invoke(null, "foof")
assertEquals("foof", foo)
assertNull(::foo.getter.javaConstructor)
assertNull(::foo.setter.javaConstructor)
val a = A()
val barGetter = A::bar.getter.javaMethod ?: return "Fail barGetter"
assertEquals("bar", barGetter.invoke(a))
val barSetter = A::bar.setter.javaMethod ?: return "Fail barSetter"
barSetter.invoke(a, "barb")
assertEquals("barb", a.bar)
assertNull(A::bar.getter.javaConstructor)
assertNull(A::bar.setter.javaConstructor)
return "OK"
}
@@ -4,7 +4,7 @@
// WITH_REFLECT // WITH_REFLECT
import kotlin.reflect.jvm.* import kotlin.reflect.jvm.*
import kotlin.test.assertEquals import kotlin.test.*
var topLevel = "123" var topLevel = "123"
@@ -13,19 +13,21 @@ val fileFacadeClass = object {}::class.java.enclosingClass
fun box(): String { fun box(): String {
val p = ::topLevel val p = ::topLevel
assert(p.javaField != null) { "Fail p field" } assertNotNull(p.javaField, "Fail p field")
val field = p.javaField!! assertEquals(p.javaField!!.getDeclaringClass(), fileFacadeClass)
assertEquals(fileFacadeClass, field.getDeclaringClass())
val getter = p.javaGetter!! val getter = p.javaGetter!!
val setter = p.javaSetter!! val setter = p.javaSetter!!
assertEquals(getter, fileFacadeClass.getMethod("getTopLevel")) assertEquals(fileFacadeClass.getMethod("getTopLevel"), getter)
assertEquals(setter, fileFacadeClass.getMethod("setTopLevel", String::class.java)) assertEquals(fileFacadeClass.getMethod("setTopLevel", String::class.java), setter)
assert(getter.invoke(null) == "123") { "Fail k getter" } assertNull(p.getter.javaConstructor)
assertNull(p.setter.javaConstructor)
assertEquals("123", getter.invoke(null), "Fail k getter")
setter.invoke(null, "456") setter.invoke(null, "456")
assert(getter.invoke(null) == "456") { "Fail k setter" } assertEquals("456", getter.invoke(null), "Fail k setter")
return "OK" return "OK"
} }
@@ -24439,6 +24439,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/reflection/mapping/interfaceCompanionPropertyWithJvmField.kt"); runTest("compiler/testData/codegen/box/reflection/mapping/interfaceCompanionPropertyWithJvmField.kt");
} }
@TestMetadata("lateinitProperty.kt")
public void testLateinitProperty() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/lateinitProperty.kt");
}
@TestMetadata("mappedClassIsEqualToClassLiteral.kt") @TestMetadata("mappedClassIsEqualToClassLiteral.kt")
public void testMappedClassIsEqualToClassLiteral() throws Exception { public void testMappedClassIsEqualToClassLiteral() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/mappedClassIsEqualToClassLiteral.kt"); runTest("compiler/testData/codegen/box/reflection/mapping/mappedClassIsEqualToClassLiteral.kt");
@@ -24464,9 +24469,9 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/reflection/mapping/openSuspendFun.kt"); runTest("compiler/testData/codegen/box/reflection/mapping/openSuspendFun.kt");
} }
@TestMetadata("propertyAccessors.kt") @TestMetadata("privateProperty.kt")
public void testPropertyAccessors() throws Exception { public void testPrivateProperty() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/propertyAccessors.kt"); runTest("compiler/testData/codegen/box/reflection/mapping/privateProperty.kt");
} }
@TestMetadata("propertyAccessorsWithJvmName.kt") @TestMetadata("propertyAccessorsWithJvmName.kt")
@@ -23256,6 +23256,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/reflection/mapping/interfaceCompanionPropertyWithJvmField.kt"); runTest("compiler/testData/codegen/box/reflection/mapping/interfaceCompanionPropertyWithJvmField.kt");
} }
@TestMetadata("lateinitProperty.kt")
public void testLateinitProperty() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/lateinitProperty.kt");
}
@TestMetadata("mappedClassIsEqualToClassLiteral.kt") @TestMetadata("mappedClassIsEqualToClassLiteral.kt")
public void testMappedClassIsEqualToClassLiteral() throws Exception { public void testMappedClassIsEqualToClassLiteral() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/mappedClassIsEqualToClassLiteral.kt"); runTest("compiler/testData/codegen/box/reflection/mapping/mappedClassIsEqualToClassLiteral.kt");
@@ -23281,9 +23286,9 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/reflection/mapping/openSuspendFun.kt"); runTest("compiler/testData/codegen/box/reflection/mapping/openSuspendFun.kt");
} }
@TestMetadata("propertyAccessors.kt") @TestMetadata("privateProperty.kt")
public void testPropertyAccessors() throws Exception { public void testPrivateProperty() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/propertyAccessors.kt"); runTest("compiler/testData/codegen/box/reflection/mapping/privateProperty.kt");
} }
@TestMetadata("propertyAccessorsWithJvmName.kt") @TestMetadata("propertyAccessorsWithJvmName.kt")
@@ -22948,6 +22948,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/reflection/mapping/interfaceCompanionPropertyWithJvmField.kt"); runTest("compiler/testData/codegen/box/reflection/mapping/interfaceCompanionPropertyWithJvmField.kt");
} }
@TestMetadata("lateinitProperty.kt")
public void testLateinitProperty() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/lateinitProperty.kt");
}
@TestMetadata("mappedClassIsEqualToClassLiteral.kt") @TestMetadata("mappedClassIsEqualToClassLiteral.kt")
public void testMappedClassIsEqualToClassLiteral() throws Exception { public void testMappedClassIsEqualToClassLiteral() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/mappedClassIsEqualToClassLiteral.kt"); runTest("compiler/testData/codegen/box/reflection/mapping/mappedClassIsEqualToClassLiteral.kt");
@@ -22973,9 +22978,9 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/reflection/mapping/openSuspendFun.kt"); runTest("compiler/testData/codegen/box/reflection/mapping/openSuspendFun.kt");
} }
@TestMetadata("propertyAccessors.kt") @TestMetadata("privateProperty.kt")
public void testPropertyAccessors() throws Exception { public void testPrivateProperty() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/propertyAccessors.kt"); runTest("compiler/testData/codegen/box/reflection/mapping/privateProperty.kt");
} }
@TestMetadata("propertyAccessorsWithJvmName.kt") @TestMetadata("propertyAccessorsWithJvmName.kt")
@@ -22948,6 +22948,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/reflection/mapping/interfaceCompanionPropertyWithJvmField.kt"); runTest("compiler/testData/codegen/box/reflection/mapping/interfaceCompanionPropertyWithJvmField.kt");
} }
@TestMetadata("lateinitProperty.kt")
public void testLateinitProperty() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/lateinitProperty.kt");
}
@TestMetadata("mappedClassIsEqualToClassLiteral.kt") @TestMetadata("mappedClassIsEqualToClassLiteral.kt")
public void testMappedClassIsEqualToClassLiteral() throws Exception { public void testMappedClassIsEqualToClassLiteral() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/mappedClassIsEqualToClassLiteral.kt"); runTest("compiler/testData/codegen/box/reflection/mapping/mappedClassIsEqualToClassLiteral.kt");
@@ -22973,9 +22978,9 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/reflection/mapping/openSuspendFun.kt"); runTest("compiler/testData/codegen/box/reflection/mapping/openSuspendFun.kt");
} }
@TestMetadata("propertyAccessors.kt") @TestMetadata("privateProperty.kt")
public void testPropertyAccessors() throws Exception { public void testPrivateProperty() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/propertyAccessors.kt"); runTest("compiler/testData/codegen/box/reflection/mapping/privateProperty.kt");
} }
@TestMetadata("propertyAccessorsWithJvmName.kt") @TestMetadata("propertyAccessorsWithJvmName.kt")