From 1376fed1d472ba06679023aa81b8f5ac13c9b97a Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Mon, 2 Nov 2020 04:06:46 +0100 Subject: [PATCH] Support non-public inline class constructors #KT-28056 Fixed --- .../ir/FirBlackBoxCodegenTestGenerated.java | 5 + .../jetbrains/kotlin/diagnostics/Errors.java | 1 - .../rendering/DefaultErrorMessages.java | 1 - .../checkers/InlineClassDeclarationChecker.kt | 6 - .../constructorImplVisibility.kt | 18 +++ .../inlineClasses/constructor.kt | 11 ++ .../inlineClasses/constructor.txt | 143 ++++++++++++++++++ ...fPublicPrimaryConstructorForInlineClass.kt | 6 +- .../codegen/BlackBoxCodegenTestGenerated.java | 5 + .../codegen/BytecodeListingTestGenerated.java | 5 + .../LightAnalysisModeTestGenerated.java | 5 + .../ir/IrBlackBoxCodegenTestGenerated.java | 5 + .../ir/IrBytecodeListingTestGenerated.java | 5 + 13 files changed, 205 insertions(+), 11 deletions(-) create mode 100644 compiler/testData/codegen/box/inlineClasses/constructorImplVisibility.kt create mode 100644 compiler/testData/codegen/bytecodeListing/inlineClasses/constructor.kt create mode 100644 compiler/testData/codegen/bytecodeListing/inlineClasses/constructor.txt diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 7e1ab8de938..c49c7c56dc3 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -13567,6 +13567,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/inlineClasses/conformToComparableAndCallInterfaceMethod.kt"); } + @TestMetadata("constructorImplVisibility.kt") + public void testConstructorImplVisibility() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/constructorImplVisibility.kt"); + } + @TestMetadata("correctBoxingForBranchExpressions.kt") public void testCorrectBoxingForBranchExpressions() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/correctBoxingForBranchExpressions.kt"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 3619dab4968..592ac5f4f16 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -352,7 +352,6 @@ public interface Errors { DiagnosticFactory0 INLINE_CLASS_NOT_TOP_LEVEL = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 INLINE_CLASS_NOT_FINAL = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 ABSENCE_OF_PRIMARY_CONSTRUCTOR_FOR_INLINE_CLASS = DiagnosticFactory0.create(ERROR); - DiagnosticFactory0 NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 INLINE_CLASS_CONSTRUCTOR_WRONG_PARAMETERS_SIZE = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 7e406404c8f..980b0b6a83a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -706,7 +706,6 @@ public class DefaultErrorMessages { MAP.put(INLINE_CLASS_NOT_TOP_LEVEL, "Inline classes are only allowed on top level"); MAP.put(INLINE_CLASS_NOT_FINAL, "Inline classes can be only final"); MAP.put(ABSENCE_OF_PRIMARY_CONSTRUCTOR_FOR_INLINE_CLASS, "Primary constructor is required for inline class"); - MAP.put(NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS, "Primary constructor of inline class must be public"); MAP.put(INLINE_CLASS_CONSTRUCTOR_WRONG_PARAMETERS_SIZE, "Inline class must have exactly one primary constructor parameter"); MAP.put(INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER, "Inline class primary constructor must have only final read-only (val) property parameter"); MAP.put(PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS, "Inline class cannot have properties with backing fields"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/InlineClassDeclarationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/InlineClassDeclarationChecker.kt index 29362e3b87d..b5f3decc39d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/InlineClassDeclarationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/InlineClassDeclarationChecker.kt @@ -46,12 +46,6 @@ object InlineClassDeclarationChecker : DeclarationChecker { return } - val primaryConstructorVisibility = descriptor.unsubstitutedPrimaryConstructor?.visibility - if (primaryConstructorVisibility != null && primaryConstructorVisibility != DescriptorVisibilities.PUBLIC) { - trace.report(Errors.NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS.on(primaryConstructor.visibilityModifier() ?: inlineKeyword)) - return - } - val baseParameter = primaryConstructor.valueParameters.singleOrNull() if (baseParameter == null) { (primaryConstructor.valueParameterList ?: declaration).let { diff --git a/compiler/testData/codegen/box/inlineClasses/constructorImplVisibility.kt b/compiler/testData/codegen/box/inlineClasses/constructorImplVisibility.kt new file mode 100644 index 00000000000..e7efccb4a1a --- /dev/null +++ b/compiler/testData/codegen/box/inlineClasses/constructorImplVisibility.kt @@ -0,0 +1,18 @@ +// TARGET_BACKEND: JVM +// WITH_RUNTIME +// FULL_JDK + +import java.lang.reflect.Modifier + +inline class IC1 public constructor(val i: Int) +inline class IC11 internal constructor(val i: Int) +inline class IC2 private constructor(val i: Int) +inline class IC4 protected constructor(val i: Int) + +fun box(): String { + if (!Modifier.isPublic(IC1::class.java.declaredMethods.single { it.name == "constructor-impl" }.modifiers)) return "FAIL 1" + if (!Modifier.isPublic(IC11::class.java.declaredMethods.single { it.name == "constructor-impl" }.modifiers)) return "FAIL 1" + if (!Modifier.isPrivate(IC2::class.java.declaredMethods.single { it.name == "constructor-impl" }.modifiers)) return "FAIL 2" + if (!Modifier.isProtected(IC4::class.java.declaredMethods.single { it.name == "constructor-impl" }.modifiers)) return "FAIL 4" + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/inlineClasses/constructor.kt b/compiler/testData/codegen/bytecodeListing/inlineClasses/constructor.kt new file mode 100644 index 00000000000..66824674360 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/inlineClasses/constructor.kt @@ -0,0 +1,11 @@ +// !LANGUAGE: +InlineClasses + +inline class IC1 public constructor(val i: Int) +inline class IC11 internal constructor(val i: Int) +inline class IC2 private constructor(val i: Int) +inline class IC4 protected constructor(val i: Int) + +private inline class PIC1 public constructor(val i: Int) +private inline class PIC11 internal constructor(val i: Int) +private inline class PIC2 private constructor(val i: Int) +private inline class PIC4 protected constructor(val i: Int) \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/inlineClasses/constructor.txt b/compiler/testData/codegen/bytecodeListing/inlineClasses/constructor.txt new file mode 100644 index 00000000000..ee562d2bb17 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/inlineClasses/constructor.txt @@ -0,0 +1,143 @@ +@kotlin.Metadata +public final class IC1 { + // source: 'constructor.kt' + private final field i: int + private synthetic method (p0: int): void + public synthetic final static method box-impl(p0: int): IC1 + public static method constructor-impl(p0: int): int + 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 final method getI(): int + public method hashCode(): int + public static method hashCode-impl(p0: int): int + public method toString(): java.lang.String + public static method toString-impl(p0: int): java.lang.String + public synthetic final method unbox-impl(): int +} + +@kotlin.Metadata +public final class IC11 { + // source: 'constructor.kt' + private final field i: int + private synthetic method (p0: int): void + public synthetic final static method box-impl(p0: int): IC11 + public static method constructor-impl(p0: int): int + 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 final method getI(): int + public method hashCode(): int + public static method hashCode-impl(p0: int): int + public method toString(): java.lang.String + public static method toString-impl(p0: int): java.lang.String + public synthetic final method unbox-impl(): int +} + +@kotlin.Metadata +public final class IC2 { + // source: 'constructor.kt' + private final field i: int + private synthetic method (p0: int): void + public synthetic final static method box-impl(p0: int): IC2 + private static method constructor-impl(p0: int): int + 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 final method getI(): int + public method hashCode(): int + public static method hashCode-impl(p0: int): int + public method toString(): java.lang.String + public static method toString-impl(p0: int): java.lang.String + public synthetic final method unbox-impl(): int +} + +@kotlin.Metadata +public final class IC4 { + // source: 'constructor.kt' + private final field i: int + private synthetic method (p0: int): void + public synthetic final static method box-impl(p0: int): IC4 + protected static method constructor-impl(p0: int): int + 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 final method getI(): int + public method hashCode(): int + public static method hashCode-impl(p0: int): int + public method toString(): java.lang.String + public static method toString-impl(p0: int): java.lang.String + public synthetic final method unbox-impl(): int +} + +@kotlin.Metadata +final class PIC1 { + // source: 'constructor.kt' + private final field i: int + private synthetic method (p0: int): void + public synthetic final static method box-impl(p0: int): PIC1 + public static method constructor-impl(p0: int): int + 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 final method getI(): int + public method hashCode(): int + public static method hashCode-impl(p0: int): int + public method toString(): java.lang.String + public static method toString-impl(p0: int): java.lang.String + public synthetic final method unbox-impl(): int +} + +@kotlin.Metadata +final class PIC11 { + // source: 'constructor.kt' + private final field i: int + private synthetic method (p0: int): void + public synthetic final static method box-impl(p0: int): PIC11 + public static method constructor-impl(p0: int): int + 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 final method getI(): int + public method hashCode(): int + public static method hashCode-impl(p0: int): int + public method toString(): java.lang.String + public static method toString-impl(p0: int): java.lang.String + public synthetic final method unbox-impl(): int +} + +@kotlin.Metadata +final class PIC2 { + // source: 'constructor.kt' + private final field i: int + private synthetic method (p0: int): void + public synthetic final static method box-impl(p0: int): PIC2 + private static method constructor-impl(p0: int): int + 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 final method getI(): int + public method hashCode(): int + public static method hashCode-impl(p0: int): int + public method toString(): java.lang.String + public static method toString-impl(p0: int): java.lang.String + public synthetic final method unbox-impl(): int +} + +@kotlin.Metadata +final class PIC4 { + // source: 'constructor.kt' + private final field i: int + private synthetic method (p0: int): void + public synthetic final static method box-impl(p0: int): PIC4 + protected static method constructor-impl(p0: int): int + 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 final method getI(): int + public method hashCode(): int + public static method hashCode-impl(p0: int): int + public method toString(): java.lang.String + public static method toString-impl(p0: int): java.lang.String + public synthetic final method unbox-impl(): int +} diff --git a/compiler/testData/diagnostics/tests/inlineClasses/presenceOfPublicPrimaryConstructorForInlineClass.kt b/compiler/testData/diagnostics/tests/inlineClasses/presenceOfPublicPrimaryConstructorForInlineClass.kt index 3b33f655c0c..3d4387b1ec7 100644 --- a/compiler/testData/diagnostics/tests/inlineClasses/presenceOfPublicPrimaryConstructorForInlineClass.kt +++ b/compiler/testData/diagnostics/tests/inlineClasses/presenceOfPublicPrimaryConstructorForInlineClass.kt @@ -2,6 +2,6 @@ inline class ConstructorWithDefaultVisibility(val x: Int) inline class PublicConstructor public constructor(val x: Int) -inline class InternalConstructor internal constructor(val x: Int) -inline class ProtectedConstructor protected constructor(val x: Int) -inline class PrivateConstructor private constructor(val x: Int) +inline class InternalConstructor internal constructor(val x: Int) +inline class ProtectedConstructor protected constructor(val x: Int) +inline class PrivateConstructor private constructor(val x: Int) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index d58790fb6b3..5614d9fe66a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -14967,6 +14967,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/inlineClasses/conformToComparableAndCallInterfaceMethod.kt"); } + @TestMetadata("constructorImplVisibility.kt") + public void testConstructorImplVisibility() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/constructorImplVisibility.kt"); + } + @TestMetadata("correctBoxingForBranchExpressions.kt") public void testCorrectBoxingForBranchExpressions() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/correctBoxingForBranchExpressions.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java index 99ce2b1e4f2..89076168231 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java @@ -867,6 +867,11 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/computablePropertiesInsideInlineClass.kt"); } + @TestMetadata("constructor.kt") + public void testConstructor() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/constructor.kt"); + } + @TestMetadata("constructorsWithDefaultParameterValues.kt") public void testConstructorsWithDefaultParameterValues() throws Exception { runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/constructorsWithDefaultParameterValues.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index add8f278fef..a5e575950fc 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -14982,6 +14982,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/inlineClasses/conformToComparableAndCallInterfaceMethod.kt"); } + @TestMetadata("constructorImplVisibility.kt") + public void testConstructorImplVisibility() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/constructorImplVisibility.kt"); + } + @TestMetadata("correctBoxingForBranchExpressions.kt") public void testCorrectBoxingForBranchExpressions() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/correctBoxingForBranchExpressions.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index a457b3f505e..b180d43fae2 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -13567,6 +13567,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/inlineClasses/conformToComparableAndCallInterfaceMethod.kt"); } + @TestMetadata("constructorImplVisibility.kt") + public void testConstructorImplVisibility() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/constructorImplVisibility.kt"); + } + @TestMetadata("correctBoxingForBranchExpressions.kt") public void testCorrectBoxingForBranchExpressions() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/correctBoxingForBranchExpressions.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java index e4ff24726b6..4c8c9ba2923 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java @@ -837,6 +837,11 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/computablePropertiesInsideInlineClass.kt"); } + @TestMetadata("constructor.kt") + public void testConstructor() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/constructor.kt"); + } + @TestMetadata("constructorsWithDefaultParameterValues.kt") public void testConstructorsWithDefaultParameterValues() throws Exception { runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/constructorsWithDefaultParameterValues.kt");