From 61acd2b6f5be6565c72abe7ab2cee4964126d7b0 Mon Sep 17 00:00:00 2001 From: Brian Norman Date: Tue, 27 Jun 2023 16:49:22 +0300 Subject: [PATCH] [FIR] Do not allow context receivers on value classes #KT-59413 Fixed --- .../api/fir/diagnostics/KtFirDataClassConverters.kt | 6 ++++++ .../analysis/api/fir/diagnostics/KtFirDiagnostics.kt | 4 ++++ .../api/fir/diagnostics/KtFirDiagnosticsImpl.kt | 5 +++++ .../generator/diagnostics/FirDiagnosticsList.kt | 1 + .../kotlin/fir/analysis/diagnostics/FirErrors.kt | 1 + .../declaration/FirValueClassDeclarationChecker.kt | 7 +++++-- .../analysis/diagnostics/FirErrorsDefaultMessages.kt | 2 ++ .../noContextReceiversOnValueClasses.fir.kt | 12 ++++++------ 8 files changed, 30 insertions(+), 8 deletions(-) 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 d9e28b1fbc3..661a51782e0 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 @@ -1646,6 +1646,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.VALUE_CLASS_CANNOT_HAVE_CONTEXT_RECEIVERS) { firDiagnostic -> + ValueClassCannotHaveContextReceiversImpl( + firDiagnostic as KtPsiDiagnostic, + token, + ) + } add(FirErrors.ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET) { firDiagnostic -> AnnotationOnIllegalMultiFieldValueClassTypedTargetImpl( firDiagnostic.a, 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 c10be060dfa..bb8105b2a07 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 @@ -1182,6 +1182,10 @@ sealed interface KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = ValueClassCannotBeCloneable::class } + interface ValueClassCannotHaveContextReceivers : KtFirDiagnostic { + override val diagnosticClass get() = ValueClassCannotHaveContextReceivers::class + } + interface AnnotationOnIllegalMultiFieldValueClassTypedTarget : KtFirDiagnostic { override val diagnosticClass get() = AnnotationOnIllegalMultiFieldValueClassTypedTarget::class val name: String 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 cf54946094e..bf95d9c38f5 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 @@ -1419,6 +1419,11 @@ internal class ValueClassCannotBeCloneableImpl( token: KtLifetimeToken, ) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.ValueClassCannotBeCloneable +internal class ValueClassCannotHaveContextReceiversImpl( + firDiagnostic: KtPsiDiagnostic, + token: KtLifetimeToken, +) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.ValueClassCannotHaveContextReceivers + internal class AnnotationOnIllegalMultiFieldValueClassTypedTargetImpl( override val name: String, firDiagnostic: KtPsiDiagnostic, 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 eabb446473c..f3fe43903d0 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 @@ -490,6 +490,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS by error() val INNER_CLASS_INSIDE_VALUE_CLASS by error(PositioningStrategy.INNER_MODIFIER) val VALUE_CLASS_CANNOT_BE_CLONEABLE by error(PositioningStrategy.INLINE_OR_VALUE_MODIFIER) + val VALUE_CLASS_CANNOT_HAVE_CONTEXT_RECEIVERS by error() val ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET by error { parameter("name") } 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 82d09ff151e..1fce6f04b8a 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 @@ -349,6 +349,7 @@ object FirErrors { val TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS by error0() val INNER_CLASS_INSIDE_VALUE_CLASS by error0(SourceElementPositioningStrategies.INNER_MODIFIER) val VALUE_CLASS_CANNOT_BE_CLONEABLE by error0(SourceElementPositioningStrategies.INLINE_OR_VALUE_MODIFIER) + val VALUE_CLASS_CANNOT_HAVE_CONTEXT_RECEIVERS by error0() val ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET by error1() // Applicability diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirValueClassDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirValueClassDeclarationChecker.kt index 337fd28be92..5d11c4982fb 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirValueClassDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirValueClassDeclarationChecker.kt @@ -53,7 +53,10 @@ object FirValueClassDeclarationChecker : FirRegularClassChecker() { reporter.reportOn(declaration.source, FirErrors.VALUE_CLASS_NOT_FINAL, context) } - // TODO check absence of context receivers when FIR infrastructure is ready + if (declaration.contextReceivers.isNotEmpty()) { + reporter.reportOn(declaration.source, FirErrors.VALUE_CLASS_CANNOT_HAVE_CONTEXT_RECEIVERS, context) + } + for (supertypeEntry in declaration.superTypeRefs) { if (supertypeEntry !is FirImplicitAnyTypeRef && supertypeEntry.toRegularClassSymbol(context.session)?.isInterface != true) { @@ -206,7 +209,7 @@ object FirValueClassDeclarationChecker : FirRegularClassChecker() { } declaration.multiFieldValueClassRepresentation != null && primaryConstructorParameter.defaultValue != null -> { - // todo fix when inline arguments are supported + // TODO, KT-50113: Fix when inline arguments are supported. reporter.reportOn( primaryConstructorParameter.defaultValue!!.source, FirErrors.MULTI_FIELD_VALUE_CLASS_PRIMARY_CONSTRUCTOR_DEFAULT_PARAMETER, 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 ad62b106a2b..3050e034c2f 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 @@ -601,6 +601,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_VARARG_ON import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_CANNOT_BE_CLONEABLE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_CANNOT_BE_RECURSIVE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_CANNOT_EXTEND_CLASSES +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_CANNOT_HAVE_CONTEXT_RECEIVERS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_CANNOT_IMPLEMENT_INTERFACE_BY_DELEGATION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_EMPTY_CONSTRUCTOR @@ -1382,6 +1383,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { map.put(TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS, "Type arguments for typed value class equals must all be star projections") 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(VALUE_CLASS_CANNOT_HAVE_CONTEXT_RECEIVERS, "Value classes cannot have context receivers") map.put( ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET, "Annotations on ''{0}'' of multi-field value class type are not supported", diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/noContextReceiversOnValueClasses.fir.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/noContextReceiversOnValueClasses.fir.kt index 96b1dd8f4f9..4854c02eb0e 100644 --- a/compiler/testData/diagnostics/tests/extensions/contextReceivers/noContextReceiversOnValueClasses.fir.kt +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/noContextReceiversOnValueClasses.fir.kt @@ -7,13 +7,13 @@ class A -context(A) -inline class B1(val x: Int) +context(A) +inline class B1(val x: Int) -context(A) +context(A) OPTIONAL_JVM_INLINE_ANNOTATION -value class B2(val x: Int) +value class B2(val x: Int) -context(A) +context(A) OPTIONAL_JVM_INLINE_ANNOTATION -value class C(val x: Int, val y: Int) \ No newline at end of file +value class C(val x: Int, val y: Int)