From 1a0aab4a44ed138d3e3403ae24540a3333d0b11f Mon Sep 17 00:00:00 2001 From: Anastasiya Shadrina Date: Tue, 16 Mar 2021 19:21:05 +0700 Subject: [PATCH] [FE] Inline classes cannot have context receivers --- .../FirOldFrontendDiagnosticsTestGenerated.java | 6 ++++++ .../org/jetbrains/kotlin/diagnostics/Errors.java | 1 + .../rendering/DefaultErrorMessages.java | 1 + .../checkers/InlineClassDeclarationChecker.kt | 6 ++++++ .../org/jetbrains/kotlin/psi/KtClassOrObject.kt | 16 ++++++++++++++++ .../noContextReceiversOnInlineClasses.fir.kt | 6 ++++++ .../noContextReceiversOnInlineClasses.kt | 6 ++++++ .../noContextReceiversOnInlineClasses.txt | 16 ++++++++++++++++ .../test/runners/DiagnosticTestGenerated.java | 6 ++++++ 9 files changed, 64 insertions(+) create mode 100644 compiler/testData/diagnostics/tests/extensions/contextReceivers/noContextReceiversOnInlineClasses.fir.kt create mode 100644 compiler/testData/diagnostics/tests/extensions/contextReceivers/noContextReceiversOnInlineClasses.kt create mode 100644 compiler/testData/diagnostics/tests/extensions/contextReceivers/noContextReceiversOnInlineClasses.txt diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index a50e908be94..2812c76612e 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -10612,6 +10612,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/noBackingField.kt"); } + @Test + @TestMetadata("noContextReceiversOnInlineClasses.kt") + public void testNoContextReceiversOnInlineClasses() throws Exception { + runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/noContextReceiversOnInlineClasses.kt"); + } + @Test @TestMetadata("noExplicitReceiver.kt") public void testNoExplicitReceiver() throws Exception { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 035cae444ae..dafee7bb565 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -385,6 +385,7 @@ public interface Errors { DiagnosticFactory0 INNER_CLASS_INSIDE_VALUE_CLASS = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 VALUE_CLASS_CANNOT_BE_CLONEABLE = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 INLINE_CLASS_DEPRECATED = DiagnosticFactory0.create(WARNING); + DiagnosticFactory0 INLINE_CLASS_CANNOT_HAVE_CONTEXT_RECEIVERS = 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 ecd91af674f..45dbd9002f5 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -761,6 +761,7 @@ public class DefaultErrorMessages { MAP.put(INNER_CLASS_INSIDE_VALUE_CLASS, "Value class cannot have inner classes"); MAP.put(VALUE_CLASS_CANNOT_BE_CLONEABLE, "Value class cannot be Cloneable"); MAP.put(INLINE_CLASS_DEPRECATED, "'inline' modifier is deprecated. Use 'value' instead"); + MAP.put(INLINE_CLASS_CANNOT_HAVE_CONTEXT_RECEIVERS, "Inline classes cannot have context receivers"); 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/checkers/InlineClassDeclarationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/InlineClassDeclarationChecker.kt index 1c2632b6a14..59b130f8aac 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/InlineClassDeclarationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/InlineClassDeclarationChecker.kt @@ -58,6 +58,12 @@ object InlineClassDeclarationChecker : DeclarationChecker { return } + if (declaration.contextReceivers.isNotEmpty()) { + val contextReceiverList = declaration.getContextReceiverList() + requireNotNull(contextReceiverList) { "Declaration cannot have context receivers with no context receiver list" } + trace.report(Errors.INLINE_CLASS_CANNOT_HAVE_CONTEXT_RECEIVERS.on(contextReceiverList)) + } + val modalityModifier = declaration.modalityModifier() if (modalityModifier != null && descriptor.modality != Modality.FINAL) { trace.report(Errors.VALUE_CLASS_NOT_FINAL.on(modalityModifier)) diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtClassOrObject.kt b/compiler/psi/src/org/jetbrains/kotlin/psi/KtClassOrObject.kt index f2847dfceb3..ea01417b63a 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/KtClassOrObject.kt +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtClassOrObject.kt @@ -188,6 +188,22 @@ abstract class KtClassOrObject : return parts.joinToString(separator = ".") } + fun getContextReceiverList(): KtContextReceiverList? { + val stub = stub + if (stub != null) { + return getStubOrPsiChild(KtStubElementTypes.CONTEXT_RECEIVER_LIST) + } + var node = node.firstChildNode + while (node != null) { + val tt = node.elementType + if (tt === KtNodeTypes.CONTEXT_RECEIVER_LIST) { + return node.psi as KtContextReceiverList + } + node = node.treeNext + } + return null + } + override fun getContextReceivers(): List { val stub = stub if (stub != null) { diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/noContextReceiversOnInlineClasses.fir.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/noContextReceiversOnInlineClasses.fir.kt new file mode 100644 index 00000000000..e076b2f3d30 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/noContextReceiversOnInlineClasses.fir.kt @@ -0,0 +1,6 @@ +// !LANGUAGE: +InlineClasses, -JvmInlineValueClasses + +class A + +context(A) +inline class B(val x: Int) \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/noContextReceiversOnInlineClasses.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/noContextReceiversOnInlineClasses.kt new file mode 100644 index 00000000000..258496c950e --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/noContextReceiversOnInlineClasses.kt @@ -0,0 +1,6 @@ +// !LANGUAGE: +InlineClasses, -JvmInlineValueClasses + +class A + +context(A) +inline class B(val x: Int) \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/noContextReceiversOnInlineClasses.txt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/noContextReceiversOnInlineClasses.txt new file mode 100644 index 00000000000..c2cd50a79b5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/noContextReceiversOnInlineClasses.txt @@ -0,0 +1,16 @@ +package + +public final class A { + public constructor A() + 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 final inline class B { + public constructor B(/*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 +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index ee743e6bf29..c291f4c95d2 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -10618,6 +10618,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/noBackingField.kt"); } + @Test + @TestMetadata("noContextReceiversOnInlineClasses.kt") + public void testNoContextReceiversOnInlineClasses() throws Exception { + runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/noContextReceiversOnInlineClasses.kt"); + } + @Test @TestMetadata("noExplicitReceiver.kt") public void testNoExplicitReceiver() throws Exception {