Fix generation of property accessor to the underlying value

This commit is contained in:
Mikhail Zarechenskiy
2018-02-07 17:50:02 +03:00
parent ce601bebbe
commit 2c279978c8
3 changed files with 43 additions and 9 deletions
@@ -239,20 +239,12 @@ public class FunctionCodegen {
!(containingDeclaration instanceof PackageFragmentDescriptor) &&
origin.getOriginKind() != JvmDeclarationOriginKind.CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL;
boolean isMethodInInlineClassWrapper =
isClass(containingDeclaration) &&
((ClassDescriptor) containingDeclaration).isInline() &&
contextKind != OwnerKind.ERASED_INLINE_CLASS &&
!(functionDescriptor instanceof ConstructorDescriptor) &&
!KotlinTypeMapper.isAccessor(functionDescriptor) &&
origin.getOriginKind() != JvmDeclarationOriginKind.UNBOX_METHOD_OF_INLINE_CLASS;
if (isOpenSuspendInClass) {
generateOpenMethodInSuspendClass(
origin, functionDescriptor, methodContext, strategy, mv, jvmSignature, asmMethod, flags, staticInCompanionObject
);
}
else if (isMethodInInlineClassWrapper) {
else if (shouldDelegateMethodBodyToInlineClass(origin, functionDescriptor, contextKind, containingDeclaration, bindingContext)) {
generateMethodInsideInlineClassWrapper(origin, functionDescriptor, (ClassDescriptor) containingDeclaration, mv);
}
else {
@@ -262,6 +254,34 @@ public class FunctionCodegen {
}
}
private static boolean shouldDelegateMethodBodyToInlineClass(
@NotNull JvmDeclarationOrigin origin,
@NotNull FunctionDescriptor functionDescriptor,
@NotNull OwnerKind contextKind,
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull BindingContext bindingContext
) {
// special kind / function
if (contextKind == OwnerKind.ERASED_INLINE_CLASS) return false;
if (origin.getOriginKind() == JvmDeclarationOriginKind.UNBOX_METHOD_OF_INLINE_CLASS) return false;
// descriptor corresponds to the underlying value
if (functionDescriptor instanceof PropertyAccessorDescriptor) {
PropertyDescriptor property = ((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty();
// property for the underlying value
if (JvmCodegenUtil.hasBackingField(property, contextKind, bindingContext)) {
return false;
}
}
// base check
boolean isInlineClass = isClass(containingDeclaration) && ((ClassDescriptor) containingDeclaration).isInline();
boolean simpleFunctionOrProperty =
!(functionDescriptor instanceof ConstructorDescriptor) && !KotlinTypeMapper.isAccessor(functionDescriptor);
return isInlineClass && simpleFunctionOrProperty;
}
private void generateMethodInsideInlineClassWrapper(
@NotNull JvmDeclarationOrigin origin,
@NotNull FunctionDescriptor functionDescriptor,
@@ -0,0 +1,8 @@
// !LANGUAGE: +InlineClasses
inline class UInt(val value: Int)
// 0 INVOKESTATIC UInt\$Erased.getValue
// 0 valueOf
// 0 intValue
@@ -1944,6 +1944,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
doTest(fileName);
}
@TestMetadata("generationOfAccessorToUnderlyingValue.kt")
public void testGenerationOfAccessorToUnderlyingValue() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/generationOfAccessorToUnderlyingValue.kt");
doTest(fileName);
}
@TestMetadata("inlineClassBoxingOnAssignment.kt")
public void testInlineClassBoxingOnAssignment() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/inlineClassBoxingOnAssignment.kt");