From 7ab9b68ad55b82bb8aff19b25f53305e006a2c39 Mon Sep 17 00:00:00 2001 From: Anastasiya Shadrina Date: Wed, 3 Nov 2021 19:54:08 +0700 Subject: [PATCH] [FE] Move type-related checks to TypeResolver --- ...CompilerTestFE10TestdataTestGenerated.java | 6 ++++ ...irOldFrontendDiagnosticsTestGenerated.java | 6 ++++ ...DiagnosticsWithLightTreeTestGenerated.java | 6 ++++ .../jetbrains/kotlin/resolve/TypeResolver.kt | 26 ++++++++++++--- .../checkers/ContextualDeclarationChecker.kt | 32 ------------------- .../jetbrains/kotlin/psi/KtFunctionType.java | 9 ++++-- .../contextReceivers/unsupported.fir.kt | 15 +++++++++ .../contextReceivers/unsupported.kt | 15 +++++++++ .../contextReceivers/unsupported.txt | 12 +++++++ .../test/runners/DiagnosticTestGenerated.java | 6 ++++ 10 files changed, 95 insertions(+), 38 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/extensions/contextReceivers/unsupported.fir.kt create mode 100644 compiler/testData/diagnostics/tests/extensions/contextReceivers/unsupported.kt create mode 100644 compiler/testData/diagnostics/tests/extensions/contextReceivers/unsupported.txt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index 809aecd660a..5602232b8b4 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -10726,6 +10726,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/typeParameterizedList.kt"); } + @Test + @TestMetadata("unsupported.kt") + public void testUnsupported() throws Exception { + runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/unsupported.kt"); + } + @Test @TestMetadata("withExplicitReceiver.kt") public void testWithExplicitReceiver() throws Exception { 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 d4e87909c36..dcb27cef464 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 @@ -10726,6 +10726,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/typeParameterizedList.kt"); } + @Test + @TestMetadata("unsupported.kt") + public void testUnsupported() throws Exception { + runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/unsupported.kt"); + } + @Test @TestMetadata("withExplicitReceiver.kt") public void testWithExplicitReceiver() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index 70f546b5b40..b1d87339036 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -10726,6 +10726,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/typeParameterizedList.kt"); } + @Test + @TestMetadata("unsupported.kt") + public void testUnsupported() throws Exception { + runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/unsupported.kt"); + } + @Test @TestMetadata("withExplicitReceiver.kt") public void testWithExplicitReceiver() throws Exception { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt index 8bef3542c1a..827eed5b274 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt @@ -348,10 +348,13 @@ class TypeResolver( val receiverTypeRef = type.receiverTypeReference val receiverType = if (receiverTypeRef?.typeElement == null) null else resolveType(c.noBareTypes(), receiverTypeRef) - val contextReceiversTypeRefs = type.contextReceiversTypeReferences - val contextReceiversTypes = contextReceiversTypeRefs?.mapNotNull { - resolveType(c.noBareTypes(), it) - } ?: emptyList() + val contextReceiverList = type.contextReceiverList + val contextReceiversTypes = if (contextReceiverList != null) { + checkContextReceiversAreEnabled(contextReceiverList) + contextReceiverList.typeReferences().map { typeRef -> + resolveType(c.noBareTypes(), typeRef) + } + } else emptyList() val parameterDescriptors = resolveParametersOfFunctionType(type.parameters) checkParametersOfFunctionType(parameterDescriptors) @@ -430,6 +433,10 @@ class TypeResolver( } } + override fun visitContextReceiverList(contextReceiverList: KtContextReceiverList) { + checkContextReceiversAreEnabled(contextReceiverList) + } + override fun visitDynamicType(type: KtDynamicType) { result = type(dynamicCallableDescriptors.dynamicType.replaceAnnotations(annotations)) if (!dynamicTypesSettings.dynamicTypesAllowed) { @@ -469,6 +476,17 @@ class TypeResolver( c.trace.report(Errors.UNSUPPORTED.on(it, "val or var on parameter in function type")) } } + + private fun checkContextReceiversAreEnabled(contextReceiverList: KtContextReceiverList) { + if (!languageVersionSettings.supportsFeature(LanguageFeature.ContextReceivers)) { + c.trace.report( + UNSUPPORTED_FEATURE.on( + contextReceiverList, + LanguageFeature.ContextReceivers to languageVersionSettings + ) + ) + } + } }) return result ?: type(ErrorUtils.createErrorType(typeElement?.getDebugText() ?: "No type element")) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ContextualDeclarationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ContextualDeclarationChecker.kt index 53a338fb69b..5019143c0ae 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ContextualDeclarationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ContextualDeclarationChecker.kt @@ -26,37 +26,5 @@ object ContextualDeclarationChecker : DeclarationChecker { ) return } - val types = mutableListOf() - when (declaration) { - is KtFunction -> { - types.addAll(declaration.valueParameters.mapNotNull { it.typeReference }) - types.add(declaration.receiverTypeReference) - types.add(declaration.typeReference) - } - is KtProperty -> { - types.add(declaration.receiverTypeReference) - types.add(declaration.typeReference) - } - is KtClass -> { - types.addAll(declaration.primaryConstructor?.valueParameters?.map { it.typeReference } ?: emptyList()) - } - is KtTypeAlias -> { - types.add(declaration.getTypeReference()) - } - } - - fun KtTypeReference.isOrHasContextualType(): Boolean { - val typeElement = typeElement as? KtFunctionType ?: return false - return !typeElement.contextReceiversTypeReferences.isNullOrEmpty() - || typeElement.typeArgumentsAsTypes.any(KtTypeReference::isOrHasContextualType) - } - - types.filterNotNull().filter { it.isOrHasContextualType() }.forEach { - context.trace.report( - Errors.UNSUPPORTED_FEATURE.on( - it, LanguageFeature.ContextReceivers to context.languageVersionSettings - ) - ) - } } } \ No newline at end of file diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtFunctionType.java b/compiler/psi/src/org/jetbrains/kotlin/psi/KtFunctionType.java index 31bbb91aa07..af0d68ba0b1 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/KtFunctionType.java +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtFunctionType.java @@ -93,13 +93,18 @@ public class KtFunctionType extends KtElementImplStub getContextReceiversTypeReferences() { + @Nullable + public KtContextReceiverList getContextReceiverList() { KtFunctionTypeReceiver receiverDeclaration = getReceiver(); if (receiverDeclaration == null) { return null; } KtTypeReference receiverTypeRef = receiverDeclaration.getTypeReference(); - KtContextReceiverList contextReceiverList = receiverTypeRef.getStubOrPsiChild(KtStubElementTypes.CONTEXT_RECEIVER_LIST); + return receiverTypeRef.getStubOrPsiChild(KtStubElementTypes.CONTEXT_RECEIVER_LIST); + } + + public List getContextReceiversTypeReferences() { + KtContextReceiverList contextReceiverList = getContextReceiverList(); if (contextReceiverList != null) { return contextReceiverList.typeReferences(); } else { diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/unsupported.fir.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/unsupported.fir.kt new file mode 100644 index 00000000000..20373298fb5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/unsupported.fir.kt @@ -0,0 +1,15 @@ +// !DIAGNOSTICS: -UNCHECKED_CAST + +context(Any) +fun f(g: context(Any) () -> Unit, value: Any): context(A) () -> Unit { + return value as (context(A) () -> Unit) +} + +context(String, Int) +class A { + context(Any) + val p: Any get() = 42 + + context(String, Int) + fun m() {} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/unsupported.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/unsupported.kt new file mode 100644 index 00000000000..67917bf3580 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/unsupported.kt @@ -0,0 +1,15 @@ +// !DIAGNOSTICS: -UNCHECKED_CAST + +context(Any) +fun f(g: context(Any) () -> Unit, value: Any): context(A) () -> Unit { + return value as (context(A) () -> Unit) +} + +context(String, Int) +class A { + context(Any) + val p: Any get() = 42 + + context(String, Int) + fun m() {} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/unsupported.txt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/unsupported.txt new file mode 100644 index 00000000000..e6fede1945e --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/unsupported.txt @@ -0,0 +1,12 @@ +package + +public fun f(/*0*/ g: context(kotlin.Any) () -> kotlin.Unit, /*1*/ value: kotlin.Any): context(A) () -> kotlin.Unit + +public final class A { + public constructor A() + public final val p: kotlin.Any + 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 final fun m(): kotlin.Unit + public open override /*1*/ /*fake_override*/ 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 e93e8bd7205..6272ac3842c 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 @@ -10732,6 +10732,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/typeParameterizedList.kt"); } + @Test + @TestMetadata("unsupported.kt") + public void testUnsupported() throws Exception { + runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/unsupported.kt"); + } + @Test @TestMetadata("withExplicitReceiver.kt") public void testWithExplicitReceiver() throws Exception {