From 91465d7110e46a90ca9aa5c21182e55c2ff15329 Mon Sep 17 00:00:00 2001 From: Tomas Husak Date: Wed, 6 Dec 2023 15:35:43 +0100 Subject: [PATCH] [FIR] KT-59421 add checker context receiver property backing field --- .../diagnostics/KtFirDataClassConverters.kt | 6 ++++ .../api/fir/diagnostics/KtFirDiagnostics.kt | 4 +++ .../fir/diagnostics/KtFirDiagnosticsImpl.kt | 5 ++++ .../diagnostics/FirDiagnosticsList.kt | 1 + .../fir/analysis/diagnostics/FirErrors.kt | 1 + .../FirNonSuppressibleErrorNames.kt | 1 + .../checkers/CommonDeclarationCheckers.kt | 1 + ...extReceiversPropertyBackingFieldChecker.kt | 29 +++++++++++++++++++ .../diagnostics/FirErrorsDefaultMessages.kt | 5 ++++ .../contextReceivers/noBackingField.fir.kt | 17 ----------- .../contextReceivers/noBackingField.kt | 1 + 11 files changed, 54 insertions(+), 17 deletions(-) create mode 100644 compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirContextReceiversPropertyBackingFieldChecker.kt delete mode 100644 compiler/testData/diagnostics/tests/extensions/contextReceivers/noBackingField.fir.kt diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt index d62f08a2619..ce914741392 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -2111,6 +2111,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.CONTEXT_RECEIVERS_WITH_BACKING_FIELD) { firDiagnostic -> + ContextReceiversWithBackingFieldImpl( + firDiagnostic as KtPsiDiagnostic, + token, + ) + } add(FirErrors.RECURSION_IN_IMPLICIT_TYPES) { firDiagnostic -> RecursionInImplicitTypesImpl( firDiagnostic as KtPsiDiagnostic, diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt index 38ade7eae77..ffe0cee30c6 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt @@ -1504,6 +1504,10 @@ sealed interface KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = SubtypingBetweenContextReceivers::class } + interface ContextReceiversWithBackingField : KtFirDiagnostic { + override val diagnosticClass get() = ContextReceiversWithBackingField::class + } + interface RecursionInImplicitTypes : KtFirDiagnostic { override val diagnosticClass get() = RecursionInImplicitTypes::class } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 668dfbc7cbd..fd29b283c5c 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -1805,6 +1805,11 @@ internal class SubtypingBetweenContextReceiversImpl( token: KtLifetimeToken, ) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.SubtypingBetweenContextReceivers +internal class ContextReceiversWithBackingFieldImpl( + firDiagnostic: KtPsiDiagnostic, + token: KtLifetimeToken, +) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.ContextReceiversWithBackingField + internal class RecursionInImplicitTypesImpl( firDiagnostic: KtPsiDiagnostic, token: KtLifetimeToken, diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index a6110a4b8fc..8b754fc57ce 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -676,6 +676,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val AMBIGUOUS_CALL_WITH_IMPLICIT_CONTEXT_RECEIVER by error(PositioningStrategy.REFERENCE_BY_QUALIFIED) val UNSUPPORTED_CONTEXTUAL_DECLARATION_CALL by error(PositioningStrategy.NAME_IDENTIFIER) val SUBTYPING_BETWEEN_CONTEXT_RECEIVERS by error(PositioningStrategy.DEFAULT) + val CONTEXT_RECEIVERS_WITH_BACKING_FIELD by error(PositioningStrategy.DEFAULT) } val TYPES_AND_TYPE_PARAMETERS by object : DiagnosticGroup("Types & type parameters") { diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index f77d6f5f155..e80d3ad2c88 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -425,6 +425,7 @@ object FirErrors { val AMBIGUOUS_CALL_WITH_IMPLICIT_CONTEXT_RECEIVER: KtDiagnosticFactory0 by error0(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) val UNSUPPORTED_CONTEXTUAL_DECLARATION_CALL: KtDiagnosticFactory0 by error0(SourceElementPositioningStrategies.NAME_IDENTIFIER) val SUBTYPING_BETWEEN_CONTEXT_RECEIVERS: KtDiagnosticFactory0 by error0() + val CONTEXT_RECEIVERS_WITH_BACKING_FIELD: KtDiagnosticFactory0 by error0() // Types & type parameters val RECURSION_IN_IMPLICIT_TYPES: KtDiagnosticFactory0 by error0() diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirNonSuppressibleErrorNames.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirNonSuppressibleErrorNames.kt index 48bbe0dc034..1ade479426b 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirNonSuppressibleErrorNames.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirNonSuppressibleErrorNames.kt @@ -264,6 +264,7 @@ val FIR_NON_SUPPRESSIBLE_ERROR_NAMES: Set = setOf( "AMBIGUOUS_CALL_WITH_IMPLICIT_CONTEXT_RECEIVER", "UNSUPPORTED_CONTEXTUAL_DECLARATION_CALL", "SUBTYPING_BETWEEN_CONTEXT_RECEIVERS", + "CONTEXT_RECEIVERS_WITH_BACKING_FIELD", "RECURSION_IN_IMPLICIT_TYPES", "INFERENCE_ERROR", "PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT", diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt index 00bf92e9c6a..f14da240e33 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt @@ -91,6 +91,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() { ContractSyntaxV2PropertyChecker, FirVolatileAnnotationChecker, FirInlinePropertyChecker, + FirContextReceiversPropertyBackingFieldChecker ) override val backingFieldCheckers: Set diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirContextReceiversPropertyBackingFieldChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirContextReceiversPropertyBackingFieldChecker.kt new file mode 100644 index 00000000000..043a57afcc9 --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirContextReceiversPropertyBackingFieldChecker.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.analysis.checkers.declaration + +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors +import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.fir.declarations.utils.hasBackingField + +object FirContextReceiversPropertyBackingFieldChecker : FirPropertyChecker() { + override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) { + if (!context.languageVersionSettings.supportsFeature(LanguageFeature.ContextReceivers)) return + if (declaration.contextReceivers.isEmpty()) return + + if (declaration.hasBackingField) { + reporter.reportOn( + declaration.initializer?.source, + FirErrors.CONTEXT_RECEIVERS_WITH_BACKING_FIELD, + context + ) + } + } +} \ No newline at end of file diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt index 8c49776779d..45f6b9706f5 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt @@ -154,6 +154,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITHOUT import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_DELEGATE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_GETTER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_NON_CONST_INITIALIZER +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONTEXT_RECEIVERS_WITH_BACKING_FIELD import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONTRACT_NOT_ALLOWED import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLE_IN_ANNOTATION_PARAMETER @@ -1282,6 +1283,10 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { SUBTYPING_BETWEEN_CONTEXT_RECEIVERS, "Subtyping relation between context receivers is prohibited." ) + map.put( + CONTEXT_RECEIVERS_WITH_BACKING_FIELD, + "Property with context receivers cannot be initialized because it has no backing field." + ) // Ambiguity map.put(OVERLOAD_RESOLUTION_AMBIGUITY, "Overload resolution ambiguity between candidates: {0}", SYMBOLS) diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/noBackingField.fir.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/noBackingField.fir.kt deleted file mode 100644 index 4be7bda1df3..00000000000 --- a/compiler/testData/diagnostics/tests/extensions/contextReceivers/noBackingField.fir.kt +++ /dev/null @@ -1,17 +0,0 @@ -// !LANGUAGE: +ContextReceivers - -interface A { - fun a(): Int -} -interface B { - fun b(): Int -} - -context(A) -val a = 1 - -context(A, B) -var b = 2 - -context(A, B) -val c get() = a() + b() diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/noBackingField.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/noBackingField.kt index 31bff9ecd5f..ac18f8cf91d 100644 --- a/compiler/testData/diagnostics/tests/extensions/contextReceivers/noBackingField.kt +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/noBackingField.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: +ContextReceivers interface A {