Make inline+reified functions synthetic instead of private in bytecode

#KT-18563 Fixed
This commit is contained in:
Alexander Udalov
2019-04-10 15:52:25 +03:00
parent a645b36688
commit f9d61f2dc7
26 changed files with 119 additions and 34 deletions
@@ -65,7 +65,8 @@ import static org.jetbrains.kotlin.codegen.CodegenUtilKt.isToArrayFromCollection
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConstOrHasJvmFieldAnnotation;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
import static org.jetbrains.kotlin.resolve.inline.InlineOnlyKt.isEffectivelyInlineOnly;
import static org.jetbrains.kotlin.resolve.inline.InlineOnlyKt.isInlineOnlyPrivateInBytecode;
import static org.jetbrains.kotlin.resolve.inline.InlineOnlyKt.isInlineWithReified;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
import static org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt.hasJvmDefaultAnnotation;
import static org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt.hasJvmSyntheticAnnotation;
@@ -388,7 +389,8 @@ public class AsmUtil {
flags |= getVarargsFlag(functionDescriptor);
flags |= getDeprecatedAccessFlag(functionDescriptor);
if (deprecationResolver.isDeprecatedHidden(functionDescriptor) ||
(functionDescriptor.isSuspend()) && functionDescriptor.getVisibility().equals(Visibilities.PRIVATE)) {
isInlineWithReified(functionDescriptor) ||
functionDescriptor.isSuspend() && functionDescriptor.getVisibility().equals(Visibilities.PRIVATE)) {
flags |= ACC_SYNTHETIC;
}
return flags;
@@ -526,7 +528,7 @@ public class AsmUtil {
return ACC_PRIVATE;
}
if (isEffectivelyInlineOnly(memberDescriptor)) {
if (isInlineOnlyPrivateInBytecode(memberDescriptor)) {
return ACC_PRIVATE;
}
@@ -76,6 +76,7 @@ import static org.jetbrains.kotlin.descriptors.ModalityKt.isOverridable;
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
import static org.jetbrains.kotlin.resolve.inline.InlineOnlyKt.isEffectivelyInlineOnly;
import static org.jetbrains.kotlin.resolve.inline.InlineOnlyKt.isInlineOnlyPrivateInBytecode;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
import static org.jetbrains.kotlin.resolve.jvm.InlineClassManglingRulesKt.shouldHideConstructorDueToInlineClassTypeValueParameters;
import static org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt.hasJvmDefaultAnnotation;
@@ -1153,10 +1154,10 @@ public class FunctionCodegen {
// $default methods are never private to be accessible from other class files (e.g. inner) without the need of synthetic accessors
// $default methods are never protected to be accessible from subclass nested classes
int visibilityFlag = Visibilities.isPrivate(functionDescriptor.getVisibility()) ||
isEffectivelyInlineOnly(functionDescriptor) ?
AsmUtil.NO_FLAG_PACKAGE_PRIVATE : Opcodes.ACC_PUBLIC;
int flags = visibilityFlag | getDeprecatedAccessFlag(functionDescriptor) | ACC_SYNTHETIC;
int visibilityFlag =
Visibilities.isPrivate(functionDescriptor.getVisibility()) || isInlineOnlyPrivateInBytecode(functionDescriptor)
? AsmUtil.NO_FLAG_PACKAGE_PRIVATE : Opcodes.ACC_PUBLIC;
int flags = visibilityFlag | getDeprecatedAccessFlag(functionDescriptor) | ACC_SYNTHETIC;
if (!(functionDescriptor instanceof ConstructorDescriptor &&
!InlineClassesUtilsKt.isInlineClass(functionDescriptor.getContainingDeclaration()))
) {
@@ -27,7 +27,7 @@ import java.util.*;
import static org.jetbrains.kotlin.codegen.AsmUtil.getVisibilityAccessFlag;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isNonDefaultInterfaceMember;
import static org.jetbrains.kotlin.resolve.inline.InlineOnlyKt.isEffectivelyInlineOnly;
import static org.jetbrains.kotlin.resolve.inline.InlineOnlyKt.isInlineOnlyPrivateInBytecode;
import static org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt.hasJvmDefaultAnnotation;
import static org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt.isCallableMemberWithJvmDefaultAnnotation;
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PRIVATE;
@@ -693,7 +693,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
boolean withinInline,
boolean isSuperCall
) {
if (isEffectivelyInlineOnly(unwrappedDescriptor)) return false;
if (isInlineOnlyPrivateInBytecode(unwrappedDescriptor)) return false;
return isSuperCall && withinInline ||
(accessFlag & ACC_PRIVATE) != 0 ||
@@ -181,7 +181,9 @@ class InlineAnalyzerExtension(
}
if (hasInlineArgs) return
if (functionDescriptor.isInlineOnlyOrReifiable() || functionDescriptor.isExpect || functionDescriptor.isSuspend) return
if (functionDescriptor.isInlineWithReified() || functionDescriptor.isInlineOnly() || functionDescriptor.isExpect ||
functionDescriptor.isSuspend
) return
if (reasonableInlineRules.any { it.isInlineReasonable(functionDescriptor, function, trace.bindingContext) }) return
@@ -14,8 +14,17 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
private val INLINE_ONLY_ANNOTATION_FQ_NAME = FqName("kotlin.internal.InlineOnly")
/**
* @return true if it's impossible to observe a call instruction referencing this member in the bytecode.
*/
fun MemberDescriptor.isEffectivelyInlineOnly(): Boolean =
isInlineWithReified() || isInlineOnly() || isPrivateInlineSuspend()
isInlineWithReified() || isInlineOnlyPrivateInBytecode()
/**
* @return true if this member should be private in bytecode because it's effectively inline-only.
*/
fun MemberDescriptor.isInlineOnlyPrivateInBytecode(): Boolean =
isInlineOnly() || isPrivateInlineSuspend()
fun MemberDescriptor.isInlineOnly(): Boolean =
this is FunctionDescriptor && isInline &&
@@ -431,8 +431,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
forceStatic: Boolean,
forcePrivate: Boolean = false
): Collection<KtLightMethod> {
if (ktFunction.hasAnnotation(JVM_SYNTHETIC_ANNOTATION_FQ_NAME)) return emptyList()
if (ktFunction.hasAnnotation(JVM_SYNTHETIC_ANNOTATION_FQ_NAME) || ktFunction.hasReifiedParameters()) return emptyList()
val basicMethod = asJavaMethod(ktFunction, forceStatic, forcePrivate)
@@ -562,7 +561,6 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
private fun KtDeclaration.isInlineOnly(): Boolean {
if (this !is KtCallableDeclaration || !hasModifier(INLINE_KEYWORD)) return false
if (typeParameters.any { it.hasModifier(REIFIED_KEYWORD) }) return true
if (annotationEntries.isEmpty()) return false
val descriptor = resolve() as? CallableMemberDescriptor ?: return false
@@ -638,7 +636,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
): List<KtLightMethod> {
val propertyName = declaration.name ?: return emptyList()
if (declaration.isConstOrJvmField()) return emptyList()
if (declaration.isConstOrJvmField() || declaration.hasReifiedParameters()) return emptyList()
val ktGetter = (declaration as? KtProperty)?.getter
val ktSetter = (declaration as? KtProperty)?.setter
@@ -704,6 +702,9 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
!declaration.hasModifier(ABSTRACT_KEYWORD)
}
private fun KtCallableDeclaration.hasReifiedParameters(): Boolean =
typeParameters.any { it.hasModifier(REIFIED_KEYWORD) }
override fun getInitializers(): Array<PsiClassInitializer> = emptyArray()
override fun getContainingClass(): PsiClass? =
@@ -0,0 +1,3 @@
public final class InlineReified {
public InlineReified() { /* compiled code */ }
}
+13
View File
@@ -0,0 +1,13 @@
// a.InlineReified
package a
class InlineReified {
inline fun <reified T> foo(x: Any): T = x as T
inline val <reified T> T.bar: T?
get() = null as T?
var <reified T> T.x: String
inline get() = toString()
inline set(value) {}
}
@@ -0,0 +1,11 @@
class C {
inline fun <reified T> foo(x: Any): T = x as T
inline val <reified T> bar: T?
get() = null as T?
set(value) {}
var <reified T> T.x: String
inline get() = toString()
inline set(value) {}
}
@@ -1,10 +1,11 @@
@kotlin.Metadata
public final class test/Foo {
public final static method foo(): void
public synthetic final static method inlineReified(): void
}
@kotlin.Metadata
synthetic final class test/Foo__InlineReifiedMultifileKt {
public final static method foo(): void
private final static method inlineReified(): void
public synthetic final static method inlineReified(): void
}
@@ -1,10 +1,11 @@
@kotlin.Metadata
public final class test/Foo {
public final static method foo(): void
public synthetic final static @org.jetbrains.annotations.NotNull method getExtProp(p0: java.lang.Object): java.lang.String
}
@kotlin.Metadata
synthetic final class test/Foo__InlineReifiedPropertyMultifileKt {
public final static method foo(): void
private final static method getExtProp(p0: java.lang.Object): java.lang.String
public synthetic final static @org.jetbrains.annotations.NotNull method getExtProp(p0: java.lang.Object): java.lang.String
}
@@ -2,11 +2,11 @@
public final class Foo {
public method <init>(): void
public final method bar(): void
private final method baz(): void
public synthetic final method baz(): void
}
@kotlin.Metadata
public final class InlineReifiedKt {
public final static method bar(): void
private final static method baz(): void
public synthetic final static method baz(): void
}
@@ -1,10 +1,10 @@
@kotlin.Metadata
public final class Foo {
public method <init>(): void
private final method getExtProp(p0: java.lang.Object): java.lang.String
public synthetic final @org.jetbrains.annotations.NotNull method getExtProp(p0: java.lang.Object): java.lang.String
}
@kotlin.Metadata
public final class InlineReifiedPropertyKt {
private final static method getExtProp(p0: java.lang.Object): java.lang.String
public synthetic final static @org.jetbrains.annotations.NotNull method getExtProp(p0: java.lang.Object): java.lang.String
}
@@ -7,8 +7,8 @@ public final class Foo {
private final @org.jetbrains.annotations.Nullable method generic$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
public final @org.jetbrains.annotations.Nullable method generic(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
public final @org.jetbrains.annotations.Nullable method generic(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
private final method genericWithReified(p0: java.lang.Object, p1: kotlin.coroutines.Continuation): java.lang.Object
private final method genericWithReified(p0: kotlin.coroutines.Continuation): java.lang.Object
public synthetic final @org.jetbrains.annotations.Nullable method genericWithReified(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
public synthetic final @org.jetbrains.annotations.Nullable method genericWithReified(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
private synthetic final method privateInline(p0: kotlin.coroutines.Continuation): java.lang.Object
private final @kotlin.internal.InlineOnly method shouldNotHaveSuffix(p0: kotlin.coroutines.Continuation): java.lang.Object
private final @org.jetbrains.annotations.Nullable method simple$$forInline(@org.jetbrains.annotations.NotNull p0: kotlin.Unit, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
@@ -25,8 +25,8 @@ public final class SimpleNamedKt {
private final static @org.jetbrains.annotations.Nullable method generic$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
public final static @org.jetbrains.annotations.Nullable method generic(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
public final static @org.jetbrains.annotations.Nullable method generic(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
private final static method genericWithReified(p0: java.lang.Object, p1: kotlin.coroutines.Continuation): java.lang.Object
private final static method genericWithReified(p0: kotlin.coroutines.Continuation): java.lang.Object
public synthetic final static @org.jetbrains.annotations.Nullable method genericWithReified(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
public synthetic final static @org.jetbrains.annotations.Nullable method genericWithReified(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
private synthetic final static method privateInline(p0: kotlin.coroutines.Continuation): java.lang.Object
private final static @kotlin.internal.InlineOnly method shouldNotHaveSuffix(p0: kotlin.coroutines.Continuation): java.lang.Object
private final static @org.jetbrains.annotations.Nullable method simple$$forInline(@org.jetbrains.annotations.NotNull p0: kotlin.Unit, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
@@ -14,8 +14,8 @@ final class test/SamAdapterAndInlinedOneKt$sam$java_lang_Runnable$0 {
@kotlin.Metadata
public final class test/SamAdapterAndInlinedOneKt {
private final static method makeRunnable(p0: kotlin.jvm.functions.Function0): java.lang.Runnable
public synthetic final static @org.jetbrains.annotations.NotNull method makeRunnable(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): java.lang.Runnable
public final static @org.jetbrains.annotations.NotNull method makeRunnable2(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): java.lang.Runnable
public final static @org.jetbrains.annotations.NotNull method noInline(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): java.lang.Runnable
public final static @org.jetbrains.annotations.NotNull method noInline2(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): java.lang.Runnable
}
}
@@ -1,7 +1,7 @@
@kotlin.Metadata
public class AbstractStuff {
public method <init>(): void
private final method hello(p0: java.lang.Object, p1: COROUTINES_PACKAGE.Continuation): java.lang.Object
public synthetic final @org.jetbrains.annotations.Nullable method hello(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: COROUTINES_PACKAGE.Continuation): java.lang.Object
}
@kotlin.Metadata
@@ -1,8 +1,7 @@
// IGNORE_BACKEND: JVM_IR
class MyClass() {
inline fun <reified T> test(s: String = "") {}
}
// TESTED_OBJECT_KIND: function
// TESTED_OBJECTS: MyClass, test$default
// FLAGS: ACC_STATIC, ACC_SYNTHETIC
// FLAGS: ACC_PUBLIC, ACC_STATIC, ACC_SYNTHETIC
+10
View File
@@ -0,0 +1,10 @@
// IGNORE_BACKEND: JVM_IR
class MyClass {
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@kotlin.internal.InlineOnly
inline fun test(s: String) {}
}
// TESTED_OBJECT_KIND: function
// TESTED_OBJECTS: MyClass, test
// FLAGS: ACC_PRIVATE, ACC_FINAL
@@ -99,6 +99,11 @@ public class CompilerLightClassTestGenerated extends AbstractCompilerLightClassT
runTest("compiler/testData/asJava/lightClasses/InheritingInterfaceDefaultImpls.kt");
}
@TestMetadata("InlineReified.kt")
public void testInlineReified() throws Exception {
runTest("compiler/testData/asJava/lightClasses/InlineReified.kt");
}
@TestMetadata("JvmNameOnMember.kt")
public void testJvmNameOnMember() throws Exception {
runTest("compiler/testData/asJava/lightClasses/JvmNameOnMember.kt");
@@ -635,6 +635,11 @@ public class WriteFlagsTestGenerated extends AbstractWriteFlagsTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/writeFlags/inline"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("inlineOnly.kt")
public void testInlineOnly() throws Exception {
runTest("compiler/testData/writeFlags/inline/inlineOnly.kt");
}
@TestMetadata("lostInnerClass.kt")
public void testLostInnerClass() throws Exception {
runTest("compiler/testData/writeFlags/inline/lostInnerClass.kt");
@@ -635,6 +635,11 @@ public class IrWriteFlagsTestGenerated extends AbstractIrWriteFlagsTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/writeFlags/inline"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
}
@TestMetadata("inlineOnly.kt")
public void testInlineOnly() throws Exception {
runTest("compiler/testData/writeFlags/inline/inlineOnly.kt");
}
@TestMetadata("lostInnerClass.kt")
public void testLostInnerClass() throws Exception {
runTest("compiler/testData/writeFlags/inline/lostInnerClass.kt");
@@ -110,13 +110,10 @@ private fun Member.getKPackage(): KDeclarationContainer? =
/**
* Returns a [KFunction] instance corresponding to the given Java [Method] instance,
* or `null` if this method cannot be represented by a Kotlin function
* (for example, if it is a synthetic method).
* or `null` if this method cannot be represented by a Kotlin function.
*/
val Method.kotlinFunction: KFunction<*>?
get() {
if (isSynthetic) return null
if (Modifier.isStatic(modifiers)) {
val kotlinPackage = getKPackage()
if (kotlinPackage != null) {
@@ -104,6 +104,11 @@ public class UltraLightClassLoadingTestGenerated extends AbstractUltraLightClass
runTest("compiler/testData/asJava/ultraLightClasses/inlineOnly.kt");
}
@TestMetadata("inlineReified.kt")
public void testInlineReified() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/inlineReified.kt");
}
@TestMetadata("jvmField.kt")
public void testJvmField() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/jvmField.kt");
@@ -99,6 +99,11 @@ public class UltraLightClassSanityTestGenerated extends AbstractUltraLightClassS
runTest("compiler/testData/asJava/lightClasses/InheritingInterfaceDefaultImpls.kt");
}
@TestMetadata("InlineReified.kt")
public void testInlineReified() throws Exception {
runTest("compiler/testData/asJava/lightClasses/InlineReified.kt");
}
@TestMetadata("JvmNameOnMember.kt")
public void testJvmNameOnMember() throws Exception {
runTest("compiler/testData/asJava/lightClasses/JvmNameOnMember.kt");
@@ -99,6 +99,11 @@ public class IdeCompiledLightClassTestGenerated extends AbstractIdeCompiledLight
runTest("compiler/testData/asJava/lightClasses/InheritingInterfaceDefaultImpls.kt");
}
@TestMetadata("InlineReified.kt")
public void testInlineReified() throws Exception {
runTest("compiler/testData/asJava/lightClasses/InlineReified.kt");
}
@TestMetadata("JvmNameOnMember.kt")
public void testJvmNameOnMember() throws Exception {
runTest("compiler/testData/asJava/lightClasses/JvmNameOnMember.kt");
@@ -99,6 +99,11 @@ public class IdeLightClassTestGenerated extends AbstractIdeLightClassTest {
runTest("compiler/testData/asJava/lightClasses/InheritingInterfaceDefaultImpls.kt");
}
@TestMetadata("InlineReified.kt")
public void testInlineReified() throws Exception {
runTest("compiler/testData/asJava/lightClasses/InlineReified.kt");
}
@TestMetadata("JvmNameOnMember.kt")
public void testJvmNameOnMember() throws Exception {
runTest("compiler/testData/asJava/lightClasses/JvmNameOnMember.kt");