diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index c331a7704bc..e013a0cf321 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -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, diff --git a/compiler/testData/codegen/bytecodeText/inlineClasses/generationOfAccessorToUnderlyingValue.kt b/compiler/testData/codegen/bytecodeText/inlineClasses/generationOfAccessorToUnderlyingValue.kt new file mode 100644 index 00000000000..1c0bb5b243a --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/inlineClasses/generationOfAccessorToUnderlyingValue.kt @@ -0,0 +1,8 @@ +// !LANGUAGE: +InlineClasses + +inline class UInt(val value: Int) + +// 0 INVOKESTATIC UInt\$Erased.getValue + +// 0 valueOf +// 0 intValue \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index 4031de70dab..0d3c7014626 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -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");