From 0d55c9108d46b508bab4c22578772578a9b8f278 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Fri, 27 Nov 2020 23:44:57 +0100 Subject: [PATCH] IC: Forbid inner classes inside inline classes #KT-43067 Fixed --- ...irOldFrontendDiagnosticsTestGenerated.java | 5 ++++ .../jetbrains/kotlin/diagnostics/Errors.java | 1 + .../rendering/DefaultErrorMessages.java | 1 + .../resolve/PlatformConfiguratorBase.kt | 1 + .../checkers/InlineClassDeclarationChecker.kt | 12 ++++++++ .../codegen/box/inlineClasses/kt27705.kt | 1 + .../codegen/box/inlineClasses/kt27706.kt | 1 + .../constructorWithInlineClassParameters.kt | 1 + .../innerClassInsideInlineClass.fir.kt | 8 +++++ .../innerClassInsideInlineClass.kt | 8 +++++ .../innerClassInsideInlineClass.txt | 29 +++++++++++++++++++ .../checkers/DiagnosticsTestGenerated.java | 5 ++++ .../DiagnosticsUsingJavacTestGenerated.java | 5 ++++ 13 files changed, 78 insertions(+) create mode 100644 compiler/testData/diagnostics/tests/inlineClasses/innerClassInsideInlineClass.fir.kt create mode 100644 compiler/testData/diagnostics/tests/inlineClasses/innerClassInsideInlineClass.kt create mode 100644 compiler/testData/diagnostics/tests/inlineClasses/innerClassInsideInlineClass.txt diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java index 6461511a692..ee445859742 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java @@ -12917,6 +12917,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/inlineClasses/inlineClassesInsideAnnotations.kt"); } + @TestMetadata("innerClassInsideInlineClass.kt") + public void testInnerClassInsideInlineClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/inlineClasses/innerClassInsideInlineClass.kt"); + } + @TestMetadata("lateinitInlineClasses.kt") public void testLateinitInlineClasses() throws Exception { runTest("compiler/testData/diagnostics/tests/inlineClasses/lateinitInlineClasses.kt"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 821a05c031e..af6d60a3286 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -362,6 +362,7 @@ public interface Errors { DiagnosticFactory0 INLINE_CLASS_CANNOT_BE_RECURSIVE = DiagnosticFactory0.create(ERROR); DiagnosticFactory1 RESERVED_MEMBER_INSIDE_INLINE_CLASS = DiagnosticFactory1.create(ERROR); DiagnosticFactory0 SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_INLINE_CLASS = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 INNER_CLASS_INSIDE_INLINE_CLASS = DiagnosticFactory0.create(ERROR); // Result class 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 1d7d12906bc..135f8d5ebd7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -717,6 +717,7 @@ public class DefaultErrorMessages { MAP.put(INLINE_CLASS_CANNOT_BE_RECURSIVE, "Inline class cannot be recursive"); MAP.put(RESERVED_MEMBER_INSIDE_INLINE_CLASS, "Member with the name ''{0}'' is reserved for future releases", STRING); MAP.put(SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_INLINE_CLASS, "Secondary constructors with bodies are reserved for for future releases"); + MAP.put(INNER_CLASS_INSIDE_INLINE_CLASS, "Inline class cannot have inner classes"); MAP.put(RESULT_CLASS_IN_RETURN_TYPE, "'kotlin.Result' cannot be used as a return type"); MAP.put(RESULT_CLASS_WITH_NULLABLE_OPERATOR, "Expression of type 'kotlin.Result' cannot be used as a left operand of ''{0}''", STRING); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt index 5f5a9aba0f9..10c744d58d3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt @@ -28,6 +28,7 @@ private val DEFAULT_DECLARATION_CHECKERS = listOf( SuspendLimitationsChecker, InlineClassDeclarationChecker, PropertiesWithBackingFieldsInsideInlineClass(), + InnerClassInsideInlineClass(), AnnotationClassTargetAndRetentionChecker(), ReservedMembersAndConstructsForInlineClass(), ResultClassInReturnTypeChecker(), 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 66616901983..97bc3378858 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/InlineClassDeclarationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/InlineClassDeclarationChecker.kt @@ -124,6 +124,18 @@ class PropertiesWithBackingFieldsInsideInlineClass : DeclarationChecker { } } +class InnerClassInsideInlineClass : DeclarationChecker { + override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) { + if (declaration !is KtClass) return + if (descriptor !is ClassDescriptor) return + if (!descriptor.isInner) return + + if (!descriptor.containingDeclaration.isInlineClass()) return + + context.trace.report(Errors.INNER_CLASS_INSIDE_INLINE_CLASS.on(declaration.modifierList!!.getModifier(KtTokens.INNER_KEYWORD)!!)) + } +} + class ReservedMembersAndConstructsForInlineClass : DeclarationChecker { companion object { diff --git a/compiler/testData/codegen/box/inlineClasses/kt27705.kt b/compiler/testData/codegen/box/inlineClasses/kt27705.kt index 49ba36aa170..dbc9fbb6785 100644 --- a/compiler/testData/codegen/box/inlineClasses/kt27705.kt +++ b/compiler/testData/codegen/box/inlineClasses/kt27705.kt @@ -2,6 +2,7 @@ // WITH_RUNTIME inline class Z(val x: Int) { + @Suppress("INNER_CLASS_INSIDE_INLINE_CLASS") inner class Inner(val y: Int) { val xx = x } diff --git a/compiler/testData/codegen/box/inlineClasses/kt27706.kt b/compiler/testData/codegen/box/inlineClasses/kt27706.kt index 3ef3ea87971..c5179393421 100644 --- a/compiler/testData/codegen/box/inlineClasses/kt27706.kt +++ b/compiler/testData/codegen/box/inlineClasses/kt27706.kt @@ -2,6 +2,7 @@ // WITH_RUNTIME inline class Z(val x: Int) { + @Suppress("INNER_CLASS_INSIDE_INLINE_CLASS") inner class Inner(val z: Z) { val xx = x } diff --git a/compiler/testData/codegen/box/reflection/call/inlineClasses/constructorWithInlineClassParameters.kt b/compiler/testData/codegen/box/reflection/call/inlineClasses/constructorWithInlineClassParameters.kt index afd064f8144..fb2716354de 100644 --- a/compiler/testData/codegen/box/reflection/call/inlineClasses/constructorWithInlineClassParameters.kt +++ b/compiler/testData/codegen/box/reflection/call/inlineClasses/constructorWithInlineClassParameters.kt @@ -12,6 +12,7 @@ class Outer(val z1: Z) { } inline class InlineOuter(val z1: Z) { + @Suppress("INNER_CLASS_INSIDE_INLINE_CLASS") inner class Inner(val z2: Z) { val test = "$z1 $z2" } diff --git a/compiler/testData/diagnostics/tests/inlineClasses/innerClassInsideInlineClass.fir.kt b/compiler/testData/diagnostics/tests/inlineClasses/innerClassInsideInlineClass.fir.kt new file mode 100644 index 00000000000..7188dcc1dc1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inlineClasses/innerClassInsideInlineClass.fir.kt @@ -0,0 +1,8 @@ +// !LANGUAGE: +InlineClasses +// !DIAGNOSTICS: -UNUSED_VARIABLE + +inline class Foo(val x: Int) { + inner class InnerC + inner object InnerO + inner interface InnerI +} diff --git a/compiler/testData/diagnostics/tests/inlineClasses/innerClassInsideInlineClass.kt b/compiler/testData/diagnostics/tests/inlineClasses/innerClassInsideInlineClass.kt new file mode 100644 index 00000000000..3c64938fd96 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inlineClasses/innerClassInsideInlineClass.kt @@ -0,0 +1,8 @@ +// !LANGUAGE: +InlineClasses +// !DIAGNOSTICS: -UNUSED_VARIABLE + +inline class Foo(val x: Int) { + inner class InnerC + inner object InnerO + inner interface InnerI +} diff --git a/compiler/testData/diagnostics/tests/inlineClasses/innerClassInsideInlineClass.txt b/compiler/testData/diagnostics/tests/inlineClasses/innerClassInsideInlineClass.txt new file mode 100644 index 00000000000..214e6b891c9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inlineClasses/innerClassInsideInlineClass.txt @@ -0,0 +1,29 @@ +package + +public final inline class Foo { + public constructor Foo(/*0*/ x: kotlin.Int) + public final val x: kotlin.Int + public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String + + public final inner class InnerC { + public constructor InnerC() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public interface InnerI { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public object InnerO { + private constructor InnerO() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} diff --git a/compiler/tests-gen/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 0b2c9fb6136..da47f330b4a 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -12924,6 +12924,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali runTest("compiler/testData/diagnostics/tests/inlineClasses/inlineClassesInsideAnnotations.kt"); } + @TestMetadata("innerClassInsideInlineClass.kt") + public void testInnerClassInsideInlineClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/inlineClasses/innerClassInsideInlineClass.kt"); + } + @TestMetadata("lateinitInlineClasses.kt") public void testLateinitInlineClasses() throws Exception { runTest("compiler/testData/diagnostics/tests/inlineClasses/lateinitInlineClasses.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index ac73819e95e..6d1619ed9ba 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -12919,6 +12919,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inlineClasses/inlineClassesInsideAnnotations.kt"); } + @TestMetadata("innerClassInsideInlineClass.kt") + public void testInnerClassInsideInlineClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/inlineClasses/innerClassInsideInlineClass.kt"); + } + @TestMetadata("lateinitInlineClasses.kt") public void testLateinitInlineClasses() throws Exception { runTest("compiler/testData/diagnostics/tests/inlineClasses/lateinitInlineClasses.kt");