Do not generate useless methods inside wrapper for inline class
Fix for test data (inlineFunctionInsideInlineClassesBox.kt) is needed to avoid check about "no inline functions". This check has two steps: first, names of inline functions from the metadata are loaded, then these names are checked that they are presented for physical methods in the classfile. Because now there are no physical methods in the classfile, we can't pass the second check, therefore this fix is needed. #KT-24872 Fixed
This commit is contained in:
@@ -196,6 +196,10 @@ public class FunctionCodegen {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!shouldGenerateMethodInsideInlineClass(origin, functionDescriptor, contextKind, containingDeclaration)) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean hasSpecialBridge = hasSpecialBridgeMethod(functionDescriptor);
|
||||
JvmMethodGenericSignature jvmSignature = strategy.mapMethodSignature(functionDescriptor, typeMapper, contextKind, hasSpecialBridge);
|
||||
Method asmMethod = jvmSignature.getAsmMethod();
|
||||
@@ -255,7 +259,7 @@ public class FunctionCodegen {
|
||||
origin, functionDescriptor, methodContext, strategy, mv, jvmSignature, asmMethod, flags, staticInCompanionObject
|
||||
);
|
||||
}
|
||||
else if (shouldDelegateMethodBodyToInlineClass(origin, functionDescriptor, contextKind, containingDeclaration, bindingContext)) {
|
||||
else if (canDelegateMethodBodyToInlineClass(origin, functionDescriptor, contextKind, containingDeclaration)) {
|
||||
generateMethodInsideInlineClassWrapper(origin, functionDescriptor, (ClassDescriptor) containingDeclaration, mv, typeMapper);
|
||||
}
|
||||
else {
|
||||
@@ -277,12 +281,21 @@ public class FunctionCodegen {
|
||||
return v.newMethod(origin, access, name, desc, signature, exceptions);
|
||||
}
|
||||
|
||||
private static boolean shouldDelegateMethodBodyToInlineClass(
|
||||
private static boolean shouldGenerateMethodInsideInlineClass(
|
||||
@NotNull JvmDeclarationOrigin origin,
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@NotNull OwnerKind contextKind,
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
@NotNull BindingContext bindingContext
|
||||
@NotNull DeclarationDescriptor containingDeclaration
|
||||
) {
|
||||
return !canDelegateMethodBodyToInlineClass(origin, functionDescriptor, contextKind, containingDeclaration) ||
|
||||
!functionDescriptor.getOverriddenDescriptors().isEmpty();
|
||||
}
|
||||
|
||||
private static boolean canDelegateMethodBodyToInlineClass(
|
||||
@NotNull JvmDeclarationOrigin origin,
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@NotNull OwnerKind contextKind,
|
||||
@NotNull DeclarationDescriptor containingDeclaration
|
||||
) {
|
||||
// special kind / function
|
||||
if (contextKind == OwnerKind.ERASED_INLINE_CLASS) return false;
|
||||
|
||||
+2
@@ -11,6 +11,8 @@ inline class A(val x: Int) {
|
||||
inline fun result(other: A): String = if (other.x == x) "OK" else "fail"
|
||||
}
|
||||
|
||||
inline fun stub() {}
|
||||
|
||||
// FILE: 2.kt
|
||||
|
||||
import test.*
|
||||
|
||||
Vendored
-1
@@ -27,7 +27,6 @@ public final class Foo {
|
||||
public method equals(p0: java.lang.Object): boolean
|
||||
public final method getX(): int
|
||||
public method hashCode(): int
|
||||
public final method inInlineClass(): void
|
||||
public method toString(): java.lang.String
|
||||
public final method unbox(): int
|
||||
}
|
||||
|
||||
Vendored
-2
@@ -14,8 +14,6 @@ public final class Foo {
|
||||
private final field x: int
|
||||
public method <init>(p0: int): void
|
||||
public method equals(p0: java.lang.Object): boolean
|
||||
public final method getAsThis(): int
|
||||
public final method getProp(): int
|
||||
public final method getX(): int
|
||||
public method hashCode(): int
|
||||
public method toString(): java.lang.String
|
||||
|
||||
Vendored
-3
@@ -14,12 +14,9 @@ public final static class Foo$Erased {
|
||||
public final class Foo {
|
||||
private final field l: long
|
||||
public method <init>(p0: long): void
|
||||
public final method empty(): void
|
||||
public method equals(p0: java.lang.Object): boolean
|
||||
public final method extension(@org.jetbrains.annotations.NotNull p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.lang.String): void
|
||||
public final method getL(): long
|
||||
public method hashCode(): int
|
||||
public final method param(p0: double): void
|
||||
public method toString(): java.lang.String
|
||||
public final method unbox(): long
|
||||
}
|
||||
|
||||
+3
-3
@@ -12,7 +12,7 @@ inline class Foo(val x: Int) {
|
||||
}
|
||||
}
|
||||
|
||||
// 2 INVOKESTATIC Foo\$Erased.empty \(I\)V
|
||||
// 2 INVOKESTATIC Foo\$Erased.withParam \(ILjava/lang/String;\)V
|
||||
// 2 INVOKESTATIC Foo\$Erased.withInlineClassParam \(II\)V
|
||||
// 1 INVOKESTATIC Foo\$Erased.empty \(I\)V
|
||||
// 1 INVOKESTATIC Foo\$Erased.withParam \(ILjava/lang/String;\)V
|
||||
// 1 INVOKESTATIC Foo\$Erased.withInlineClassParam \(II\)V
|
||||
// 5 INVOKEVIRTUAL
|
||||
Vendored
+4
-4
@@ -1,7 +1,7 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
|
||||
inline class Foo(val x: Int) {
|
||||
inline fun inlineInc(): Foo = Foo(x + 1) // one actual call inside wrapper class Foo
|
||||
inline fun inlineInc(): Foo = Foo(x + 1)
|
||||
fun notInlineInc(): Foo = Foo(x + 1)
|
||||
|
||||
fun foo() {
|
||||
@@ -11,8 +11,8 @@ inline class Foo(val x: Int) {
|
||||
|
||||
fun test(f: Foo) {
|
||||
f.inlineInc().inlineInc().inlineInc()
|
||||
f.notInlineInc() // one here, one inside wrapper class Foo
|
||||
f.notInlineInc() // one here
|
||||
}
|
||||
|
||||
// 1 INVOKESTATIC Foo\$Erased.inlineInc
|
||||
// 2 INVOKESTATIC Foo\$Erased.notInlineInc
|
||||
// 0 INVOKESTATIC Foo\$Erased.inlineInc
|
||||
// 1 INVOKESTATIC Foo\$Erased.notInlineInc
|
||||
|
||||
Reference in New Issue
Block a user