Fix VerifyError on primitive override properties
Don't just blindly map property type in PropertyCodegen when generating getter: we already have its full signature, so we can just as well take the type from it. The former also isn't correct for properties which are overrides with a primitive type. Simple mapType is safe for setter though, because the type of a method parameter cannot change with override on JVM The change in StackValue relates to call sites of properties which return Unit: in that case StackValue's this.type is V, whereas the return type of its getter is Ljet/Unit; -- so coerceTo was coercing from the wrong type in case of getter calls #KT-4373 Fixed #KT-4383 Fixed
This commit is contained in:
@@ -316,7 +316,6 @@ public class PropertyCodegen extends GenerationStateAware {
|
|||||||
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
||||||
InstructionAdapter v = codegen.v;
|
InstructionAdapter v = codegen.v;
|
||||||
PropertyDescriptor propertyDescriptor = callableDescriptor.getCorrespondingProperty();
|
PropertyDescriptor propertyDescriptor = callableDescriptor.getCorrespondingProperty();
|
||||||
Type type = codegen.typeMapper.mapType(propertyDescriptor);
|
|
||||||
|
|
||||||
int paramCode = 0;
|
int paramCode = 0;
|
||||||
if (codegen.context.getContextKind() != OwnerKind.NAMESPACE) {
|
if (codegen.context.getContextKind() != OwnerKind.NAMESPACE) {
|
||||||
@@ -327,6 +326,7 @@ public class PropertyCodegen extends GenerationStateAware {
|
|||||||
StackValue property = codegen.intermediateValueForProperty(propertyDescriptor, true, null);
|
StackValue property = codegen.intermediateValueForProperty(propertyDescriptor, true, null);
|
||||||
|
|
||||||
if (callableDescriptor instanceof PropertyGetterDescriptor) {
|
if (callableDescriptor instanceof PropertyGetterDescriptor) {
|
||||||
|
Type type = signature.getReturnType();
|
||||||
property.put(type, v);
|
property.put(type, v);
|
||||||
v.areturn(type);
|
v.areturn(type);
|
||||||
}
|
}
|
||||||
@@ -335,8 +335,8 @@ public class PropertyCodegen extends GenerationStateAware {
|
|||||||
if (receiverParameter != null) {
|
if (receiverParameter != null) {
|
||||||
paramCode += codegen.typeMapper.mapType(receiverParameter.getType()).getSize();
|
paramCode += codegen.typeMapper.mapType(receiverParameter.getType()).getSize();
|
||||||
}
|
}
|
||||||
|
Type type = codegen.typeMapper.mapType(propertyDescriptor);
|
||||||
v.load(paramCode, type);
|
v.load(paramCode, type);
|
||||||
|
|
||||||
property.store(type, v);
|
property.store(type, v);
|
||||||
v.visitInsn(RETURN);
|
v.visitInsn(RETURN);
|
||||||
} else {
|
} else {
|
||||||
@@ -370,14 +370,9 @@ public class PropertyCodegen extends GenerationStateAware {
|
|||||||
StackValue delegatedProperty = codegen.intermediateValueForProperty(propertyDescriptor, true, null);
|
StackValue delegatedProperty = codegen.intermediateValueForProperty(propertyDescriptor, true, null);
|
||||||
StackValue lastValue = codegen.invokeFunction(call, delegatedProperty, resolvedCall);
|
StackValue lastValue = codegen.invokeFunction(call, delegatedProperty, resolvedCall);
|
||||||
|
|
||||||
if (lastValue.type != Type.VOID_TYPE) {
|
Type asmType = signature.getReturnType();
|
||||||
Type asmType = codegen.typeMapper.mapType(propertyDescriptor);
|
lastValue.put(asmType, v);
|
||||||
lastValue.put(asmType, v);
|
v.areturn(asmType);
|
||||||
v.areturn(asmType);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
v.areturn(Type.VOID_TYPE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -865,12 +865,13 @@ public abstract class StackValue {
|
|||||||
v.visitFieldInsn(isStatic ? GETSTATIC : GETFIELD, methodOwner.getInternalName(), getPropertyName(),
|
v.visitFieldInsn(isStatic ? GETSTATIC : GETFIELD, methodOwner.getInternalName(), getPropertyName(),
|
||||||
this.type.getDescriptor());
|
this.type.getDescriptor());
|
||||||
genNotNullAssertionForField(v, state, descriptor);
|
genNotNullAssertionForField(v, state, descriptor);
|
||||||
|
coerceTo(type, v);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Method method = getter.getAsmMethod();
|
Method method = getter.getAsmMethod();
|
||||||
v.visitMethodInsn(getter.getInvokeOpcode(), getter.getOwner().getInternalName(), method.getName(), method.getDescriptor());
|
v.visitMethodInsn(getter.getInvokeOpcode(), getter.getOwner().getInternalName(), method.getName(), method.getDescriptor());
|
||||||
|
coerce(method.getReturnType(), type, v);
|
||||||
}
|
}
|
||||||
coerceTo(type, v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
trait Tr<T> {
|
||||||
|
val prop: T
|
||||||
|
}
|
||||||
|
|
||||||
|
class A(a: Tr<Int>) : Tr<Int> by a
|
||||||
|
|
||||||
|
fun eat(x: Int) {}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
eat(A(object : Tr<Int> {
|
||||||
|
override val prop = 42
|
||||||
|
}).prop)
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
class D {
|
||||||
|
fun get(a: Any, p: PropertyMetadata) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
object P {
|
||||||
|
val u = Unit.VALUE
|
||||||
|
val v by D()
|
||||||
|
var w = Unit.VALUE
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
if (P.u != P.v) return "Fail uv"
|
||||||
|
P.w = Unit.VALUE
|
||||||
|
if (P.w != P.u) return "Fail w"
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
trait R<in T: Comparable<T>> {
|
||||||
|
var value: T
|
||||||
|
}
|
||||||
|
|
||||||
|
class A(override var value: Int): R<Int>
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val a = A(239)
|
||||||
|
a.value = 42
|
||||||
|
return if (a.value == 42) "OK" else "Fail 1"
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
class Holder(var value: Int) {
|
||||||
|
fun get(that: Any?, desc: PropertyMetadata) = value
|
||||||
|
fun set(that: Any?, desc: PropertyMetadata, newValue: Int) { value = newValue }
|
||||||
|
}
|
||||||
|
|
||||||
|
trait R<in T: Comparable<T>> {
|
||||||
|
var value: T
|
||||||
|
}
|
||||||
|
|
||||||
|
class A(start: Int) : R<Int> {
|
||||||
|
override var value: Int by Holder(start)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val a = A(239)
|
||||||
|
a.value = 42
|
||||||
|
return if (a.value == 42) "OK" else "Fail 1"
|
||||||
|
}
|
||||||
@@ -4470,11 +4470,31 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest("compiler/testData/codegen/box/properties/kt4252_2.kt");
|
doTest("compiler/testData/codegen/box/properties/kt4252_2.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt4373.kt")
|
||||||
|
public void testKt4373() throws Exception {
|
||||||
|
doTest("compiler/testData/codegen/box/properties/kt4373.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt4383.kt")
|
||||||
|
public void testKt4383() throws Exception {
|
||||||
|
doTest("compiler/testData/codegen/box/properties/kt4383.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt613.kt")
|
@TestMetadata("kt613.kt")
|
||||||
public void testKt613() throws Exception {
|
public void testKt613() throws Exception {
|
||||||
doTest("compiler/testData/codegen/box/properties/kt613.kt");
|
doTest("compiler/testData/codegen/box/properties/kt613.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("primitiveOverrideDefaultAccessor.kt")
|
||||||
|
public void testPrimitiveOverrideDefaultAccessor() throws Exception {
|
||||||
|
doTest("compiler/testData/codegen/box/properties/primitiveOverrideDefaultAccessor.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("primitiveOverrideDelegateAccessor.kt")
|
||||||
|
public void testPrimitiveOverrideDelegateAccessor() throws Exception {
|
||||||
|
doTest("compiler/testData/codegen/box/properties/primitiveOverrideDelegateAccessor.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("privatePropertyWithoutBackingField.kt")
|
@TestMetadata("privatePropertyWithoutBackingField.kt")
|
||||||
public void testPrivatePropertyWithoutBackingField() throws Exception {
|
public void testPrivatePropertyWithoutBackingField() throws Exception {
|
||||||
doTest("compiler/testData/codegen/box/properties/privatePropertyWithoutBackingField.kt");
|
doTest("compiler/testData/codegen/box/properties/privatePropertyWithoutBackingField.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user