diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/AnnotationCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/AnnotationCodegen.kt index 3767620c87e..a36bfd41d89 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/AnnotationCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/AnnotationCodegen.kt @@ -57,7 +57,11 @@ abstract class AnnotationCodegen( /** * @param returnType can be null if not applicable (e.g. [annotated] is a class) */ - fun genAnnotations(annotated: IrAnnotationContainer?, returnType: Type?, typeForTypeAnnotations: IrType?) { + fun genAnnotations( + annotated: IrAnnotationContainer?, + returnType: Type?, + typeForTypeAnnotations: IrType? + ) { if (annotated == null) return val annotationDescriptorsAlreadyPresent = mutableSetOf() @@ -94,7 +98,10 @@ abstract class AnnotationCodegen( } } - generateAdditionalAnnotations(annotated, returnType, annotationDescriptorsAlreadyPresent) + if (!skipNullabilityAnnotations && annotated is IrDeclaration && returnType != null && !AsmUtil.isPrimitive(returnType)) { + generateNullabilityAnnotationForCallable(annotated, annotationDescriptorsAlreadyPresent) + } + generateTypeAnnotations(annotated, typeForTypeAnnotations) } @@ -109,16 +116,6 @@ abstract class AnnotationCodegen( } - private fun generateAdditionalAnnotations( - annotated: IrAnnotationContainer, - returnType: Type?, - annotationDescriptorsAlreadyPresent: MutableSet - ) { - if (!skipNullabilityAnnotations && annotated is IrDeclaration && returnType != null && !AsmUtil.isPrimitive(returnType)) { - generateNullabilityAnnotationForCallable(annotated, annotationDescriptorsAlreadyPresent) - } - } - private fun generateNullabilityAnnotationForCallable( declaration: IrDeclaration, // There is no superclass that encompasses IrFunction, IrField and nothing else. annotationDescriptorsAlreadyPresent: MutableSet @@ -127,6 +124,7 @@ abstract class AnnotationCodegen( if (declaration is IrValueParameter) { val parent = declaration.parent as IrDeclaration if (isInvisibleForNullabilityAnalysis(parent)) return + if (isMovedReceiverParameterOfStaticInlineClassReplacement(declaration, parent)) return } // No need to annotate annotation methods since they're always non-null @@ -167,6 +165,10 @@ abstract class AnnotationCodegen( generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent, annotationClass) } + private fun isMovedReceiverParameterOfStaticInlineClassReplacement(parameter: IrValueParameter, parent: IrDeclaration): Boolean = + parent.origin == JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_REPLACEMENT && + parameter.origin == IrDeclarationOrigin.MOVED_DISPATCH_RECEIVER + private fun generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent: MutableSet, annotationClass: Class<*>) { val descriptor = Type.getType(annotationClass).descriptor if (!annotationDescriptorsAlreadyPresent.contains(descriptor)) { diff --git a/compiler/testData/codegen/bytecodeListing/inlineClasses/defaultInterfaceMembers/jvmDefaultAll_ir.txt b/compiler/testData/codegen/bytecodeListing/inlineClasses/defaultInterfaceMembers/jvmDefaultAll_ir.txt deleted file mode 100644 index 0d942d45dc1..00000000000 --- a/compiler/testData/codegen/bytecodeListing/inlineClasses/defaultInterfaceMembers/jvmDefaultAll_ir.txt +++ /dev/null @@ -1,53 +0,0 @@ -@kotlin.Metadata -public interface IFooBar { - // source: 'jvmDefaultAll.kt' - public @org.jetbrains.annotations.NotNull method bar(): java.lang.String - public @org.jetbrains.annotations.NotNull method foo(): java.lang.String -} - -@kotlin.Metadata -public interface IFooBar2 { - // source: 'jvmDefaultAll.kt' -} - -@kotlin.jvm.JvmInline -@kotlin.Metadata -public final class Test1 { - // source: 'jvmDefaultAll.kt' - private final @org.jetbrains.annotations.NotNull field k: java.lang.String - private synthetic method (p0: java.lang.String): void - public @org.jetbrains.annotations.NotNull method bar(): java.lang.String - public static @org.jetbrains.annotations.NotNull method bar-impl(@org.jetbrains.annotations.NotNull p0: java.lang.String): java.lang.String - public synthetic final static method box-impl(p0: java.lang.String): Test1 - public static @org.jetbrains.annotations.NotNull method constructor-impl(@org.jetbrains.annotations.NotNull p0: java.lang.String): java.lang.String - public method equals(p0: java.lang.Object): boolean - public static method equals-impl(p0: java.lang.String, p1: java.lang.Object): boolean - public final static method equals-impl0(p0: java.lang.String, p1: java.lang.String): boolean - public final @org.jetbrains.annotations.NotNull method getK(): java.lang.String - public method hashCode(): int - public static method hashCode-impl(p0: java.lang.String): int - public method toString(): java.lang.String - public static method toString-impl(p0: java.lang.String): java.lang.String - public synthetic final method unbox-impl(): java.lang.String -} - -@kotlin.jvm.JvmInline -@kotlin.Metadata -public final class Test2 { - // source: 'jvmDefaultAll.kt' - private final @org.jetbrains.annotations.NotNull field k: java.lang.String - private synthetic method (p0: java.lang.String): void - public @org.jetbrains.annotations.NotNull method bar(): java.lang.String - public static @org.jetbrains.annotations.NotNull method bar-impl(@org.jetbrains.annotations.NotNull p0: java.lang.String): java.lang.String - public synthetic final static method box-impl(p0: java.lang.String): Test2 - public static @org.jetbrains.annotations.NotNull method constructor-impl(@org.jetbrains.annotations.NotNull p0: java.lang.String): java.lang.String - public method equals(p0: java.lang.Object): boolean - public static method equals-impl(p0: java.lang.String, p1: java.lang.Object): boolean - public final static method equals-impl0(p0: java.lang.String, p1: java.lang.String): boolean - public final @org.jetbrains.annotations.NotNull method getK(): java.lang.String - public method hashCode(): int - public static method hashCode-impl(p0: java.lang.String): int - public method toString(): java.lang.String - public static method toString-impl(p0: java.lang.String): java.lang.String - public synthetic final method unbox-impl(): java.lang.String -} diff --git a/compiler/testData/codegen/bytecodeListing/inlineClasses/defaultInterfaceMembers/jvmDefaultEnable_ir.txt b/compiler/testData/codegen/bytecodeListing/inlineClasses/defaultInterfaceMembers/jvmDefaultEnable_ir.txt deleted file mode 100644 index 20c34e9f340..00000000000 --- a/compiler/testData/codegen/bytecodeListing/inlineClasses/defaultInterfaceMembers/jvmDefaultEnable_ir.txt +++ /dev/null @@ -1,53 +0,0 @@ -@kotlin.Metadata -public interface IFooBar { - // source: 'jvmDefaultEnable.kt' - public @kotlin.jvm.JvmDefault @org.jetbrains.annotations.NotNull method bar(): java.lang.String - public @kotlin.jvm.JvmDefault @org.jetbrains.annotations.NotNull method foo(): java.lang.String -} - -@kotlin.Metadata -public interface IFooBar2 { - // source: 'jvmDefaultEnable.kt' -} - -@kotlin.jvm.JvmInline -@kotlin.Metadata -public final class Test1 { - // source: 'jvmDefaultEnable.kt' - private final @org.jetbrains.annotations.NotNull field k: java.lang.String - private synthetic method (p0: java.lang.String): void - public @org.jetbrains.annotations.NotNull method bar(): java.lang.String - public static @org.jetbrains.annotations.NotNull method bar-impl(@org.jetbrains.annotations.NotNull p0: java.lang.String): java.lang.String - public synthetic final static method box-impl(p0: java.lang.String): Test1 - public static @org.jetbrains.annotations.NotNull method constructor-impl(@org.jetbrains.annotations.NotNull p0: java.lang.String): java.lang.String - public method equals(p0: java.lang.Object): boolean - public static method equals-impl(p0: java.lang.String, p1: java.lang.Object): boolean - public final static method equals-impl0(p0: java.lang.String, p1: java.lang.String): boolean - public final @org.jetbrains.annotations.NotNull method getK(): java.lang.String - public method hashCode(): int - public static method hashCode-impl(p0: java.lang.String): int - public method toString(): java.lang.String - public static method toString-impl(p0: java.lang.String): java.lang.String - public synthetic final method unbox-impl(): java.lang.String -} - -@kotlin.jvm.JvmInline -@kotlin.Metadata -public final class Test2 { - // source: 'jvmDefaultEnable.kt' - private final @org.jetbrains.annotations.NotNull field k: java.lang.String - private synthetic method (p0: java.lang.String): void - public @org.jetbrains.annotations.NotNull method bar(): java.lang.String - public static @org.jetbrains.annotations.NotNull method bar-impl(@org.jetbrains.annotations.NotNull p0: java.lang.String): java.lang.String - public synthetic final static method box-impl(p0: java.lang.String): Test2 - public static @org.jetbrains.annotations.NotNull method constructor-impl(@org.jetbrains.annotations.NotNull p0: java.lang.String): java.lang.String - public method equals(p0: java.lang.Object): boolean - public static method equals-impl(p0: java.lang.String, p1: java.lang.Object): boolean - public final static method equals-impl0(p0: java.lang.String, p1: java.lang.String): boolean - public final @org.jetbrains.annotations.NotNull method getK(): java.lang.String - public method hashCode(): int - public static method hashCode-impl(p0: java.lang.String): int - public method toString(): java.lang.String - public static method toString-impl(p0: java.lang.String): java.lang.String - public synthetic final method unbox-impl(): java.lang.String -} diff --git a/compiler/testData/codegen/bytecodeListing/inlineClasses/inlineCharSequence_ir.txt b/compiler/testData/codegen/bytecodeListing/inlineClasses/inlineCharSequence_ir.txt index 1f3d6f5832a..4cf80234401 100644 --- a/compiler/testData/codegen/bytecodeListing/inlineClasses/inlineCharSequence_ir.txt +++ b/compiler/testData/codegen/bytecodeListing/inlineClasses/inlineCharSequence_ir.txt @@ -11,14 +11,14 @@ public final class InlineCharSequence { public static method equals-impl(p0: java.lang.CharSequence, p1: java.lang.Object): boolean public final static method equals-impl0(p0: java.lang.CharSequence, p1: java.lang.CharSequence): boolean public method get(p0: int): char - public static method get-impl(@org.jetbrains.annotations.NotNull p0: java.lang.CharSequence, p1: int): char + public static method get-impl(p0: java.lang.CharSequence, p1: int): char public method getLength(): int - public static method getLength-impl(@org.jetbrains.annotations.NotNull p0: java.lang.CharSequence): int + public static method getLength-impl(p0: java.lang.CharSequence): int public method hashCode(): int public static method hashCode-impl(p0: java.lang.CharSequence): int public synthetic bridge method length(): int public @org.jetbrains.annotations.NotNull method subSequence(p0: int, p1: int): java.lang.CharSequence - public static @org.jetbrains.annotations.NotNull method subSequence-impl(@org.jetbrains.annotations.NotNull p0: java.lang.CharSequence, p1: int, p2: int): java.lang.CharSequence + public static @org.jetbrains.annotations.NotNull method subSequence-impl(p0: java.lang.CharSequence, p1: int, p2: int): java.lang.CharSequence public method toString(): java.lang.String public static method toString-impl(p0: java.lang.CharSequence): java.lang.String public synthetic final method unbox-impl(): java.lang.CharSequence diff --git a/compiler/testData/codegen/bytecodeListing/inlineClasses/inlineCollection/UIntArrayWithFullJdk_ir.txt b/compiler/testData/codegen/bytecodeListing/inlineClasses/inlineCollection/UIntArrayWithFullJdk_ir.txt index 8f0a0a75320..44b3d3082ac 100644 --- a/compiler/testData/codegen/bytecodeListing/inlineClasses/inlineCollection/UIntArrayWithFullJdk_ir.txt +++ b/compiler/testData/codegen/bytecodeListing/inlineClasses/inlineCollection/UIntArrayWithFullJdk_ir.txt @@ -30,22 +30,22 @@ public final class UIntArray { public method clear(): void public static @org.jetbrains.annotations.NotNull method constructor-impl(@org.jetbrains.annotations.NotNull p0: int[]): int[] public synthetic bridge method contains(p0: java.lang.Object): boolean - public static method contains-fLmw4x8(@org.jetbrains.annotations.NotNull p0: int[], p1: int): boolean public method contains-fLmw4x8(p0: int): boolean + public static method contains-fLmw4x8(p0: int[], p1: int): boolean public method containsAll(@org.jetbrains.annotations.NotNull p0: java.util.Collection): boolean - public static method containsAll-impl(@org.jetbrains.annotations.NotNull p0: int[], @org.jetbrains.annotations.NotNull p1: java.util.Collection): boolean + public static method containsAll-impl(p0: int[], @org.jetbrains.annotations.NotNull p1: java.util.Collection): boolean public method equals(p0: java.lang.Object): boolean public static method equals-impl(p0: int[], p1: java.lang.Object): boolean public final static method equals-impl0(p0: int[], p1: int[]): boolean public method getSize(): int - public static method getSize-impl(@org.jetbrains.annotations.NotNull p0: int[]): int + public static method getSize-impl(p0: int[]): int public method hashCode(): int public static method hashCode-impl(p0: int[]): int public method isEmpty(): boolean - public static method isEmpty-impl(@org.jetbrains.annotations.NotNull p0: int[]): boolean + public static method isEmpty-impl(p0: int[]): boolean public @org.jetbrains.annotations.NotNull method iterator(): java.lang.Void public synthetic bridge method iterator(): java.util.Iterator - public static @org.jetbrains.annotations.NotNull method iterator-impl(@org.jetbrains.annotations.NotNull p0: int[]): java.lang.Void + public static @org.jetbrains.annotations.NotNull method iterator-impl(p0: int[]): java.lang.Void public method remove(p0: java.lang.Object): boolean public method removeAll(p0: java.util.Collection): boolean public method removeIf(p0: java.util.function.Predicate): boolean diff --git a/compiler/testData/codegen/bytecodeListing/inlineClasses/nullabilityAnnotationsOnInlineClassMembers.kt b/compiler/testData/codegen/bytecodeListing/inlineClasses/nullabilityAnnotationsOnInlineClassMembers.kt new file mode 100644 index 00000000000..bfb5140ff61 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/inlineClasses/nullabilityAnnotationsOnInlineClassMembers.kt @@ -0,0 +1,19 @@ +inline class Test(val s: String) { + fun memberFun(x: String) = s + + fun String.memberExtFun() = s + + val memberVal + get() = s + + val String.memberExtVal + get() = s + + var memberVar + get() = s + set(value) {} + + var String.memberExtVar + get() = s + set(value) {} +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/inlineClasses/nullabilityAnnotationsOnInlineClassMembers.txt b/compiler/testData/codegen/bytecodeListing/inlineClasses/nullabilityAnnotationsOnInlineClassMembers.txt new file mode 100644 index 00000000000..e7824b55a7f --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/inlineClasses/nullabilityAnnotationsOnInlineClassMembers.txt @@ -0,0 +1,26 @@ +@kotlin.jvm.JvmInline +@kotlin.Metadata +public final class Test { + // source: 'nullabilityAnnotationsOnInlineClassMembers.kt' + private final @org.jetbrains.annotations.NotNull field s: java.lang.String + private synthetic method (p0: java.lang.String): void + public synthetic final static method box-impl(p0: java.lang.String): Test + public static @org.jetbrains.annotations.NotNull method constructor-impl(@org.jetbrains.annotations.NotNull p0: java.lang.String): java.lang.String + public method equals(p0: java.lang.Object): boolean + public static method equals-impl(p0: java.lang.String, p1: java.lang.Object): boolean + public final static method equals-impl0(p0: java.lang.String, p1: java.lang.String): boolean + public final static @org.jetbrains.annotations.NotNull method getMemberExtVal-impl(p0: java.lang.String, @org.jetbrains.annotations.NotNull p1: java.lang.String): java.lang.String + public final static @org.jetbrains.annotations.NotNull method getMemberExtVar-impl(p0: java.lang.String, @org.jetbrains.annotations.NotNull p1: java.lang.String): java.lang.String + public final static @org.jetbrains.annotations.NotNull method getMemberVal-impl(p0: java.lang.String): java.lang.String + public final static @org.jetbrains.annotations.NotNull method getMemberVar-impl(p0: java.lang.String): java.lang.String + public final @org.jetbrains.annotations.NotNull method getS(): java.lang.String + public method hashCode(): int + public static method hashCode-impl(p0: java.lang.String): int + public final static @org.jetbrains.annotations.NotNull method memberExtFun-impl(p0: java.lang.String, @org.jetbrains.annotations.NotNull p1: java.lang.String): java.lang.String + public final static @org.jetbrains.annotations.NotNull method memberFun-impl(p0: java.lang.String, @org.jetbrains.annotations.NotNull p1: java.lang.String): java.lang.String + public final static method setMemberExtVar-impl(p0: java.lang.String, @org.jetbrains.annotations.NotNull p1: java.lang.String, @org.jetbrains.annotations.NotNull p2: java.lang.String): void + public final static method setMemberVar-impl(p0: java.lang.String, @org.jetbrains.annotations.NotNull p1: java.lang.String): void + public method toString(): java.lang.String + public static method toString-impl(p0: java.lang.String): java.lang.String + public synthetic final method unbox-impl(): java.lang.String +} diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java index a0df878ef93..4a6242c1ee5 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java @@ -1046,6 +1046,11 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/noBridgesForErasedInlineClass.kt"); } + @TestMetadata("nullabilityAnnotationsOnInlineClassMembers.kt") + public void testNullabilityAnnotationsOnInlineClassMembers() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/nullabilityAnnotationsOnInlineClassMembers.kt"); + } + @TestMetadata("nullabilityInExpansion.kt") public void testNullabilityInExpansion() throws Exception { runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/nullabilityInExpansion.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java index ee3806fb430..62eeda4bd02 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java @@ -1046,6 +1046,11 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/noBridgesForErasedInlineClass.kt"); } + @TestMetadata("nullabilityAnnotationsOnInlineClassMembers.kt") + public void testNullabilityAnnotationsOnInlineClassMembers() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/nullabilityAnnotationsOnInlineClassMembers.kt"); + } + @TestMetadata("nullabilityInExpansion.kt") public void testNullabilityInExpansion() throws Exception { runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/nullabilityInExpansion.kt");