diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java index 7a4a458b3ac..0a11e1e3232 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java @@ -438,7 +438,9 @@ public class PropertyCodegen { @Nullable KtPropertyAccessor accessor, @NotNull PropertyAccessorDescriptor accessorDescriptor ) { - if (context instanceof MultifileClassFacadeContext && Visibilities.isPrivate(accessorDescriptor.getVisibility())) { + if (context instanceof MultifileClassFacadeContext && + (Visibilities.isPrivate(accessorDescriptor.getVisibility()) || + AsmUtil.getVisibilityAccessFlag(accessorDescriptor) == Opcodes.ACC_PRIVATE)) { return; } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java index 74a2434dd00..f26b0dd1259 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java @@ -69,7 +69,7 @@ import java.util.*; import static org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags; import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive; import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.*; -import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.hasInlineOnlyAnnotation; +import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isInlineOnly; import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral; public class InlineCodegen extends CallGenerator { @@ -436,7 +436,7 @@ public class InlineCodegen extends CallGenerator { node, parameters, info, new FieldRemapper(null, null, parameters), isSameModule, "Method inlining " + callElement.getText(), createNestedSourceMapper(nodeAndSmap, sourceMapper), info.getCallSiteInfo(), - hasInlineOnlyAnnotation(functionDescriptor) ? new InlineOnlySmapSkipper(codegen) : null + isInlineOnly(functionDescriptor) ? new InlineOnlySmapSkipper(codegen) : null ); //with captured LocalVarRemapper remapper = new LocalVarRemapper(parameters, initialFrameSize); diff --git a/compiler/testData/codegen/boxInline/smap/inlineOnly/noSmapWithProperty.kt b/compiler/testData/codegen/boxInline/smap/inlineOnly/noSmapWithProperty.kt new file mode 100644 index 00000000000..c749d0b31cf --- /dev/null +++ b/compiler/testData/codegen/boxInline/smap/inlineOnly/noSmapWithProperty.kt @@ -0,0 +1,30 @@ +// FILE: 1.kt +// WITH_RUNTIME +package test +inline fun stub() { + +} +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") +@kotlin.internal.InlineOnly +inline val prop: String + get() = "OK" + +// FILE: 2.kt +import test.* + +fun box(): String { + return prop +} + +// FILE: 2.smap + +SMAP +2.kt +Kotlin +*S Kotlin +*F ++ 1 2.kt +_2Kt +*L +1#1,8:1 +*E diff --git a/compiler/testData/codegen/boxInline/smap/inlineOnly/reifiedProperty.kt b/compiler/testData/codegen/boxInline/smap/inlineOnly/reifiedProperty.kt new file mode 100644 index 00000000000..5b9157c7814 --- /dev/null +++ b/compiler/testData/codegen/boxInline/smap/inlineOnly/reifiedProperty.kt @@ -0,0 +1,39 @@ +// FILE: 1.kt +// WITH_REFLECT +package test + +inline val T.className: String; get() = T::class.java.simpleName + +// FILE: 2.kt + +import test.* + +fun box(): String { + val z = "OK".className + if (z != "String") return "fail: $z" + + return "OK" +} + +// FILE: 2.smap + +SMAP +2.kt +Kotlin +*S Kotlin +*F ++ 1 2.kt +_2Kt ++ 2 1.kt +test/_1Kt +*L +1#1,12:1 +5#2:13 +*E +*S KotlinDebug +*F ++ 1 2.kt +_2Kt +*L +6#1:13 +*E \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/InlineOnlyMultifile.kt b/compiler/testData/codegen/bytecodeListing/InlineOnlyMultifile.kt index bbf53ea407a..9883620176b 100644 --- a/compiler/testData/codegen/bytecodeListing/InlineOnlyMultifile.kt +++ b/compiler/testData/codegen/bytecodeListing/InlineOnlyMultifile.kt @@ -5,8 +5,13 @@ package test fun foo() { inlineOnly() + inlineOnlyAnnotated() } // No method should be generated in multifile facade for 'inlineOnly' // Because 'inlineOnly' is private in file part (because it's inline-only) and can't be delegated from facade public inline fun inlineOnly() {} + +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") +@kotlin.internal.InlineOnly +inline fun inlineOnlyAnnotated() { } diff --git a/compiler/testData/codegen/bytecodeListing/InlineOnlyMultifile.txt b/compiler/testData/codegen/bytecodeListing/InlineOnlyMultifile.txt index 489d4bae512..17646e6f65f 100644 --- a/compiler/testData/codegen/bytecodeListing/InlineOnlyMultifile.txt +++ b/compiler/testData/codegen/bytecodeListing/InlineOnlyMultifile.txt @@ -7,4 +7,5 @@ public final class test/Foo { synthetic final class test/Foo__InlineOnlyMultifileKt { public final static method foo(): void private final static method inlineOnly(): void -} \ No newline at end of file + private final static @kotlin.internal.InlineOnly method inlineOnlyAnnotated(): void +} diff --git a/compiler/testData/codegen/bytecodeListing/InlineOnlyPropertyMultifile.kt b/compiler/testData/codegen/bytecodeListing/InlineOnlyPropertyMultifile.kt new file mode 100644 index 00000000000..6a6d2566328 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/InlineOnlyPropertyMultifile.kt @@ -0,0 +1,20 @@ +// WITH_RUNTIME + +@file:[JvmName("Foo") JvmMultifileClass] +package test + +fun foo() { + prop + "".extProp +} + +// No method should be generated in multifile facade for 'inlineOnly' +// Because 'inlineOnly' is private in file part (because it's inline-only) and can't be delegated from facade +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") +@kotlin.internal.InlineOnly +inline var prop: String + get() = "12" + set(value) {} + +inline val Z.extProp: String + get() = "123" diff --git a/compiler/testData/codegen/bytecodeListing/InlineOnlyPropertyMultifile.txt b/compiler/testData/codegen/bytecodeListing/InlineOnlyPropertyMultifile.txt new file mode 100644 index 00000000000..59876542af5 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/InlineOnlyPropertyMultifile.txt @@ -0,0 +1,13 @@ +@kotlin.Metadata +public final class test/Foo { + public final static method foo(): void +} + +@kotlin.Metadata +synthetic final class test/Foo__InlineOnlyPropertyMultifileKt { + public final static method foo(): void + private final static method getExtProp(p0: java.lang.Object): java.lang.String + private final static method getProp(): java.lang.String + private synthetic deprecated static @kotlin.internal.InlineOnly method prop$annotations(): void + private final static method setProp(p0: java.lang.String): void +} diff --git a/compiler/testData/codegen/bytecodeListing/inlineOnlyProperty.kt b/compiler/testData/codegen/bytecodeListing/inlineOnlyProperty.kt new file mode 100644 index 00000000000..77a5c5e0d29 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/inlineOnlyProperty.kt @@ -0,0 +1,38 @@ + +// WITH_RUNTIME + +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") +@kotlin.internal.InlineOnly +inline var prop: String + get() = "12" + set(value) {} + +inline var prop2: String + @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") +@kotlin.internal.InlineOnly + get() = "12" + set(value) {} + + +inline val Z.extProp: String + get() = "123" + +class Foo { + + @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") + @kotlin.internal.InlineOnly + inline var prop: String + get() = "12" + set(value) {} + + inline var prop2: String + @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") + @kotlin.internal.InlineOnly + get() = "12" + set(value) {} + + + inline val Z.extProp: String + get() = "123" + +} diff --git a/compiler/testData/codegen/bytecodeListing/inlineOnlyProperty.txt b/compiler/testData/codegen/bytecodeListing/inlineOnlyProperty.txt new file mode 100644 index 00000000000..2323e6e4e84 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/inlineOnlyProperty.txt @@ -0,0 +1,20 @@ +@kotlin.Metadata +public final class Foo { + public method (): void + private final method getExtProp(p0: java.lang.Object): java.lang.String + private final method getProp(): java.lang.String + private final @kotlin.internal.InlineOnly method getProp2(): java.lang.String + private synthetic deprecated static @kotlin.internal.InlineOnly method prop$annotations(): void + private final method setProp(p0: java.lang.String): void + public final method setProp2(@org.jetbrains.annotations.NotNull p0: java.lang.String): void +} + +@kotlin.Metadata +public final class InlineOnlyPropertyKt { + private final static method getExtProp(p0: java.lang.Object): java.lang.String + private final static method getProp(): java.lang.String + private final static @kotlin.internal.InlineOnly method getProp2(): java.lang.String + private synthetic deprecated static @kotlin.internal.InlineOnly method prop$annotations(): void + private final static method setProp(p0: java.lang.String): void + public final static method setProp2(@org.jetbrains.annotations.NotNull p0: java.lang.String): void +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java index 4345bf3c7c4..eae57dd51fe 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java @@ -2236,11 +2236,23 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo doTest(fileName); } + @TestMetadata("noSmapWithProperty.kt") + public void testNoSmapWithProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/inlineOnly/noSmapWithProperty.kt"); + doTest(fileName); + } + @TestMetadata("reified.kt") public void testReified() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/inlineOnly/reified.kt"); doTest(fileName); } + + @TestMetadata("reifiedProperty.kt") + public void testReifiedProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/inlineOnly/reifiedProperty.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/boxInline/smap/newsmap") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java index 679e57062a4..475afe8cc9e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java @@ -78,6 +78,18 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { doTest(fileName); } + @TestMetadata("inlineOnlyProperty.kt") + public void testInlineOnlyProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/inlineOnlyProperty.kt"); + doTest(fileName); + } + + @TestMetadata("InlineOnlyPropertyMultifile.kt") + public void testInlineOnlyPropertyMultifile() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/InlineOnlyPropertyMultifile.kt"); + doTest(fileName); + } + @TestMetadata("noCollectionStubMethodsInInterface.kt") public void testNoCollectionStubMethodsInInterface() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/noCollectionStubMethodsInInterface.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java index fd274a4e87a..d883a0e802e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -2236,11 +2236,23 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi doTest(fileName); } + @TestMetadata("noSmapWithProperty.kt") + public void testNoSmapWithProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/inlineOnly/noSmapWithProperty.kt"); + doTest(fileName); + } + @TestMetadata("reified.kt") public void testReified() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/inlineOnly/reified.kt"); doTest(fileName); } + + @TestMetadata("reifiedProperty.kt") + public void testReifiedProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/inlineOnly/reifiedProperty.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/boxInline/smap/newsmap") diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/annotationUtil.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/annotationUtil.kt index 2772301399f..b16e4f06fe9 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/annotationUtil.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/annotationUtil.kt @@ -17,12 +17,10 @@ package org.jetbrains.kotlin.descriptors.annotations import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.MemberDescriptor -import org.jetbrains.kotlin.descriptors.SourceElement -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.constants.AnnotationValue import org.jetbrains.kotlin.resolve.constants.ArrayValue import org.jetbrains.kotlin.resolve.constants.EnumValue @@ -73,10 +71,15 @@ private operator fun Collection.get(parameterName: Str private val INLINE_ONLY_ANNOTATION_FQ_NAME = FqName("kotlin.internal.InlineOnly") fun MemberDescriptor.isInlineOnlyOrReified(): Boolean = - this is FunctionDescriptor && (typeParameters.any { it.isReified } || hasInlineOnlyAnnotation()) + this is CallableMemberDescriptor && (isReifiable() || DescriptorUtils.getDirectMember(this).isReifiable() || isInlineOnly()) -fun MemberDescriptor.hasInlineOnlyAnnotation(): Boolean { - if (this !is FunctionDescriptor || !annotations.hasAnnotation(INLINE_ONLY_ANNOTATION_FQ_NAME)) return false +fun MemberDescriptor.isInlineOnly(): Boolean { + if (this !is FunctionDescriptor || + !(hasInlineOnlyAnnotation() || DescriptorUtils.getDirectMember(this).hasInlineOnlyAnnotation())) return false assert(isInline) { "Function is not inline: $this" } return true } + +private fun CallableMemberDescriptor.isReifiable() = typeParameters.any { it.isReified } + +private fun CallableMemberDescriptor.hasInlineOnlyAnnotation() = annotations.hasAnnotation(INLINE_ONLY_ANNOTATION_FQ_NAME) diff --git a/libraries/stdlib/src/kotlin/internal/Annotations.kt b/libraries/stdlib/src/kotlin/internal/Annotations.kt index 6eae8ff6127..a422b260654 100644 --- a/libraries/stdlib/src/kotlin/internal/Annotations.kt +++ b/libraries/stdlib/src/kotlin/internal/Annotations.kt @@ -55,7 +55,7 @@ internal annotation class OnlyInputTypes /** * Specifies that this function should not be called directly without inlining */ -@Target(AnnotationTarget.FUNCTION) +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER) @Retention(AnnotationRetention.BINARY) internal annotation class InlineOnly