Fix for KT-14162: Support @InlineOnly on inline properties
#KT-14162 Fixed
This commit is contained in:
@@ -438,7 +438,9 @@ public class PropertyCodegen {
|
|||||||
@Nullable KtPropertyAccessor accessor,
|
@Nullable KtPropertyAccessor accessor,
|
||||||
@NotNull PropertyAccessorDescriptor accessorDescriptor
|
@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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ import java.util.*;
|
|||||||
import static org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags;
|
import static org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags;
|
||||||
import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive;
|
import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive;
|
||||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.*;
|
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;
|
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral;
|
||||||
|
|
||||||
public class InlineCodegen extends CallGenerator {
|
public class InlineCodegen extends CallGenerator {
|
||||||
@@ -436,7 +436,7 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
node, parameters, info, new FieldRemapper(null, null, parameters), isSameModule,
|
node, parameters, info, new FieldRemapper(null, null, parameters), isSameModule,
|
||||||
"Method inlining " + callElement.getText(),
|
"Method inlining " + callElement.getText(),
|
||||||
createNestedSourceMapper(nodeAndSmap, sourceMapper), info.getCallSiteInfo(),
|
createNestedSourceMapper(nodeAndSmap, sourceMapper), info.getCallSiteInfo(),
|
||||||
hasInlineOnlyAnnotation(functionDescriptor) ? new InlineOnlySmapSkipper(codegen) : null
|
isInlineOnly(functionDescriptor) ? new InlineOnlySmapSkipper(codegen) : null
|
||||||
); //with captured
|
); //with captured
|
||||||
|
|
||||||
LocalVarRemapper remapper = new LocalVarRemapper(parameters, initialFrameSize);
|
LocalVarRemapper remapper = new LocalVarRemapper(parameters, initialFrameSize);
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
// FILE: 1.kt
|
||||||
|
// WITH_REFLECT
|
||||||
|
package test
|
||||||
|
|
||||||
|
inline val <reified T : Any> 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
|
||||||
@@ -5,8 +5,13 @@ package test
|
|||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
inlineOnly<String>()
|
inlineOnly<String>()
|
||||||
|
inlineOnlyAnnotated()
|
||||||
}
|
}
|
||||||
|
|
||||||
// No method should be generated in multifile facade for 'inlineOnly'
|
// 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
|
// Because 'inlineOnly' is private in file part (because it's inline-only) and can't be delegated from facade
|
||||||
public inline fun <reified T> inlineOnly() {}
|
public inline fun <reified T> inlineOnly() {}
|
||||||
|
|
||||||
|
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
inline fun inlineOnlyAnnotated() { }
|
||||||
|
|||||||
@@ -7,4 +7,5 @@ public final class test/Foo {
|
|||||||
synthetic final class test/Foo__InlineOnlyMultifileKt {
|
synthetic final class test/Foo__InlineOnlyMultifileKt {
|
||||||
public final static method foo(): void
|
public final static method foo(): void
|
||||||
private final static method inlineOnly(): void
|
private final static method inlineOnly(): void
|
||||||
}
|
private final static @kotlin.internal.InlineOnly method inlineOnlyAnnotated(): void
|
||||||
|
}
|
||||||
|
|||||||
@@ -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 <reified Z> Z.extProp: String
|
||||||
|
get() = "123"
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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 <reified Z> 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 <reified Z> Z.extProp: String
|
||||||
|
get() = "123"
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class Foo {
|
||||||
|
public method <init>(): 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
|
||||||
|
}
|
||||||
@@ -2236,11 +2236,23 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("reified.kt")
|
||||||
public void testReified() throws Exception {
|
public void testReified() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/inlineOnly/reified.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/inlineOnly/reified.kt");
|
||||||
doTest(fileName);
|
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")
|
@TestMetadata("compiler/testData/codegen/boxInline/smap/newsmap")
|
||||||
|
|||||||
@@ -78,6 +78,18 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("noCollectionStubMethodsInInterface.kt")
|
||||||
public void testNoCollectionStubMethodsInInterface() throws Exception {
|
public void testNoCollectionStubMethodsInInterface() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/noCollectionStubMethodsInInterface.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/noCollectionStubMethodsInInterface.kt");
|
||||||
|
|||||||
+12
@@ -2236,11 +2236,23 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("reified.kt")
|
||||||
public void testReified() throws Exception {
|
public void testReified() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/inlineOnly/reified.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/inlineOnly/reified.kt");
|
||||||
doTest(fileName);
|
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")
|
@TestMetadata("compiler/testData/codegen/boxInline/smap/newsmap")
|
||||||
|
|||||||
+10
-7
@@ -17,12 +17,10 @@
|
|||||||
package org.jetbrains.kotlin.descriptors.annotations
|
package org.jetbrains.kotlin.descriptors.annotations
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.MemberDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
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.AnnotationValue
|
||||||
import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
||||||
import org.jetbrains.kotlin.resolve.constants.EnumValue
|
import org.jetbrains.kotlin.resolve.constants.EnumValue
|
||||||
@@ -73,10 +71,15 @@ private operator fun Collection<ValueParameterDescriptor>.get(parameterName: Str
|
|||||||
private val INLINE_ONLY_ANNOTATION_FQ_NAME = FqName("kotlin.internal.InlineOnly")
|
private val INLINE_ONLY_ANNOTATION_FQ_NAME = FqName("kotlin.internal.InlineOnly")
|
||||||
|
|
||||||
fun MemberDescriptor.isInlineOnlyOrReified(): Boolean =
|
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 {
|
fun MemberDescriptor.isInlineOnly(): Boolean {
|
||||||
if (this !is FunctionDescriptor || !annotations.hasAnnotation(INLINE_ONLY_ANNOTATION_FQ_NAME)) return false
|
if (this !is FunctionDescriptor ||
|
||||||
|
!(hasInlineOnlyAnnotation() || DescriptorUtils.getDirectMember(this).hasInlineOnlyAnnotation())) return false
|
||||||
assert(isInline) { "Function is not inline: $this" }
|
assert(isInline) { "Function is not inline: $this" }
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun CallableMemberDescriptor.isReifiable() = typeParameters.any { it.isReified }
|
||||||
|
|
||||||
|
private fun CallableMemberDescriptor.hasInlineOnlyAnnotation() = annotations.hasAnnotation(INLINE_ONLY_ANNOTATION_FQ_NAME)
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ internal annotation class OnlyInputTypes
|
|||||||
/**
|
/**
|
||||||
* Specifies that this function should not be called directly without inlining
|
* 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)
|
@Retention(AnnotationRetention.BINARY)
|
||||||
internal annotation class InlineOnly
|
internal annotation class InlineOnly
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user