Fix for KT-4206: NoSuchFieldError with class objects
#KT-4206 Fixed
This commit is contained in:
@@ -1956,7 +1956,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
||||||
|
|
||||||
boolean isBackingFieldInAnotherClass = AsmUtil.isPropertyWithBackingFieldInOuterClass(propertyDescriptor);
|
boolean isBackingFieldInAnotherClass = AsmUtil.isPropertyWithBackingFieldInOuterClass(propertyDescriptor);
|
||||||
boolean isStatic = DescriptorUtils.isStaticDeclaration(propertyDescriptor);
|
boolean isStaticBackingField = DescriptorUtils.isStaticDeclaration(propertyDescriptor) || isBackingFieldInAnotherClass;
|
||||||
boolean isSuper = superExpression != null;
|
boolean isSuper = superExpression != null;
|
||||||
boolean isExtensionProperty = propertyDescriptor.getExtensionReceiverParameter() != null;
|
boolean isExtensionProperty = propertyDescriptor.getExtensionReceiverParameter() != null;
|
||||||
|
|
||||||
@@ -1969,16 +1969,17 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
boolean skipPropertyAccessors = forceField && !isBackingFieldInAnotherClass;
|
boolean skipPropertyAccessors = forceField && !isBackingFieldInAnotherClass;
|
||||||
|
|
||||||
CodegenContext backingFieldContext = context.getParentContext();
|
CodegenContext backingFieldContext = context.getParentContext();
|
||||||
|
boolean changeOwnerOnTypeMap = isBackingFieldInAnotherClass;
|
||||||
|
|
||||||
if (isBackingFieldInAnotherClass && forceField) {
|
if (isBackingFieldInAnotherClass && forceField) {
|
||||||
//delegate call to classObject owner : OWNER
|
//delegate call to classObject backingFieldOwner : OWNER
|
||||||
backingFieldContext = context.findParentContextWithDescriptor(containingDeclaration.getContainingDeclaration());
|
backingFieldContext = context.findParentContextWithDescriptor(containingDeclaration.getContainingDeclaration());
|
||||||
int flags = AsmUtil.getVisibilityForSpecialPropertyBackingField(propertyDescriptor, isDelegatedProperty);
|
int flags = AsmUtil.getVisibilityForSpecialPropertyBackingField(propertyDescriptor, isDelegatedProperty);
|
||||||
skipPropertyAccessors = (flags & ACC_PRIVATE) == 0 || methodKind == MethodKind.SYNTHETIC_ACCESSOR || methodKind == MethodKind.INITIALIZER;
|
skipPropertyAccessors = (flags & ACC_PRIVATE) == 0 || methodKind == MethodKind.SYNTHETIC_ACCESSOR || methodKind == MethodKind.INITIALIZER;
|
||||||
if (!skipPropertyAccessors) {
|
if (!skipPropertyAccessors) {
|
||||||
propertyDescriptor = (PropertyDescriptor) backingFieldContext.getAccessor(propertyDescriptor, true, delegateType);
|
propertyDescriptor = (PropertyDescriptor) backingFieldContext.getAccessor(propertyDescriptor, true, delegateType);
|
||||||
|
changeOwnerOnTypeMap = changeOwnerOnTypeMap && !(propertyDescriptor instanceof AccessorForPropertyBackingFieldInOuterClass);
|
||||||
}
|
}
|
||||||
isStatic = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!skipPropertyAccessors) {
|
if (!skipPropertyAccessors) {
|
||||||
@@ -2016,17 +2017,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Type owner;
|
|
||||||
CallableMethod callableMethod = callableGetter != null ? callableGetter : callableSetter;
|
|
||||||
|
|
||||||
propertyDescriptor = DescriptorUtils.unwrapFakeOverride(propertyDescriptor);
|
propertyDescriptor = DescriptorUtils.unwrapFakeOverride(propertyDescriptor);
|
||||||
if (callableMethod == null) {
|
Type backingFieldOwner = typeMapper.mapOwner(changeOwnerOnTypeMap ? propertyDescriptor.getContainingDeclaration() : propertyDescriptor,
|
||||||
owner = typeMapper.mapOwner(isBackingFieldInAnotherClass ? propertyDescriptor.getContainingDeclaration() : propertyDescriptor,
|
isCallInsideSameModuleAsDeclared(propertyDescriptor, context, state.getOutDirectory()));
|
||||||
isCallInsideSameModuleAsDeclared(propertyDescriptor, context, state.getOutDirectory()));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
owner = callableMethod.getOwner();
|
|
||||||
}
|
|
||||||
|
|
||||||
String fieldName;
|
String fieldName;
|
||||||
if (isExtensionProperty && !isDelegatedProperty) {
|
if (isExtensionProperty && !isDelegatedProperty) {
|
||||||
@@ -2041,9 +2034,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
fieldName = JvmAbi.getDefaultFieldNameForProperty(propertyDescriptor.getName(), isDelegatedProperty);
|
fieldName = JvmAbi.getDefaultFieldNameForProperty(propertyDescriptor.getName(), isDelegatedProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
return StackValue.property(propertyDescriptor, owner,
|
return StackValue.property(propertyDescriptor, backingFieldOwner,
|
||||||
typeMapper.mapType(isDelegatedProperty && forceField ? delegateType : propertyDescriptor.getOriginal().getType()),
|
typeMapper.mapType(isDelegatedProperty && forceField ? delegateType : propertyDescriptor.getOriginal().getType()),
|
||||||
isStatic, fieldName, callableGetter, callableSetter, state, receiver);
|
isStaticBackingField, fieldName, callableGetter, callableSetter, state, receiver);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ package org.jetbrains.jet.codegen;
|
|||||||
|
|
||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
import kotlin.Function1;
|
import kotlin.Function1;
|
||||||
import kotlin.Function2;
|
|
||||||
import kotlin.Unit;
|
import kotlin.Unit;
|
||||||
import org.jetbrains.annotations.Contract;
|
import org.jetbrains.annotations.Contract;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -199,16 +198,16 @@ public abstract class StackValue implements StackValueI {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public static Property property(
|
public static Property property(
|
||||||
@NotNull PropertyDescriptor descriptor,
|
@NotNull PropertyDescriptor descriptor,
|
||||||
@NotNull Type methodOwner,
|
@NotNull Type backingFieldOwner,
|
||||||
@NotNull Type type,
|
@NotNull Type type,
|
||||||
boolean isStatic,
|
boolean isStaticBackingField,
|
||||||
@Nullable String fieldName,
|
@Nullable String fieldName,
|
||||||
@Nullable CallableMethod getter,
|
@Nullable CallableMethod getter,
|
||||||
@Nullable CallableMethod setter,
|
@Nullable CallableMethod setter,
|
||||||
GenerationState state,
|
GenerationState state,
|
||||||
@NotNull StackValue receiver
|
@NotNull StackValue receiver
|
||||||
) {
|
) {
|
||||||
return new Property(descriptor, methodOwner, getter, setter, isStatic, fieldName, type, state, receiver);
|
return new Property(descriptor, backingFieldOwner, getter, setter, isStaticBackingField, fieldName, type, state, receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -1028,7 +1027,7 @@ public abstract class StackValue implements StackValueI {
|
|||||||
static class Property extends StackValueWithSimpleReceiver {
|
static class Property extends StackValueWithSimpleReceiver {
|
||||||
private final CallableMethod getter;
|
private final CallableMethod getter;
|
||||||
private final CallableMethod setter;
|
private final CallableMethod setter;
|
||||||
private final Type methodOwner;
|
private final Type backingFieldOwner;
|
||||||
|
|
||||||
private final PropertyDescriptor descriptor;
|
private final PropertyDescriptor descriptor;
|
||||||
private final GenerationState state;
|
private final GenerationState state;
|
||||||
@@ -1036,13 +1035,13 @@ public abstract class StackValue implements StackValueI {
|
|||||||
private final String fieldName;
|
private final String fieldName;
|
||||||
|
|
||||||
public Property(
|
public Property(
|
||||||
@NotNull PropertyDescriptor descriptor, @NotNull Type methodOwner,
|
@NotNull PropertyDescriptor descriptor, @NotNull Type backingFieldOwner,
|
||||||
@Nullable CallableMethod getter, @Nullable CallableMethod setter, boolean isStaticBackingField,
|
@Nullable CallableMethod getter, @Nullable CallableMethod setter, boolean isStaticBackingField,
|
||||||
@Nullable String fieldName, @NotNull Type type, @NotNull GenerationState state,
|
@Nullable String fieldName, @NotNull Type type, @NotNull GenerationState state,
|
||||||
@NotNull StackValue receiver
|
@NotNull StackValue receiver
|
||||||
) {
|
) {
|
||||||
super(type, isStatic(isStaticBackingField, getter), isStatic(isStaticBackingField, setter), receiver);
|
super(type, isStatic(isStaticBackingField, getter), isStatic(isStaticBackingField, setter), receiver);
|
||||||
this.methodOwner = methodOwner;
|
this.backingFieldOwner = backingFieldOwner;
|
||||||
this.getter = getter;
|
this.getter = getter;
|
||||||
this.setter = setter;
|
this.setter = setter;
|
||||||
this.descriptor = descriptor;
|
this.descriptor = descriptor;
|
||||||
@@ -1054,7 +1053,7 @@ public abstract class StackValue implements StackValueI {
|
|||||||
public void putNoReceiver(@NotNull Type type, @NotNull InstructionAdapter v) {
|
public void putNoReceiver(@NotNull Type type, @NotNull InstructionAdapter v) {
|
||||||
if (getter == null) {
|
if (getter == null) {
|
||||||
assert fieldName != null : "Property should have either a getter or a field name: " + descriptor;
|
assert fieldName != null : "Property should have either a getter or a field name: " + descriptor;
|
||||||
v.visitFieldInsn(isStaticPut ? GETSTATIC : GETFIELD, methodOwner.getInternalName(), fieldName, this.type.getDescriptor());
|
v.visitFieldInsn(isStaticPut ? GETSTATIC : GETFIELD, backingFieldOwner.getInternalName(), fieldName, this.type.getDescriptor());
|
||||||
genNotNullAssertionForField(v, state, descriptor);
|
genNotNullAssertionForField(v, state, descriptor);
|
||||||
coerceTo(type, v);
|
coerceTo(type, v);
|
||||||
}
|
}
|
||||||
@@ -1069,7 +1068,7 @@ public abstract class StackValue implements StackValueI {
|
|||||||
coerceFrom(topOfStackType, v);
|
coerceFrom(topOfStackType, v);
|
||||||
if (setter == null) {
|
if (setter == null) {
|
||||||
assert fieldName != null : "Property should have either a setter or a field name: " + descriptor;
|
assert fieldName != null : "Property should have either a setter or a field name: " + descriptor;
|
||||||
v.visitFieldInsn(isStaticStore ? PUTSTATIC : PUTFIELD, methodOwner.getInternalName(), fieldName, this.type.getDescriptor());
|
v.visitFieldInsn(isStaticStore ? PUTSTATIC : PUTFIELD, backingFieldOwner.getInternalName(), fieldName, this.type.getDescriptor());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setter.invokeWithoutAssertions(v);
|
setter.invokeWithoutAssertions(v);
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
class Foo {
|
||||||
|
class object {
|
||||||
|
val bar: String
|
||||||
|
|
||||||
|
{
|
||||||
|
bar = "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return Foo.bar
|
||||||
|
}
|
||||||
@@ -6173,6 +6173,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/staticFields"), Pattern.compile("^(.+)\\.kt$"), true);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/staticFields"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("classObjectAnonymousInitializer.kt")
|
||||||
|
public void testClassObjectAnonymousInitializer() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/staticFields/classObjectAnonymousInitializer.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("classObjectInc.kt")
|
@TestMetadata("classObjectInc.kt")
|
||||||
public void testClassObjectInc() throws Exception {
|
public void testClassObjectInc() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/staticFields/classObjectInc.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/staticFields/classObjectInc.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user