From ce601bebbef35b4f5b268e9dfd10340f11715723 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Wed, 7 Feb 2018 16:11:33 +0300 Subject: [PATCH] Fix detection of erased `this` for inline class --- .../kotlin/codegen/ExpressionCodegen.java | 7 ++++-- .../kotlin/codegen/JvmCodegenUtil.java | 23 ++++++++----------- .../kotlin/codegen/PropertyCodegen.java | 8 +------ ...callComputablePropertyInsideInlineClass.kt | 17 ++++++++++++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 6 +++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 +++++ .../LightAnalysisModeTestGenerated.java | 6 +++++ .../semantics/JsCodegenBoxTestGenerated.java | 6 +++++ 8 files changed, 57 insertions(+), 22 deletions(-) create mode 100644 compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 6ee27e4a2ce..3bd1e8f52d4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -1673,8 +1673,11 @@ public class ExpressionCodegen extends KtVisitor impleme PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; // `this` is represented as first parameter of function in erased inline class - if (contextKind() == OwnerKind.ERASED_INLINE_CLASS && - InlineClassesUtilsKt.isInlineClass(propertyDescriptor.getContainingDeclaration())) { + boolean isThisOfErasedInlineClass = + contextKind() == OwnerKind.ERASED_INLINE_CLASS && + InlineClassesUtilsKt.isInlineClass(propertyDescriptor.getContainingDeclaration()) && + JvmCodegenUtil.hasBackingField(propertyDescriptor, contextKind(), bindingContext); + if (isThisOfErasedInlineClass) { Type underlyingRepresentationType = typeMapper.mapType(propertyDescriptor.getType()); return StackValue.local(0, underlyingRepresentationType); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java index aad91e722b5..f551879c834 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java @@ -1,17 +1,6 @@ /* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. */ package org.jetbrains.kotlin.codegen; @@ -338,4 +327,12 @@ public class JvmCodegenUtil { isJvmInterface(companionObject.getContainingDeclaration()) && !JvmAbi.isMappedIntrinsicCompanionObject((ClassDescriptor) companionObject); } + + public static boolean hasBackingField( + @NotNull PropertyDescriptor descriptor, @NotNull OwnerKind kind, @NotNull BindingContext bindingContext + ) { + return !isJvmInterface(descriptor.getContainingDeclaration()) && + kind != OwnerKind.DEFAULT_IMPLS && + !Boolean.FALSE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor)); + } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java index 9dcd75aa0c2..7dbd101467b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java @@ -156,7 +156,7 @@ public class PropertyCodegen { private void genBackingFieldAndAnnotations( @Nullable KtNamedDeclaration declaration, @NotNull PropertyDescriptor descriptor, boolean isParameter ) { - boolean hasBackingField = hasBackingField(descriptor); + boolean hasBackingField = JvmCodegenUtil.hasBackingField(descriptor, kind, bindingContext); boolean hasDelegate = declaration instanceof KtProperty && ((KtProperty) declaration).hasDelegate(); AnnotationSplitter annotationSplitter = @@ -303,12 +303,6 @@ public class PropertyCodegen { return null; } - private boolean hasBackingField(@NotNull PropertyDescriptor descriptor) { - return !isJvmInterface(descriptor.getContainingDeclaration()) && - kind != OwnerKind.DEFAULT_IMPLS && - !Boolean.FALSE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor)); - } - private boolean generateBackingField( @NotNull KtNamedDeclaration p, @NotNull PropertyDescriptor descriptor, diff --git a/compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt b/compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt new file mode 100644 index 00000000000..3ba5361784f --- /dev/null +++ b/compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt @@ -0,0 +1,17 @@ +// !LANGUAGE: +InlineClasses + +inline class Props(val intArray: IntArray) { + val size get() = intArray.size + + fun foo(): Int { + val a = size + return a + } +} + +fun box(): String { + val f = Props(intArrayOf(1, 2, 3)) + if (f.foo() != 3) return "fail" + + return "OK" +} \ No newline at end of file diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index cde69be481e..d7202423d55 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -10401,6 +10401,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("callComputablePropertyInsideInlineClass.kt") + public void testCallComputablePropertyInsideInlineClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt"); + doTest(fileName); + } + @TestMetadata("checkBoxingAfterAssertionOperator.kt") public void testCheckBoxingAfterAssertionOperator() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/checkBoxingAfterAssertionOperator.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 09ea04e5178..6aba9d4546f 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -10401,6 +10401,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("callComputablePropertyInsideInlineClass.kt") + public void testCallComputablePropertyInsideInlineClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt"); + doTest(fileName); + } + @TestMetadata("checkBoxingAfterAssertionOperator.kt") public void testCheckBoxingAfterAssertionOperator() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/checkBoxingAfterAssertionOperator.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 59db8f151ac..a5b07fcdaee 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -10401,6 +10401,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes doTest(fileName); } + @TestMetadata("callComputablePropertyInsideInlineClass.kt") + public void testCallComputablePropertyInsideInlineClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt"); + doTest(fileName); + } + @TestMetadata("checkBoxingAfterAssertionOperator.kt") public void testCheckBoxingAfterAssertionOperator() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/checkBoxingAfterAssertionOperator.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index a9b8d27f57e..b0384444ce8 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -11385,6 +11385,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { doTest(fileName); } + @TestMetadata("callComputablePropertyInsideInlineClass.kt") + public void testCallComputablePropertyInsideInlineClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt"); + doTest(fileName); + } + @TestMetadata("checkBoxingAfterAssertionOperator.kt") public void testCheckBoxingAfterAssertionOperator() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/checkBoxingAfterAssertionOperator.kt");