[FIR] Do not allow context receivers on value classes

#KT-59413 Fixed
This commit is contained in:
Brian Norman
2023-06-27 16:49:22 +03:00
committed by Space Team
parent b74ff19930
commit 61acd2b6f5
8 changed files with 30 additions and 8 deletions
@@ -1646,6 +1646,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token, 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 -> add(FirErrors.ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET) { firDiagnostic ->
AnnotationOnIllegalMultiFieldValueClassTypedTargetImpl( AnnotationOnIllegalMultiFieldValueClassTypedTargetImpl(
firDiagnostic.a, firDiagnostic.a,
@@ -1182,6 +1182,10 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = ValueClassCannotBeCloneable::class override val diagnosticClass get() = ValueClassCannotBeCloneable::class
} }
interface ValueClassCannotHaveContextReceivers : KtFirDiagnostic<KtDeclaration> {
override val diagnosticClass get() = ValueClassCannotHaveContextReceivers::class
}
interface AnnotationOnIllegalMultiFieldValueClassTypedTarget : KtFirDiagnostic<KtAnnotationEntry> { interface AnnotationOnIllegalMultiFieldValueClassTypedTarget : KtFirDiagnostic<KtAnnotationEntry> {
override val diagnosticClass get() = AnnotationOnIllegalMultiFieldValueClassTypedTarget::class override val diagnosticClass get() = AnnotationOnIllegalMultiFieldValueClassTypedTarget::class
val name: String val name: String
@@ -1419,6 +1419,11 @@ internal class ValueClassCannotBeCloneableImpl(
token: KtLifetimeToken, token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<KtDeclaration>(firDiagnostic, token), KtFirDiagnostic.ValueClassCannotBeCloneable ) : KtAbstractFirDiagnostic<KtDeclaration>(firDiagnostic, token), KtFirDiagnostic.ValueClassCannotBeCloneable
internal class ValueClassCannotHaveContextReceiversImpl(
firDiagnostic: KtPsiDiagnostic,
token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<KtDeclaration>(firDiagnostic, token), KtFirDiagnostic.ValueClassCannotHaveContextReceivers
internal class AnnotationOnIllegalMultiFieldValueClassTypedTargetImpl( internal class AnnotationOnIllegalMultiFieldValueClassTypedTargetImpl(
override val name: String, override val name: String,
firDiagnostic: KtPsiDiagnostic, firDiagnostic: KtPsiDiagnostic,
@@ -490,6 +490,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS by error<KtTypeReference>() val TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS by error<KtTypeReference>()
val INNER_CLASS_INSIDE_VALUE_CLASS by error<KtDeclaration>(PositioningStrategy.INNER_MODIFIER) val INNER_CLASS_INSIDE_VALUE_CLASS by error<KtDeclaration>(PositioningStrategy.INNER_MODIFIER)
val VALUE_CLASS_CANNOT_BE_CLONEABLE by error<KtDeclaration>(PositioningStrategy.INLINE_OR_VALUE_MODIFIER) val VALUE_CLASS_CANNOT_BE_CLONEABLE by error<KtDeclaration>(PositioningStrategy.INLINE_OR_VALUE_MODIFIER)
val VALUE_CLASS_CANNOT_HAVE_CONTEXT_RECEIVERS by error<KtDeclaration>()
val ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET by error<KtAnnotationEntry> { val ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET by error<KtAnnotationEntry> {
parameter<String>("name") parameter<String>("name")
} }
@@ -349,6 +349,7 @@ object FirErrors {
val TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS by error0<KtTypeReference>() val TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS by error0<KtTypeReference>()
val INNER_CLASS_INSIDE_VALUE_CLASS by error0<KtDeclaration>(SourceElementPositioningStrategies.INNER_MODIFIER) val INNER_CLASS_INSIDE_VALUE_CLASS by error0<KtDeclaration>(SourceElementPositioningStrategies.INNER_MODIFIER)
val VALUE_CLASS_CANNOT_BE_CLONEABLE by error0<KtDeclaration>(SourceElementPositioningStrategies.INLINE_OR_VALUE_MODIFIER) val VALUE_CLASS_CANNOT_BE_CLONEABLE by error0<KtDeclaration>(SourceElementPositioningStrategies.INLINE_OR_VALUE_MODIFIER)
val VALUE_CLASS_CANNOT_HAVE_CONTEXT_RECEIVERS by error0<KtDeclaration>()
val ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET by error1<KtAnnotationEntry, String>() val ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET by error1<KtAnnotationEntry, String>()
// Applicability // Applicability
@@ -53,7 +53,10 @@ object FirValueClassDeclarationChecker : FirRegularClassChecker() {
reporter.reportOn(declaration.source, FirErrors.VALUE_CLASS_NOT_FINAL, context) 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) { for (supertypeEntry in declaration.superTypeRefs) {
if (supertypeEntry !is FirImplicitAnyTypeRef && supertypeEntry.toRegularClassSymbol(context.session)?.isInterface != true) { if (supertypeEntry !is FirImplicitAnyTypeRef && supertypeEntry.toRegularClassSymbol(context.session)?.isInterface != true) {
@@ -206,7 +209,7 @@ object FirValueClassDeclarationChecker : FirRegularClassChecker() {
} }
declaration.multiFieldValueClassRepresentation != null && primaryConstructorParameter.defaultValue != null -> { declaration.multiFieldValueClassRepresentation != null && primaryConstructorParameter.defaultValue != null -> {
// todo fix when inline arguments are supported // TODO, KT-50113: Fix when inline arguments are supported.
reporter.reportOn( reporter.reportOn(
primaryConstructorParameter.defaultValue!!.source, primaryConstructorParameter.defaultValue!!.source,
FirErrors.MULTI_FIELD_VALUE_CLASS_PRIMARY_CONSTRUCTOR_DEFAULT_PARAMETER, FirErrors.MULTI_FIELD_VALUE_CLASS_PRIMARY_CONSTRUCTOR_DEFAULT_PARAMETER,
@@ -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_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_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_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_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_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_EMPTY_CONSTRUCTOR 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(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(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_BE_CLONEABLE, "Value class cannot be Cloneable")
map.put(VALUE_CLASS_CANNOT_HAVE_CONTEXT_RECEIVERS, "Value classes cannot have context receivers")
map.put( map.put(
ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET, ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET,
"Annotations on ''{0}'' of multi-field value class type are not supported", "Annotations on ''{0}'' of multi-field value class type are not supported",
@@ -7,13 +7,13 @@
class A class A
context(A) <!VALUE_CLASS_CANNOT_HAVE_CONTEXT_RECEIVERS!>context(A)
inline class B1(val x: Int) inline class B1(val x: Int)<!>
context(A) <!VALUE_CLASS_CANNOT_HAVE_CONTEXT_RECEIVERS!>context(A)
OPTIONAL_JVM_INLINE_ANNOTATION OPTIONAL_JVM_INLINE_ANNOTATION
value class B2(val x: Int) value class B2(val x: Int)<!>
context(A) <!VALUE_CLASS_CANNOT_HAVE_CONTEXT_RECEIVERS!>context(A)
OPTIONAL_JVM_INLINE_ANNOTATION OPTIONAL_JVM_INLINE_ANNOTATION
value class C(val x: Int, val y: Int) value class C(val x: Int, val y: Int)<!>