diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index 981a5045fbc..9f2fc37b99f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -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; diff --git a/compiler/testData/codegen/boxInline/inlineClasses/inlineFunctionInsideInlineClassesBox.kt b/compiler/testData/codegen/boxInline/inlineClasses/inlineFunctionInsideInlineClassesBox.kt index 819412bf417..f8ddd877767 100644 --- a/compiler/testData/codegen/boxInline/inlineClasses/inlineFunctionInsideInlineClassesBox.kt +++ b/compiler/testData/codegen/boxInline/inlineClasses/inlineFunctionInsideInlineClassesBox.kt @@ -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.* diff --git a/compiler/testData/codegen/bytecodeListing/inlineClasses/companionObjectInsideInlineClass.txt b/compiler/testData/codegen/bytecodeListing/inlineClasses/companionObjectInsideInlineClass.txt index b29d85b411d..57a51ba002d 100644 --- a/compiler/testData/codegen/bytecodeListing/inlineClasses/companionObjectInsideInlineClass.txt +++ b/compiler/testData/codegen/bytecodeListing/inlineClasses/companionObjectInsideInlineClass.txt @@ -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 } diff --git a/compiler/testData/codegen/bytecodeListing/inlineClasses/computablePropertiesInsideInlineClass.txt b/compiler/testData/codegen/bytecodeListing/inlineClasses/computablePropertiesInsideInlineClass.txt index b248450aba2..3717a0419a4 100644 --- a/compiler/testData/codegen/bytecodeListing/inlineClasses/computablePropertiesInsideInlineClass.txt +++ b/compiler/testData/codegen/bytecodeListing/inlineClasses/computablePropertiesInsideInlineClass.txt @@ -14,8 +14,6 @@ public final class Foo { private final field x: int public method (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 diff --git a/compiler/testData/codegen/bytecodeListing/inlineClasses/shapeOfInlineClassWithPrimitive.txt b/compiler/testData/codegen/bytecodeListing/inlineClasses/shapeOfInlineClassWithPrimitive.txt index eba35f9bf13..1c9f4750644 100644 --- a/compiler/testData/codegen/bytecodeListing/inlineClasses/shapeOfInlineClassWithPrimitive.txt +++ b/compiler/testData/codegen/bytecodeListing/inlineClasses/shapeOfInlineClassWithPrimitive.txt @@ -14,12 +14,9 @@ public final static class Foo$Erased { public final class Foo { private final field l: long public method (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 } diff --git a/compiler/testData/codegen/bytecodeText/inlineClasses/callMemberMethodsInsideInlineClass.kt b/compiler/testData/codegen/bytecodeText/inlineClasses/callMemberMethodsInsideInlineClass.kt index 5c2780010fb..e9b32168813 100644 --- a/compiler/testData/codegen/bytecodeText/inlineClasses/callMemberMethodsInsideInlineClass.kt +++ b/compiler/testData/codegen/bytecodeText/inlineClasses/callMemberMethodsInsideInlineClass.kt @@ -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 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/inlineClasses/noActualCallsOfInlineFunctionsOfInlineClass.kt b/compiler/testData/codegen/bytecodeText/inlineClasses/noActualCallsOfInlineFunctionsOfInlineClass.kt index 632a1c0b06e..7613aa5572a 100644 --- a/compiler/testData/codegen/bytecodeText/inlineClasses/noActualCallsOfInlineFunctionsOfInlineClass.kt +++ b/compiler/testData/codegen/bytecodeText/inlineClasses/noActualCallsOfInlineFunctionsOfInlineClass.kt @@ -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